diff options
author | Steve Dower <steve.dower@microsoft.com> | 2018-03-05 22:26:08 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-05 22:26:08 (GMT) |
commit | 6921e73e33edc3c61bc2d78ed558eaa22a89a564 (patch) | |
tree | bc695813bf31a459085fa5d93fa8d84d61441a82 /Modules/posixmodule.c | |
parent | 4c19b95734faee4c390c1d0569dc876980c33d2c (diff) | |
download | cpython-6921e73e33edc3c61bc2d78ed558eaa22a89a564.zip cpython-6921e73e33edc3c61bc2d78ed558eaa22a89a564.tar.gz cpython-6921e73e33edc3c61bc2d78ed558eaa22a89a564.tar.bz2 |
bpo-33001: Prevent buffer overrun in os.symlink (GH-5989)
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r-- | Modules/posixmodule.c | 66 |
1 files changed, 38 insertions, 28 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 6bba8ee..f4c0104 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7471,7 +7471,7 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) #if defined(MS_WINDOWS) /* Grab CreateSymbolicLinkW dynamically from kernel32 */ -static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD) = NULL; +static BOOLEAN (CALLBACK *Py_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD) = NULL; static int check_CreateSymbolicLink(void) @@ -7486,47 +7486,51 @@ check_CreateSymbolicLink(void) return Py_CreateSymbolicLinkW != NULL; } -/* Remove the last portion of the path */ -static void +/* Remove the last portion of the path - return 0 on success */ +static int _dirnameW(WCHAR *path) { WCHAR *ptr; + size_t length = wcsnlen_s(path, MAX_PATH); + if (length == MAX_PATH) { + return -1; + } /* walk the path from the end until a backslash is encountered */ - for(ptr = path + wcslen(path); ptr != path; ptr--) { - if (*ptr == L'\\' || *ptr == L'/') + for(ptr = path + length; ptr != path; ptr--) { + if (*ptr == L'\\' || *ptr == L'/') { break; + } } *ptr = 0; + return 0; } /* Is this path absolute? */ static int _is_absW(const WCHAR *path) { - return path[0] == L'\\' || path[0] == L'/' || path[1] == L':'; - + return path[0] == L'\\' || path[0] == L'/' || + (path[0] && path[1] == L':'); } -/* join root and rest with a backslash */ -static void +/* join root and rest with a backslash - return 0 on success */ +static int _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) { - size_t root_len; - if (_is_absW(rest)) { - wcscpy(dest_path, rest); - return; + return wcscpy_s(dest_path, MAX_PATH, rest); } - root_len = wcslen(root); + if (wcscpy_s(dest_path, MAX_PATH, root)) { + return -1; + } - wcscpy(dest_path, root); - if(root_len) { - dest_path[root_len] = L'\\'; - root_len++; + if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { + return -1; } - wcscpy(dest_path+root_len, rest); + + return wcscat_s(dest_path, MAX_PATH, rest); } /* Return True if the path at src relative to dest is a directory */ @@ -7538,10 +7542,14 @@ _check_dirW(LPCWSTR src, LPCWSTR dest) WCHAR src_resolved[MAX_PATH] = L""; /* dest_parent = os.path.dirname(dest) */ - wcscpy(dest_parent, dest); - _dirnameW(dest_parent); + if (wcscpy_s(dest_parent, MAX_PATH, dest) || + _dirnameW(dest_parent)) { + return 0; + } /* src_resolved = os.path.join(dest_parent, src) */ - _joinW(src_resolved, dest_parent, src); + if (_joinW(src_resolved, dest_parent, src)) { + return 0; + } return ( GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY @@ -7597,19 +7605,15 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst, } #endif - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_SetString(PyExc_ValueError, - "symlink: src and dst must be the same type"); - return NULL; - } - #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH /* if src is a directory, ensure target_is_directory==1 */ target_is_directory |= _check_dirW(src->wide, dst->wide); result = Py_CreateSymbolicLinkW(dst->wide, src->wide, target_is_directory); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (!result) @@ -7617,6 +7621,12 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst, #else + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_SetString(PyExc_ValueError, + "symlink: src and dst must be the same type"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS #if HAVE_SYMLINKAT if (dir_fd != DEFAULT_DIR_FD) |