]> granicus.if.org Git - python/commitdiff
Trent Mick <trentm@activestate.com>:
authorFred Drake <fdrake@acm.org>
Fri, 30 Jun 2000 16:18:57 +0000 (16:18 +0000)
committerFred Drake <fdrake@acm.org>
Fri, 30 Jun 2000 16:18:57 +0000 (16:18 +0000)
This patch fixes possible overflow in the use of
PyOS_GetLastModificationTime in getmtime.c and Python/import.c.

Currently PyOS_GetLastModificationTime returns a C long. This can
overflow on Win64 where sizeof(time_t) > sizeof(long). Besides it
should logically return a time_t anyway (this patch changes this).

As well, import.c uses PyOS_GetLastModificationTime for .pyc
timestamping.  There has been recent discussion about the .pyc header
format on python-dev.  This patch adds oveflow checking to import.c so
that an exception will be raised if the modification time
overflows. There are a few other minor 64-bit readiness changes made
to the module as well:

- size_t instead of int or long for function-local buffer and string
length variables

- one buffer overflow check was added (raises an exception on possible
overflow, this overflow chance exists on 32-bit platforms as well), no
other possible buffer overflows existed (from my analysis anyway)

Closes SourceForge patch #100509.

Python/getmtime.c
Python/import.c

index 4bf2adfaa4619b4958593e0f3824c0b999f5cd80..aea69094c8a29d9b6c64c2cc683a1a8c31c5da9b 100644 (file)
@@ -33,13 +33,14 @@ PERFORMANCE OF THIS SOFTWARE.
 
 /* (A separate file because this may be OS dependent) */
 
+#include "Python.h"
 #include "config.h"
 
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
-long
+time_t
 PyOS_GetLastModificationTime(path, fp)
        char *path;
        FILE *fp;
index a23b71b43d3a2b872339d389733bba9adacea21d..ede6cb68d99ed5ad14852ef1035d0273b4adab44 100644 (file)
@@ -74,7 +74,7 @@ PERFORMANCE OF THIS SOFTWARE.
 #endif
 
 
-extern long PyOS_GetLastModificationTime(); /* In getmtime.c */
+extern time_t PyOS_GetLastModificationTime(); /* In getmtime.c */
 
 /* Magic word to reject .pyc files generated by other Python versions */
 /* Change for each incompatible change */
@@ -549,9 +549,9 @@ static char *
 make_compiled_pathname(pathname, buf, buflen)
        char *pathname;
        char *buf;
-       int buflen;
+       size_t buflen;
 {
-       int len;
+       size_t len;
 
        len = strlen(pathname);
        if (len+2 > buflen)
@@ -732,7 +732,7 @@ load_source_module(name, pathname, fp)
        char *pathname;
        FILE *fp;
 {
-       long mtime;
+       time_t mtime;
        FILE *fpc;
        char buf[MAXPATHLEN+1];
        char *cpathname;
@@ -740,7 +740,20 @@ load_source_module(name, pathname, fp)
        PyObject *m;
 
        mtime = PyOS_GetLastModificationTime(pathname, fp);
-       cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1);
+       if (mtime == -1)
+               return NULL;
+#if SIZEOF_TIME_T > 4
+       /* Python's .pyc timestamp handling presumes that the timestamp fits
+          in 4 bytes. This will be fine until sometime in the year 2038,
+          when a 4-byte signed time_t will overflow.
+        */
+       if (mtime >> 32) {
+               PyErr_SetString(PyExc_OverflowError,
+                       "modification time overflows a 4 bytes");
+               return NULL;
+       }
+#endif
+       cpathname = make_compiled_pathname(pathname, buf, (size_t)MAXPATHLEN+1);
        if (cpathname != NULL &&
            (fpc = check_compiled_module(pathname, mtime, cpathname))) {
                co = read_compiled_module(cpathname, fpc);
@@ -771,7 +784,7 @@ load_source_module(name, pathname, fp)
 /* Forward */
 static PyObject *load_module Py_PROTO((char *, FILE *, char *, int));
 static struct filedescr *find_module Py_PROTO((char *, PyObject *,
-                                              char *, int, FILE **));
+                                              char *, size_t, FILE **));
 static struct _frozen *find_frozen Py_PROTO((char *name));
 
 /* Load a package and return its module object WITH INCREMENTED
@@ -869,10 +882,11 @@ find_module(realname, path, buf, buflen, p_fp)
        PyObject *path;
        /* Output parameters: */
        char *buf;
-       int buflen;
+       size_t buflen;
        FILE **p_fp;
 {
-       int i, npath, len, namelen;
+       int i, npath;
+       size_t len, namelen;
        struct _frozen *f;
        struct filedescr *fdp = NULL;
        FILE *fp = NULL;
@@ -882,6 +896,10 @@ find_module(realname, path, buf, buflen, p_fp)
        static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
        char name[MAXPATHLEN+1];
 
+       if (strlen(realname) > MAXPATHLEN) {
+               PyErr_SetString(PyExc_OverflowError, "module name is too long");
+               return NULL;
+       }
        strcpy(name, realname);
 
        if (path != NULL && PyString_Check(path)) {
@@ -933,7 +951,7 @@ find_module(realname, path, buf, buflen, p_fp)
                if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen)
                        continue; /* Too long */
                strcpy(buf, PyString_AsString(v));
-               if ((int)strlen(buf) != len)
+               if (strlen(buf) != len)
                        continue; /* v contains '\0' */
 #ifdef macintosh
 #ifdef INTERN_STRINGS
@@ -1181,8 +1199,8 @@ static int
 find_init_module(buf)
        char *buf;
 {
-       int save_len = strlen(buf);
-       int i = save_len;
+       size_t save_len = strlen(buf);
+       size_t i = save_len;
        struct stat statbuf;
 
        if (save_len + 13 >= MAXPATHLEN)
@@ -1577,7 +1595,7 @@ get_parent(globals, buf, p_buflen)
        else {
                char *start = PyString_AS_STRING(modname);
                char *lastdot = strrchr(start, '.');
-               int len;
+               size_t len;
                if (lastdot == NULL)
                        return Py_None;
                len = lastdot - start;
@@ -1612,7 +1630,7 @@ load_next(mod, altmod, p_name, buf, p_buflen)
 {
        char *name = *p_name;
        char *dot = strchr(name, '.');
-       int len;
+       size_t len;
        char *p;
        PyObject *result;