[Python-checkins] CVS: python/dist/src/Python getmtime.c,2.9,2.10 import.c,2.135,2.136

Fred L. Drake python-dev@python.org
Fri, 30 Jun 2000 09:18:59 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory slayer.i.sourceforge.net:/tmp/cvs-serv31939

Modified Files:
	getmtime.c import.c 
Log Message:
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.


Index: getmtime.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/getmtime.c,v
retrieving revision 2.9
retrieving revision 2.10
diff -C2 -r2.9 -r2.10
*** getmtime.c	1997/09/05 07:33:15	2.9
--- getmtime.c	2000/06/30 16:18:57	2.10
***************
*** 34,37 ****
--- 34,38 ----
  /* (A separate file because this may be OS dependent) */
  
+ #include "Python.h"
  #include "config.h"
  
***************
*** 40,44 ****
  #include <sys/stat.h>
  
! long
  PyOS_GetLastModificationTime(path, fp)
  	char *path;
--- 41,45 ----
  #include <sys/stat.h>
  
! time_t
  PyOS_GetLastModificationTime(path, fp)
  	char *path;

Index: import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.135
retrieving revision 2.136
diff -C2 -r2.135 -r2.136
*** import.c	2000/06/30 04:59:17	2.135
--- import.c	2000/06/30 16:18:57	2.136
***************
*** 75,79 ****
  
  
! extern long PyOS_GetLastModificationTime(); /* In getmtime.c */
  
  /* Magic word to reject .pyc files generated by other Python versions */
--- 75,79 ----
  
  
! extern time_t PyOS_GetLastModificationTime(); /* In getmtime.c */
  
  /* Magic word to reject .pyc files generated by other Python versions */
***************
*** 550,556 ****
  	char *pathname;
  	char *buf;
! 	int buflen;
  {
! 	int len;
  
  	len = strlen(pathname);
--- 550,556 ----
  	char *pathname;
  	char *buf;
! 	size_t buflen;
  {
! 	size_t len;
  
  	len = strlen(pathname);
***************
*** 733,737 ****
  	FILE *fp;
  {
! 	long mtime;
  	FILE *fpc;
  	char buf[MAXPATHLEN+1];
--- 733,737 ----
  	FILE *fp;
  {
! 	time_t mtime;
  	FILE *fpc;
  	char buf[MAXPATHLEN+1];
***************
*** 741,745 ****
  
  	mtime = PyOS_GetLastModificationTime(pathname, fp);
! 	cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1);
  	if (cpathname != NULL &&
  	    (fpc = check_compiled_module(pathname, mtime, cpathname))) {
--- 741,758 ----
  
  	mtime = PyOS_GetLastModificationTime(pathname, fp);
! 	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))) {
***************
*** 772,776 ****
  static PyObject *load_module Py_PROTO((char *, FILE *, char *, int));
  static struct filedescr *find_module Py_PROTO((char *, PyObject *,
! 					       char *, int, FILE **));
  static struct _frozen *find_frozen Py_PROTO((char *name));
  
--- 785,789 ----
  static PyObject *load_module Py_PROTO((char *, FILE *, char *, int));
  static struct filedescr *find_module Py_PROTO((char *, PyObject *,
! 					       char *, size_t, FILE **));
  static struct _frozen *find_frozen Py_PROTO((char *name));
  
***************
*** 870,877 ****
  	/* Output parameters: */
  	char *buf;
! 	int buflen;
  	FILE **p_fp;
  {
! 	int i, npath, len, namelen;
  	struct _frozen *f;
  	struct filedescr *fdp = NULL;
--- 883,891 ----
  	/* Output parameters: */
  	char *buf;
! 	size_t buflen;
  	FILE **p_fp;
  {
! 	int i, npath;
! 	size_t len, namelen;
  	struct _frozen *f;
  	struct filedescr *fdp = NULL;
***************
*** 883,886 ****
--- 897,904 ----
  	char name[MAXPATHLEN+1];
  
+ 	if (strlen(realname) > MAXPATHLEN) {
+ 		PyErr_SetString(PyExc_OverflowError, "module name is too long");
+ 		return NULL;
+ 	}
  	strcpy(name, realname);
  
***************
*** 934,938 ****
  			continue; /* Too long */
  		strcpy(buf, PyString_AsString(v));
! 		if ((int)strlen(buf) != len)
  			continue; /* v contains '\0' */
  #ifdef macintosh
--- 952,956 ----
  			continue; /* Too long */
  		strcpy(buf, PyString_AsString(v));
! 		if (strlen(buf) != len)
  			continue; /* v contains '\0' */
  #ifdef macintosh
***************
*** 1182,1187 ****
  	char *buf;
  {
! 	int save_len = strlen(buf);
! 	int i = save_len;
  	struct stat statbuf;
  
--- 1200,1205 ----
  	char *buf;
  {
! 	size_t save_len = strlen(buf);
! 	size_t i = save_len;
  	struct stat statbuf;
  
***************
*** 1578,1582 ****
  		char *start = PyString_AS_STRING(modname);
  		char *lastdot = strrchr(start, '.');
! 		int len;
  		if (lastdot == NULL)
  			return Py_None;
--- 1596,1600 ----
  		char *start = PyString_AS_STRING(modname);
  		char *lastdot = strrchr(start, '.');
! 		size_t len;
  		if (lastdot == NULL)
  			return Py_None;
***************
*** 1613,1617 ****
  	char *name = *p_name;
  	char *dot = strchr(name, '.');
! 	int len;
  	char *p;
  	PyObject *result;
--- 1631,1635 ----
  	char *name = *p_name;
  	char *dot = strchr(name, '.');
! 	size_t len;
  	char *p;
  	PyObject *result;