diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-03-18 22:54:59 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-18 22:54:59 (GMT) |
commit | 7b14f0c02ce9d919c503119db190dbca0e703393 (patch) | |
tree | c9a6d5d5b0628f4371b5a86dcdb60dabcbaaeb8f /Modules/getpath.c | |
parent | c183444f7e2640b054956474d71aae6e8d31a543 (diff) | |
download | cpython-7b14f0c02ce9d919c503119db190dbca0e703393.zip cpython-7b14f0c02ce9d919c503119db190dbca0e703393.tar.gz cpython-7b14f0c02ce9d919c503119db190dbca0e703393.tar.bz2 |
bpo-36352: Add error handling to getpath.c (GH-12421)
Replace Py_FatalError() with _PyInitError to let the caller handle
the fatal error.
Diffstat (limited to 'Modules/getpath.c')
-rw-r--r-- | Modules/getpath.c | 302 |
1 files changed, 233 insertions, 69 deletions
diff --git a/Modules/getpath.c b/Modules/getpath.c index 18df795..4dafc8b 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -117,6 +117,8 @@ extern "C" { ? _Py_INIT_USER_ERR("cannot decode " NAME) \ : _Py_INIT_NO_MEMORY() +#define PATHLEN_ERR() _Py_INIT_USER_ERR("path configuration: path too long") + typedef struct { wchar_t *path_env; /* PATH environment variable */ @@ -237,7 +239,7 @@ isdir(wchar_t *filename) than MAXPATHLEN characters at exit. If stuff is too long, only as much of stuff as fits will be appended. */ -static void +static _PyInitError joinpath(wchar_t *buffer, wchar_t *stuff) { size_t n, k; @@ -251,7 +253,7 @@ joinpath(wchar_t *buffer, wchar_t *stuff) } } if (n > MAXPATHLEN) { - Py_FatalError("buffer overflow in getpath.c's joinpath()"); + return PATHLEN_ERR(); } k = wcslen(stuff); if (n + k > MAXPATHLEN) { @@ -259,12 +261,13 @@ joinpath(wchar_t *buffer, wchar_t *stuff) } wcsncpy(buffer+n, stuff, k); buffer[n+k] = '\0'; + return _Py_INIT_OK(); } /* copy_absolute requires that path be allocated at least MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. */ -static void +static _PyInitError copy_absolute(wchar_t *path, wchar_t *p, size_t pathlen) { if (p[0] == SEP) { @@ -274,27 +277,36 @@ copy_absolute(wchar_t *path, wchar_t *p, size_t pathlen) if (!_Py_wgetcwd(path, pathlen)) { /* unable to get the current directory */ wcscpy(path, p); - return; + return _Py_INIT_OK(); } if (p[0] == '.' && p[1] == SEP) { p += 2; } - joinpath(path, p); + _PyInitError err = joinpath(path, p); + if (_Py_INIT_FAILED(err)) { + return err; + } } + return _Py_INIT_OK(); } /* absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. */ -static void +static _PyInitError absolutize(wchar_t *path) { wchar_t buffer[MAXPATHLEN+1]; if (path[0] == SEP) { - return; + return _Py_INIT_OK(); + } + + _PyInitError err = copy_absolute(buffer, path, MAXPATHLEN+1); + if (_Py_INIT_FAILED(err)) { + return err; } - copy_absolute(buffer, path, MAXPATHLEN+1); wcscpy(path, buffer); + return _Py_INIT_OK(); } @@ -307,7 +319,7 @@ absolutize(wchar_t *path) #define EXE_SUFFIX L".exe" #endif -static void +static _PyInitError add_exe_suffix(wchar_t *progpath) { /* Check for already have an executable suffix */ @@ -315,7 +327,7 @@ add_exe_suffix(wchar_t *progpath) size_t s = wcslen(EXE_SUFFIX); if (wcsncasecmp(EXE_SUFFIX, progpath+n-s, s) != 0) { if (n + s > MAXPATHLEN) { - Py_FatalError("progpath overflow in getpath.c's add_exe_suffix()"); + return PATHLEN_ERR(); } /* Save original path for revert */ wchar_t orig[MAXPATHLEN+1]; @@ -329,6 +341,7 @@ add_exe_suffix(wchar_t *progpath) wcsncpy(progpath, orig, MAXPATHLEN); } } + return _Py_INIT_OK(); } #endif @@ -336,10 +349,11 @@ add_exe_suffix(wchar_t *progpath) /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN bytes long. */ -static int +static _PyInitError search_for_prefix(const _PyCoreConfig *core_config, - PyCalculatePath *calculate, wchar_t *prefix) + PyCalculatePath *calculate, wchar_t *prefix, int *found) { + _PyInitError err; size_t n; wchar_t *vpath; @@ -351,39 +365,74 @@ search_for_prefix(const _PyCoreConfig *core_config, if (delim) { *delim = L'\0'; } - joinpath(prefix, calculate->lib_python); - joinpath(prefix, LANDMARK); - return 1; + err = joinpath(prefix, calculate->lib_python); + if (_Py_INIT_FAILED(err)) { + return err; + } + err = joinpath(prefix, LANDMARK); + if (_Py_INIT_FAILED(err)) { + return err; + } + *found = 1; + return _Py_INIT_OK(); } /* Check to see if argv[0] is in the build directory */ wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; - joinpath(prefix, L"Modules/Setup.local"); + err = joinpath(prefix, L"Modules/Setup.local"); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (isfile(prefix)) { /* Check VPATH to see if argv0_path is in the build directory. */ vpath = Py_DecodeLocale(VPATH, NULL); if (vpath != NULL) { wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; - joinpath(prefix, vpath); + err = joinpath(prefix, vpath); PyMem_RawFree(vpath); - joinpath(prefix, L"Lib"); - joinpath(prefix, LANDMARK); + if (_Py_INIT_FAILED(err)) { + return err; + } + + err = joinpath(prefix, L"Lib"); + if (_Py_INIT_FAILED(err)) { + return err; + } + err = joinpath(prefix, LANDMARK); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (ismodule(prefix)) { - return -1; + *found = -1; + return _Py_INIT_OK(); } } } /* Search from argv0_path, until root is found */ - copy_absolute(prefix, calculate->argv0_path, MAXPATHLEN+1); + err = copy_absolute(prefix, calculate->argv0_path, MAXPATHLEN+1); + if (_Py_INIT_FAILED(err)) { + return err; + } + do { n = wcslen(prefix); - joinpath(prefix, calculate->lib_python); - joinpath(prefix, LANDMARK); + err = joinpath(prefix, calculate->lib_python); + if (_Py_INIT_FAILED(err)) { + return err; + } + err = joinpath(prefix, LANDMARK); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (ismodule(prefix)) { - return 1; + *found = 1; + return _Py_INIT_OK(); } prefix[n] = L'\0'; reduce(prefix); @@ -392,33 +441,52 @@ search_for_prefix(const _PyCoreConfig *core_config, /* Look at configure's PREFIX */ wcsncpy(prefix, calculate->prefix, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; - joinpath(prefix, calculate->lib_python); - joinpath(prefix, LANDMARK); + err = joinpath(prefix, calculate->lib_python); + if (_Py_INIT_FAILED(err)) { + return err; + } + err = joinpath(prefix, LANDMARK); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (ismodule(prefix)) { - return 1; + *found = 1; + return _Py_INIT_OK(); } /* Fail */ - return 0; + *found = 0; + return _Py_INIT_OK(); } -static void +static _PyInitError calculate_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *prefix) { - calculate->prefix_found = search_for_prefix(core_config, calculate, prefix); + _PyInitError err; + + err = search_for_prefix(core_config, calculate, prefix, &calculate->prefix_found); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (!calculate->prefix_found) { if (!core_config->_frozen) { fprintf(stderr, "Could not find platform independent libraries <prefix>\n"); } wcsncpy(prefix, calculate->prefix, MAXPATHLEN); - joinpath(prefix, calculate->lib_python); + err = joinpath(prefix, calculate->lib_python); + if (_Py_INIT_FAILED(err)) { + return err; + } } else { reduce(prefix); } + return _Py_INIT_OK(); } @@ -448,10 +516,12 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix) /* search_for_exec_prefix requires that argv0_path be no more than MAXPATHLEN bytes long. */ -static int +static _PyInitError search_for_exec_prefix(const _PyCoreConfig *core_config, - PyCalculatePath *calculate, wchar_t *exec_prefix) + PyCalculatePath *calculate, wchar_t *exec_prefix, + int *found) { + _PyInitError err; size_t n; /* If PYTHONHOME is set, we believe it unconditionally */ @@ -464,9 +534,16 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, wcsncpy(exec_prefix, core_config->home, MAXPATHLEN); } exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(exec_prefix, calculate->lib_python); - joinpath(exec_prefix, L"lib-dynload"); - return 1; + err = joinpath(exec_prefix, calculate->lib_python); + if (_Py_INIT_FAILED(err)) { + return err; + } + err = joinpath(exec_prefix, L"lib-dynload"); + if (_Py_INIT_FAILED(err)) { + return err; + } + *found = 1; + return _Py_INIT_OK(); } /* Check to see if argv[0] is in the build directory. "pybuilddir.txt" @@ -474,7 +551,11 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, of shared library modules. */ wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN); exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(exec_prefix, L"pybuilddir.txt"); + err = joinpath(exec_prefix, L"pybuilddir.txt"); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (isfile(exec_prefix)) { FILE *f = _Py_wfopen(exec_prefix, L"rb"); if (f == NULL) { @@ -490,21 +571,37 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, if (rel_builddir_path) { wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN); exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(exec_prefix, rel_builddir_path); + err = joinpath(exec_prefix, rel_builddir_path); PyMem_RawFree(rel_builddir_path ); - return -1; + if (_Py_INIT_FAILED(err)) { + return err; + } + + *found = -1; + return _Py_INIT_OK(); } } } /* Search from argv0_path, until root is found */ - copy_absolute(exec_prefix, calculate->argv0_path, MAXPATHLEN+1); + err = copy_absolute(exec_prefix, calculate->argv0_path, MAXPATHLEN+1); + if (_Py_INIT_FAILED(err)) { + return err; + } + do { n = wcslen(exec_prefix); - joinpath(exec_prefix, calculate->lib_python); - joinpath(exec_prefix, L"lib-dynload"); + err = joinpath(exec_prefix, calculate->lib_python); + if (_Py_INIT_FAILED(err)) { + return err; + } + err = joinpath(exec_prefix, L"lib-dynload"); + if (_Py_INIT_FAILED(err)) { + return err; + } if (isdir(exec_prefix)) { - return 1; + *found = 1; + return _Py_INIT_OK(); } exec_prefix[n] = L'\0'; reduce(exec_prefix); @@ -513,33 +610,50 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, /* Look at configure's EXEC_PREFIX */ wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN); exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(exec_prefix, calculate->lib_python); - joinpath(exec_prefix, L"lib-dynload"); + err = joinpath(exec_prefix, calculate->lib_python); + if (_Py_INIT_FAILED(err)) { + return err; + } + err = joinpath(exec_prefix, L"lib-dynload"); + if (_Py_INIT_FAILED(err)) { + return err; + } if (isdir(exec_prefix)) { - return 1; + *found = 1; + return _Py_INIT_OK(); } /* Fail */ - return 0; + *found = 0; + return _Py_INIT_OK(); } -static void +static _PyInitError calculate_exec_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *exec_prefix) { - calculate->exec_prefix_found = search_for_exec_prefix(core_config, - calculate, - exec_prefix); + _PyInitError err; + + err = search_for_exec_prefix(core_config, calculate, exec_prefix, + &calculate->exec_prefix_found); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (!calculate->exec_prefix_found) { if (!core_config->_frozen) { fprintf(stderr, "Could not find platform dependent libraries <exec_prefix>\n"); } wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN); - joinpath(exec_prefix, L"lib/lib-dynload"); + err = joinpath(exec_prefix, L"lib/lib-dynload"); + if (_Py_INIT_FAILED(err)) { + return err; + } } /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ + return _Py_INIT_OK(); } @@ -564,6 +678,7 @@ static _PyInitError calculate_program_full_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { + _PyInitError err; wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); @@ -624,7 +739,11 @@ calculate_program_full_path(const _PyCoreConfig *core_config, wcsncpy(program_full_path, path, MAXPATHLEN); } - joinpath(program_full_path, core_config->program_name); + err = joinpath(program_full_path, core_config->program_name); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (isxfile(program_full_path)) { break; } @@ -640,7 +759,10 @@ calculate_program_full_path(const _PyCoreConfig *core_config, program_full_path[0] = '\0'; } if (program_full_path[0] != SEP && program_full_path[0] != '\0') { - absolutize(program_full_path); + err = absolutize(program_full_path); + if (_Py_INIT_FAILED(err)) { + return err; + } } #if defined(__CYGWIN__) || defined(__MINGW32__) /* For these platforms it is necessary to ensure that the .exe suffix @@ -649,7 +771,10 @@ calculate_program_full_path(const _PyCoreConfig *core_config, * path (bpo-28441). */ if (program_full_path[0] != '\0') { - add_exe_suffix(program_full_path); + err = add_exe_suffix(program_full_path); + if (_Py_INIT_FAILED(err)) { + return err; + } } #endif @@ -687,6 +812,7 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat ** be running the interpreter in the build directory, so we use the ** build-directory-specific logic to find Lib and such. */ + _PyInitError err; size_t len; wchar_t* wbuf = Py_DecodeLocale(modPath, &len); if (wbuf == NULL) { @@ -695,8 +821,16 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN); reduce(calculate->argv0_path); - joinpath(calculate->argv0_path, calculate->lib_python); - joinpath(calculate->argv0_path, LANDMARK); + err = joinpath(calculate->argv0_path, calculate->lib_python); + if (_Py_INIT_FAILED(err)) { + PyMem_RawFree(wbuf); + return err; + } + err = joinpath(calculate->argv0_path, LANDMARK); + if (_Py_INIT_FAILED(err)) { + PyMem_RawFree(wbuf); + return err; + } if (!ismodule(calculate->argv0_path)) { /* We are in the build directory so use the name of the executable - we know that the absolute path is passed */ @@ -721,8 +855,12 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat } else { /* Interpret relative to program_full_path */ + _PyInitError err; reduce(calculate->argv0_path); - joinpath(calculate->argv0_path, tmpbuffer); + err = joinpath(calculate->argv0_path, tmpbuffer); + if (_Py_INIT_FAILED(err)) { + return err; + } } linklen = _Py_wreadlink(calculate->argv0_path, tmpbuffer, MAXPATHLEN); } @@ -739,23 +877,30 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat executable's directory and then in the parent directory. If found, open it for use when searching for prefixes. */ -static void +static _PyInitError calculate_read_pyenv(PyCalculatePath *calculate) { + _PyInitError err; wchar_t tmpbuffer[MAXPATHLEN+1]; wchar_t *env_cfg = L"pyvenv.cfg"; FILE *env_file; wcscpy(tmpbuffer, calculate->argv0_path); - joinpath(tmpbuffer, env_cfg); + err = joinpath(tmpbuffer, env_cfg); + if (_Py_INIT_FAILED(err)) { + return err; + } env_file = _Py_wfopen(tmpbuffer, L"r"); if (env_file == NULL) { errno = 0; reduce(tmpbuffer); reduce(tmpbuffer); - joinpath(tmpbuffer, env_cfg); + err = joinpath(tmpbuffer, env_cfg); + if (_Py_INIT_FAILED(err)) { + return err; + } env_file = _Py_wfopen(tmpbuffer, L"r"); if (env_file == NULL) { @@ -764,7 +909,7 @@ calculate_read_pyenv(PyCalculatePath *calculate) } if (env_file == NULL) { - return; + return _Py_INIT_OK(); } /* Look for a 'home' variable and set argv0_path to it, if found */ @@ -772,12 +917,14 @@ calculate_read_pyenv(PyCalculatePath *calculate) wcscpy(calculate->argv0_path, tmpbuffer); } fclose(env_file); + return _Py_INIT_OK(); } -static void +static _PyInitError calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) { + _PyInitError err; wcsncpy(calculate->zip_path, prefix, MAXPATHLEN); calculate->zip_path[MAXPATHLEN] = L'\0'; @@ -789,12 +936,16 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) else { wcsncpy(calculate->zip_path, calculate->prefix, MAXPATHLEN); } - joinpath(calculate->zip_path, L"lib/python00.zip"); + err = joinpath(calculate->zip_path, L"lib/python00.zip"); + if (_Py_INIT_FAILED(err)) { + return err; + } /* Replace "00" with version */ size_t bufsz = wcslen(calculate->zip_path); calculate->zip_path[bufsz - 6] = VERSION[0]; calculate->zip_path[bufsz - 5] = VERSION[2]; + return _Py_INIT_OK(); } @@ -949,17 +1100,29 @@ calculate_path_impl(const _PyCoreConfig *core_config, return err; } - calculate_read_pyenv(calculate); + err = calculate_read_pyenv(calculate); + if (_Py_INIT_FAILED(err)) { + return err; + } wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); - calculate_prefix(core_config, calculate, prefix); + err = calculate_prefix(core_config, calculate, prefix); + if (_Py_INIT_FAILED(err)) { + return err; + } - calculate_zip_path(calculate, prefix); + err = calculate_zip_path(calculate, prefix); + if (_Py_INIT_FAILED(err)) { + return err; + } wchar_t exec_prefix[MAXPATHLEN+1]; memset(exec_prefix, 0, sizeof(exec_prefix)); - calculate_exec_prefix(core_config, calculate, exec_prefix); + err = calculate_exec_prefix(core_config, calculate, exec_prefix); + if (_Py_INIT_FAILED(err)) { + return err; + } if ((!calculate->prefix_found || !calculate->exec_prefix_found) && !core_config->_frozen) @@ -995,10 +1158,11 @@ calculate_path_impl(const _PyCoreConfig *core_config, _PyInitError _PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config) { + _PyInitError err; PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - _PyInitError err = calculate_init(&calculate, core_config); + err = calculate_init(&calculate, core_config); if (_Py_INIT_FAILED(err)) { goto done; } |