From 60a60677093e2792439c9e34debe6d55feead63f Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 22 Jul 2013 12:53:32 +0200 Subject: [PATCH] Issue #15905: Fix theoretical buffer overflow in handling of sys.argv[0], prefix and exec_prefix if the operation system does not obey MAXPATHLEN. --- Misc/NEWS | 3 +++ Modules/getpath.c | 16 ++++++++++++---- Python/sysmodule.c | 7 ++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 3092e323bff..2b28991c514 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 3.3.3 release candidate 1? Core and Builtins ----------------- +- Issue #15905: Fix theoretical buffer overflow in handling of sys.argv[0], + prefix and exec_prefix if the operation system does not obey MAXPATHLEN. + - Issue #18344: Fix potential ref-leaks in _bufferedreader_read_all(). - Issue #17872: Fix a segfault in marshal.load() when input stream returns diff --git a/Modules/getpath.c b/Modules/getpath.c index b98c52012d7..ff14fdd6cd3 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -326,6 +326,7 @@ search_for_prefix(wchar_t *argv0_path, wchar_t *home, wchar_t *_prefix) if (home) { wchar_t *delim; wcsncpy(prefix, home, MAXPATHLEN); + prefix[MAXPATHLEN] = L'\0'; delim = wcschr(prefix, DELIM); if (delim) *delim = L'\0'; @@ -335,13 +336,15 @@ search_for_prefix(wchar_t *argv0_path, wchar_t *home, wchar_t *_prefix) } /* Check to see if argv[0] is in the build directory */ - wcscpy(prefix, argv0_path); + wcsncpy(prefix, argv0_path, MAXPATHLEN); + prefix[MAXPATHLEN] = L'\0'; joinpath(prefix, L"Modules/Setup"); if (isfile(prefix)) { /* Check VPATH to see if argv0_path is in the build directory. */ vpath = _Py_char2wchar(VPATH, NULL); if (vpath != NULL) { - wcscpy(prefix, argv0_path); + wcsncpy(prefix, argv0_path, MAXPATHLEN); + prefix[MAXPATHLEN] = L'\0'; joinpath(prefix, vpath); PyMem_Free(vpath); joinpath(prefix, L"Lib"); @@ -365,6 +368,7 @@ search_for_prefix(wchar_t *argv0_path, wchar_t *home, wchar_t *_prefix) /* Look at configure's PREFIX */ wcsncpy(prefix, _prefix, MAXPATHLEN); + prefix[MAXPATHLEN] = L'\0'; joinpath(prefix, lib_python); joinpath(prefix, LANDMARK); if (ismodule(prefix)) @@ -391,6 +395,7 @@ search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home, wchar_t *_exec_prefix wcsncpy(exec_prefix, delim+1, MAXPATHLEN); else wcsncpy(exec_prefix, home, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, lib_python); joinpath(exec_prefix, L"lib-dynload"); return 1; @@ -399,7 +404,8 @@ search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home, wchar_t *_exec_prefix /* Check to see if argv[0] is in the build directory. "pybuilddir.txt" is written by setup.py and contains the relative path to the location of shared library modules. */ - wcscpy(exec_prefix, argv0_path); + wcsncpy(exec_prefix, argv0_path, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, L"pybuilddir.txt"); if (isfile(exec_prefix)) { FILE *f = _Py_wfopen(exec_prefix, L"rb"); @@ -420,7 +426,8 @@ search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home, wchar_t *_exec_prefix Py_DECREF(decoded); if (k >= 0) { rel_builddir_path[k] = L'\0'; - wcscpy(exec_prefix, argv0_path); + wcsncpy(exec_prefix, argv0_path, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, rel_builddir_path); return -1; } @@ -442,6 +449,7 @@ search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home, wchar_t *_exec_prefix /* Look at configure's EXEC_PREFIX */ wcsncpy(exec_prefix, _exec_prefix, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, lib_python); joinpath(exec_prefix, L"lib-dynload"); if (isdir(exec_prefix)) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 20bfa555b3d..edd6649ae6d 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1856,10 +1856,11 @@ sys_update_path(int argc, wchar_t **argv) if (q == NULL) argv0 = link; /* argv0 without path */ else { - /* Must make a copy */ - wcscpy(argv0copy, argv0); + /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */ + wcsncpy(argv0copy, argv0, MAXPATHLEN); q = wcsrchr(argv0copy, SEP); - wcscpy(q+1, link); + wcsncpy(q+1, link, MAXPATHLEN); + q[MAXPATHLEN + 1] = L'\0'; argv0 = argv0copy; } }