diff options
author | Fred Drake <fdrake@acm.org> | 2000-06-30 16:18:57 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2000-06-30 16:18:57 (GMT) |
commit | 4c82b2366ff2eb38f062fc5da1b15ddd1c01fa4b (patch) | |
tree | 9706525a1647754a3d5aed1ba183b4544acaaebe /Python/import.c | |
parent | 4358b2c928e756a77613da7cb8c57676e8872935 (diff) | |
download | cpython-4c82b2366ff2eb38f062fc5da1b15ddd1c01fa4b.zip cpython-4c82b2366ff2eb38f062fc5da1b15ddd1c01fa4b.tar.gz cpython-4c82b2366ff2eb38f062fc5da1b15ddd1c01fa4b.tar.bz2 |
Trent Mick <trentm@activestate.com>:
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.
Diffstat (limited to 'Python/import.c')
-rw-r--r-- | Python/import.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/Python/import.c b/Python/import.c index a23b71b..ede6cb6 100644 --- a/Python/import.c +++ b/Python/import.c @@ -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; |