SF bug #495021: Crash calling os.stat with a trailing backslash
Patch from Mark Hammond, plus code rearrangement and comments from me. posix_do_stat(): Windows-specific code could try to free() stack memory in some cases when a path ending with a forward or backward slash was passed to os.stat().
This commit is contained in:
parent
04a866170d
commit
500bd035fa
|
@ -679,7 +679,8 @@ posix_do_stat(PyObject *self, PyObject *args, char *format,
|
|||
int (*statfunc)(const char *, STRUCT_STAT *))
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
char *path = NULL;
|
||||
char *path = NULL; /* pass this to stat; do not free() it */
|
||||
char *pathfree = NULL; /* this memory must be free'd */
|
||||
int res;
|
||||
|
||||
#ifdef MS_WIN32
|
||||
|
@ -690,25 +691,30 @@ posix_do_stat(PyObject *self, PyObject *args, char *format,
|
|||
if (!PyArg_ParseTuple(args, format,
|
||||
Py_FileSystemDefaultEncoding, &path))
|
||||
return NULL;
|
||||
pathfree = path;
|
||||
|
||||
#ifdef MS_WIN32
|
||||
pathlen = strlen(path);
|
||||
/* the library call can blow up if the file name is too long! */
|
||||
if (pathlen > MAX_PATH) {
|
||||
PyMem_Free(path);
|
||||
PyMem_Free(pathfree);
|
||||
errno = ENAMETOOLONG;
|
||||
return posix_error();
|
||||
}
|
||||
|
||||
if ((pathlen > 0) && (path[pathlen-1] == '\\' || path[pathlen-1] == '/')) {
|
||||
/* exception for specific or current drive root */
|
||||
if (!((pathlen == 1) ||
|
||||
((pathlen == 3) &&
|
||||
(path[1] == ':') &&
|
||||
(path[2] == '\\' || path[2] == '/'))))
|
||||
{
|
||||
/* Remove trailing slash or backslash, unless it's the current
|
||||
drive root (/ or \) or a specific drive's root (like c:\ or c:/).
|
||||
*/
|
||||
if (pathlen > 0 &&
|
||||
(path[pathlen-1]== '\\' || path[pathlen-1] == '/')) {
|
||||
/* It does end with a slash -- exempt the root drive cases. */
|
||||
/* XXX UNC root drives should also be exempted? */
|
||||
if (pathlen == 1 || (pathlen == 3 && path[1] == ':'))
|
||||
/* leave it alone */;
|
||||
else {
|
||||
/* nuke the trailing backslash */
|
||||
strncpy(pathcopy, path, pathlen);
|
||||
pathcopy[pathlen-1] = '\0'; /* nuke the trailing backslash */
|
||||
pathcopy[pathlen-1] = '\0';
|
||||
path = pathcopy;
|
||||
}
|
||||
}
|
||||
|
@ -718,9 +724,9 @@ posix_do_stat(PyObject *self, PyObject *args, char *format,
|
|||
res = (*statfunc)(path, &st);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (res != 0)
|
||||
return posix_error_with_allocated_filename(path);
|
||||
return posix_error_with_allocated_filename(pathfree);
|
||||
|
||||
PyMem_Free(path);
|
||||
PyMem_Free(pathfree);
|
||||
return _pystat_fromstructstat(st);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue