From 5f9cf23502febe0eb3bc02e45c7d2bfc79424757 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 19 Mar 2019 01:46:25 +0100 Subject: bpo-36301: Error if decoding pybuilddir.txt fails (GH-12422) Python initialization now fails if decoding pybuilddir.txt configuration file fails at startup. _PyPathConfig_Calculate() now reports memory allocation failure and decoding error on decoding pybuilddir.txt content from UTF-8/surrogateescape. --- Include/internal/pycore_fileutils.h | 3 ++- .../2019-03-19-00-54-31.bpo-36301.xvOCJb.rst | 2 ++ Modules/getpath.c | 28 ++++++++++++---------- Objects/unicodeobject.c | 13 ++++++++-- Python/pathconfig.c | 2 +- 5 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-19-00-54-31.bpo-36301.xvOCJb.rst diff --git a/Include/internal/pycore_fileutils.h b/Include/internal/pycore_fileutils.h index 23ae201..bbee586 100644 --- a/Include/internal/pycore_fileutils.h +++ b/Include/internal/pycore_fileutils.h @@ -30,7 +30,8 @@ PyAPI_FUNC(int) _Py_EncodeUTF8Ex( PyAPI_FUNC(wchar_t*) _Py_DecodeUTF8_surrogateescape( const char *arg, - Py_ssize_t arglen); + Py_ssize_t arglen, + size_t *wlen); PyAPI_FUNC(int) _Py_GetForceASCII(void); diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-19-00-54-31.bpo-36301.xvOCJb.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-19-00-54-31.bpo-36301.xvOCJb.rst new file mode 100644 index 0000000..84e4b8a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-03-19-00-54-31.bpo-36301.xvOCJb.rst @@ -0,0 +1,2 @@ +Python initialization now fails if decoding ``pybuilddir.txt`` configuration +file fails at startup. diff --git a/Modules/getpath.c b/Modules/getpath.c index 4dafc8b..4364317 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -563,23 +563,27 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, } else { char buf[MAXPATHLEN+1]; - wchar_t *rel_builddir_path; n = fread(buf, 1, MAXPATHLEN, f); buf[n] = '\0'; fclose(f); - rel_builddir_path = _Py_DecodeUTF8_surrogateescape(buf, n); - if (rel_builddir_path) { - wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN); - exec_prefix[MAXPATHLEN] = L'\0'; - err = joinpath(exec_prefix, rel_builddir_path); - PyMem_RawFree(rel_builddir_path ); - if (_Py_INIT_FAILED(err)) { - return err; - } - *found = -1; - return _Py_INIT_OK(); + size_t dec_len; + wchar_t *pybuilddir; + pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len); + if (!pybuilddir) { + return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len); } + + wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; + err = joinpath(exec_prefix, pybuilddir); + PyMem_RawFree(pybuilddir ); + if (_Py_INIT_FAILED(err)) { + return err; + } + + *found = -1; + return _Py_INIT_OK(); } } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index b3a851a..9d3ed0d 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5064,12 +5064,21 @@ _Py_DecodeUTF8Ex(const char *s, Py_ssize_t size, wchar_t **wstr, size_t *wlen, return 0; } + wchar_t* -_Py_DecodeUTF8_surrogateescape(const char *arg, Py_ssize_t arglen) +_Py_DecodeUTF8_surrogateescape(const char *arg, Py_ssize_t arglen, + size_t *wlen) { wchar_t *wstr; - int res = _Py_DecodeUTF8Ex(arg, arglen, &wstr, NULL, NULL, 1); + int res = _Py_DecodeUTF8Ex(arg, arglen, + &wstr, wlen, + NULL, _Py_ERROR_SURROGATEESCAPE); if (res != 0) { + /* _Py_DecodeUTF8Ex() must support _Py_ERROR_SURROGATEESCAPE */ + assert(res != -3); + if (wlen) { + *wlen = (size_t)res; + } return NULL; } return wstr; diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 0ee87c4..87db66b 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -712,7 +712,7 @@ _Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key, continue; } - wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n); + wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL); if (tmpbuffer) { wchar_t * state; wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state); -- cgit v0.12