mirror of
https://github.com/python/cpython.git
synced 2025-08-03 00:23:06 +00:00
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.
This commit is contained in:
parent
4358b2c928
commit
4c82b2366f
2 changed files with 33 additions and 14 deletions
|
@ -33,13 +33,14 @@ PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
/* (A separate file because this may be OS dependent) */
|
/* (A separate file because this may be OS dependent) */
|
||||||
|
|
||||||
|
#include "Python.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
long
|
time_t
|
||||||
PyOS_GetLastModificationTime(path, fp)
|
PyOS_GetLastModificationTime(path, fp)
|
||||||
char *path;
|
char *path;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
|
@ -74,7 +74,7 @@ PERFORMANCE OF THIS SOFTWARE.
|
||||||
#endif
|
#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 */
|
/* Magic word to reject .pyc files generated by other Python versions */
|
||||||
/* Change for each incompatible change */
|
/* Change for each incompatible change */
|
||||||
|
@ -549,9 +549,9 @@ static char *
|
||||||
make_compiled_pathname(pathname, buf, buflen)
|
make_compiled_pathname(pathname, buf, buflen)
|
||||||
char *pathname;
|
char *pathname;
|
||||||
char *buf;
|
char *buf;
|
||||||
int buflen;
|
size_t buflen;
|
||||||
{
|
{
|
||||||
int len;
|
size_t len;
|
||||||
|
|
||||||
len = strlen(pathname);
|
len = strlen(pathname);
|
||||||
if (len+2 > buflen)
|
if (len+2 > buflen)
|
||||||
|
@ -732,7 +732,7 @@ load_source_module(name, pathname, fp)
|
||||||
char *pathname;
|
char *pathname;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
{
|
{
|
||||||
long mtime;
|
time_t mtime;
|
||||||
FILE *fpc;
|
FILE *fpc;
|
||||||
char buf[MAXPATHLEN+1];
|
char buf[MAXPATHLEN+1];
|
||||||
char *cpathname;
|
char *cpathname;
|
||||||
|
@ -740,7 +740,20 @@ load_source_module(name, pathname, fp)
|
||||||
PyObject *m;
|
PyObject *m;
|
||||||
|
|
||||||
mtime = PyOS_GetLastModificationTime(pathname, fp);
|
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 &&
|
if (cpathname != NULL &&
|
||||||
(fpc = check_compiled_module(pathname, mtime, cpathname))) {
|
(fpc = check_compiled_module(pathname, mtime, cpathname))) {
|
||||||
co = read_compiled_module(cpathname, fpc);
|
co = read_compiled_module(cpathname, fpc);
|
||||||
|
@ -771,7 +784,7 @@ load_source_module(name, pathname, fp)
|
||||||
/* Forward */
|
/* Forward */
|
||||||
static PyObject *load_module Py_PROTO((char *, FILE *, char *, int));
|
static PyObject *load_module Py_PROTO((char *, FILE *, char *, int));
|
||||||
static struct filedescr *find_module Py_PROTO((char *, PyObject *,
|
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));
|
static struct _frozen *find_frozen Py_PROTO((char *name));
|
||||||
|
|
||||||
/* Load a package and return its module object WITH INCREMENTED
|
/* Load a package and return its module object WITH INCREMENTED
|
||||||
|
@ -869,10 +882,11 @@ find_module(realname, path, buf, buflen, p_fp)
|
||||||
PyObject *path;
|
PyObject *path;
|
||||||
/* Output parameters: */
|
/* Output parameters: */
|
||||||
char *buf;
|
char *buf;
|
||||||
int buflen;
|
size_t buflen;
|
||||||
FILE **p_fp;
|
FILE **p_fp;
|
||||||
{
|
{
|
||||||
int i, npath, len, namelen;
|
int i, npath;
|
||||||
|
size_t len, namelen;
|
||||||
struct _frozen *f;
|
struct _frozen *f;
|
||||||
struct filedescr *fdp = NULL;
|
struct filedescr *fdp = NULL;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
@ -882,6 +896,10 @@ find_module(realname, path, buf, buflen, p_fp)
|
||||||
static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
|
static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
|
||||||
char name[MAXPATHLEN+1];
|
char name[MAXPATHLEN+1];
|
||||||
|
|
||||||
|
if (strlen(realname) > MAXPATHLEN) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError, "module name is too long");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
strcpy(name, realname);
|
strcpy(name, realname);
|
||||||
|
|
||||||
if (path != NULL && PyString_Check(path)) {
|
if (path != NULL && PyString_Check(path)) {
|
||||||
|
@ -933,7 +951,7 @@ find_module(realname, path, buf, buflen, p_fp)
|
||||||
if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen)
|
if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen)
|
||||||
continue; /* Too long */
|
continue; /* Too long */
|
||||||
strcpy(buf, PyString_AsString(v));
|
strcpy(buf, PyString_AsString(v));
|
||||||
if ((int)strlen(buf) != len)
|
if (strlen(buf) != len)
|
||||||
continue; /* v contains '\0' */
|
continue; /* v contains '\0' */
|
||||||
#ifdef macintosh
|
#ifdef macintosh
|
||||||
#ifdef INTERN_STRINGS
|
#ifdef INTERN_STRINGS
|
||||||
|
@ -1181,8 +1199,8 @@ static int
|
||||||
find_init_module(buf)
|
find_init_module(buf)
|
||||||
char *buf;
|
char *buf;
|
||||||
{
|
{
|
||||||
int save_len = strlen(buf);
|
size_t save_len = strlen(buf);
|
||||||
int i = save_len;
|
size_t i = save_len;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
if (save_len + 13 >= MAXPATHLEN)
|
if (save_len + 13 >= MAXPATHLEN)
|
||||||
|
@ -1577,7 +1595,7 @@ get_parent(globals, buf, p_buflen)
|
||||||
else {
|
else {
|
||||||
char *start = PyString_AS_STRING(modname);
|
char *start = PyString_AS_STRING(modname);
|
||||||
char *lastdot = strrchr(start, '.');
|
char *lastdot = strrchr(start, '.');
|
||||||
int len;
|
size_t len;
|
||||||
if (lastdot == NULL)
|
if (lastdot == NULL)
|
||||||
return Py_None;
|
return Py_None;
|
||||||
len = lastdot - start;
|
len = lastdot - start;
|
||||||
|
@ -1612,7 +1630,7 @@ load_next(mod, altmod, p_name, buf, p_buflen)
|
||||||
{
|
{
|
||||||
char *name = *p_name;
|
char *name = *p_name;
|
||||||
char *dot = strchr(name, '.');
|
char *dot = strchr(name, '.');
|
||||||
int len;
|
size_t len;
|
||||||
char *p;
|
char *p;
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue