diff options
author | Steve Dower <steve.dower@microsoft.com> | 2016-10-27 21:28:07 (GMT) |
---|---|---|
committer | Steve Dower <steve.dower@microsoft.com> | 2016-10-27 21:28:07 (GMT) |
commit | c6dd415252f255b583fcdae5d51a28e027284b06 (patch) | |
tree | 472f56f3e818640de306b3d1ac2181e40a0e93ac | |
parent | e45ef4e54cc408e1243e57eb2287c087fa81a0d4 (diff) | |
download | cpython-c6dd415252f255b583fcdae5d51a28e027284b06.zip cpython-c6dd415252f255b583fcdae5d51a28e027284b06.tar.gz cpython-c6dd415252f255b583fcdae5d51a28e027284b06.tar.bz2 |
Issue #28522: Fixes mishandled buffer reallocation in getpathp.c
-rw-r--r-- | Lib/test/test_site.py | 52 | ||||
-rw-r--r-- | Misc/NEWS | 5 | ||||
-rw-r--r-- | PC/getpathp.c | 19 |
3 files changed, 72 insertions, 4 deletions
diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index d2fbb7b..5aedbdb 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -488,6 +488,58 @@ class StartupImportTests(unittest.TestCase): 'import site, sys; site.enablerlcompleter(); sys.exit(hasattr(sys, "__interactivehook__"))']).wait() self.assertTrue(r, "'__interactivehook__' not added by enablerlcompleter()") + @unittest.skipUnless(sys.platform == 'win32', "only supported on Windows") + def test_underpth_nosite_file(self): + _pth_file = os.path.splitext(sys.executable)[0] + '._pth' + try: + libpath = os.path.dirname(os.path.dirname(encodings.__file__)) + with open(_pth_file, 'w') as f: + print('fake-path-name', file=f) + # Ensure the generated path is very long so that buffer + # resizing in getpathp.c is exercised + for _ in range(200): + print(libpath, file=f) + print('# comment', file=f) + + env = os.environ.copy() + env['PYTHONPATH'] = 'from-env' + rc = subprocess.call([sys.executable, '-c', + 'import sys; sys.exit(sys.flags.no_site and ' + 'len(sys.path) > 200 and ' + '%r in sys.path and %r in sys.path and %r not in sys.path)' % ( + os.path.join(sys.prefix, 'fake-path-name'), + libpath, + os.path.join(sys.prefix, 'from-env'), + )], env=env) + self.assertEqual(rc, 0) + finally: + os.unlink(_pth_file) + + @unittest.skipUnless(sys.platform == 'win32', "only supported on Windows") + def test_underpth_file(self): + _pth_file = os.path.splitext(sys.executable)[0] + '._pth' + try: + libpath = os.path.dirname(os.path.dirname(encodings.__file__)) + with open(_pth_file, 'w') as f: + print('fake-path-name', file=f) + for _ in range(200): + print(libpath, file=f) + print('# comment', file=f) + print('import site', file=f) + + env = os.environ.copy() + env['PYTHONPATH'] = 'from-env' + rc = subprocess.call([sys.executable, '-c', + 'import sys; sys.exit(not sys.flags.no_site and ' + '%r in sys.path and %r in sys.path and %r not in sys.path)' % ( + os.path.join(sys.prefix, 'fake-path-name'), + libpath, + os.path.join(sys.prefix, 'from-env'), + )], env=env) + self.assertEqual(rc, 0) + finally: + os.unlink(_pth_file) + if __name__ == "__main__": unittest.main() @@ -85,6 +85,11 @@ Library threadpool executor. Initial patch by Hans Lawrenz. +Windows +------- + +- Issue #28522: Fixes mishandled buffer reallocation in getpathp.c + Build ----- diff --git a/PC/getpathp.c b/PC/getpathp.c index 31f973e..0b0ae49 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -581,7 +581,8 @@ read_pth_file(const wchar_t *path, wchar_t *prefix, int *isolated, int *nosite) wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, wline, wn + 1); wline[wn] = '\0'; - while (wn + prefixlen + 4 > bufsiz) { + size_t usedsiz = wcslen(buf); + while (usedsiz + wn + prefixlen + 4 > bufsiz) { bufsiz += MAXPATHLEN; buf = (wchar_t*)PyMem_RawRealloc(buf, (bufsiz + 1) * sizeof(wchar_t)); if (!buf) { @@ -590,11 +591,21 @@ read_pth_file(const wchar_t *path, wchar_t *prefix, int *isolated, int *nosite) } } - if (buf[0]) + if (usedsiz) { wcscat_s(buf, bufsiz, L";"); + usedsiz += 1; + } - wchar_t *b = &buf[wcslen(buf)]; - wcscat_s(buf, bufsiz, prefix); + errno_t result; + _Py_BEGIN_SUPPRESS_IPH + result = wcscat_s(buf, bufsiz, prefix); + _Py_END_SUPPRESS_IPH + if (result == EINVAL) { + Py_FatalError("invalid argument during ._pth processing"); + } else if (result == ERANGE) { + Py_FatalError("buffer overflow during ._pth processing"); + } + wchar_t *b = &buf[usedsiz]; join(b, wline); PyMem_RawFree(wline); |