summaryrefslogtreecommitdiffstats
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-12-19 19:05:01 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-12-19 19:05:01 (GMT)
commit500bd035fa09ab27013d197030feb01f620a194c (patch)
treeac1a44b8b95cc638d131f9dbc0a5f06bbaaad512 /Modules/posixmodule.c
parent04a866170dcad6a4e806fedca0d5e38ebe11867b (diff)
downloadcpython-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/posixmodule.c')
-rw-r--r--Modules/posixmodule.c34
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);
}