mirror of
https://github.com/python/cpython.git
synced 2025-07-22 18:55:22 +00:00
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
1 changed files with 20 additions and 14 deletions
|
@ -679,7 +679,8 @@ posix_do_stat(PyObject *self, PyObject *args, char *format,
|
||||||
int (*statfunc)(const char *, STRUCT_STAT *))
|
int (*statfunc)(const char *, STRUCT_STAT *))
|
||||||
{
|
{
|
||||||
STRUCT_STAT st;
|
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;
|
int res;
|
||||||
|
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
|
@ -690,25 +691,30 @@ posix_do_stat(PyObject *self, PyObject *args, char *format,
|
||||||
if (!PyArg_ParseTuple(args, format,
|
if (!PyArg_ParseTuple(args, format,
|
||||||
Py_FileSystemDefaultEncoding, &path))
|
Py_FileSystemDefaultEncoding, &path))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
pathfree = path;
|
||||||
|
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
pathlen = strlen(path);
|
pathlen = strlen(path);
|
||||||
/* the library call can blow up if the file name is too long! */
|
/* the library call can blow up if the file name is too long! */
|
||||||
if (pathlen > MAX_PATH) {
|
if (pathlen > MAX_PATH) {
|
||||||
PyMem_Free(path);
|
PyMem_Free(pathfree);
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return posix_error();
|
return posix_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pathlen > 0) && (path[pathlen-1] == '\\' || path[pathlen-1] == '/')) {
|
/* Remove trailing slash or backslash, unless it's the current
|
||||||
/* exception for specific or current drive root */
|
drive root (/ or \) or a specific drive's root (like c:\ or c:/).
|
||||||
if (!((pathlen == 1) ||
|
*/
|
||||||
((pathlen == 3) &&
|
if (pathlen > 0 &&
|
||||||
(path[1] == ':') &&
|
(path[pathlen-1]== '\\' || path[pathlen-1] == '/')) {
|
||||||
(path[2] == '\\' || path[2] == '/'))))
|
/* 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);
|
strncpy(pathcopy, path, pathlen);
|
||||||
pathcopy[pathlen-1] = '\0'; /* nuke the trailing backslash */
|
pathcopy[pathlen-1] = '\0';
|
||||||
path = pathcopy;
|
path = pathcopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -718,9 +724,9 @@ posix_do_stat(PyObject *self, PyObject *args, char *format,
|
||||||
res = (*statfunc)(path, &st);
|
res = (*statfunc)(path, &st);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
if (res != 0)
|
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);
|
return _pystat_fromstructstat(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue