diff options
author | Tim Peters <tim.peters@gmail.com> | 2001-12-19 19:05:01 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2001-12-19 19:05:01 (GMT) |
commit | 500bd035fa09ab27013d197030feb01f620a194c (patch) | |
tree | ac1a44b8b95cc638d131f9dbc0a5f06bbaaad512 /Modules | |
parent | 04a866170dcad6a4e806fedca0d5e38ebe11867b (diff) | |
download | cpython-500bd035fa09ab27013d197030feb01f620a194c.zip cpython-500bd035fa09ab27013d197030feb01f620a194c.tar.gz cpython-500bd035fa09ab27013d197030feb01f620a194c.tar.bz2 |
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().
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/posixmodule.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 08b0c46..a7ec442 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -679,36 +679,42 @@ 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 - int pathlen; - char pathcopy[MAX_PATH]; + int pathlen; + char pathcopy[MAX_PATH]; #endif /* MS_WIN32 */ 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); } |