bpo-36352: Avoid hardcoded MAXPATHLEN size in getpath.c (GH-12423)

* Use Py_ARRAY_LENGTH() rather than hardcoded MAXPATHLEN in getpath.c.
* Pass string length to functions modifying strings.
This commit is contained in:
Victor Stinner 2019-03-19 02:58:14 +01:00 committed by GitHub
parent 5f9cf23502
commit faddaedd05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 247 additions and 159 deletions

View file

@ -159,14 +159,16 @@ static void
reduce(wchar_t *dir)
{
size_t i = wcslen(dir);
while (i > 0 && dir[i] != SEP)
while (i > 0 && dir[i] != SEP) {
--i;
}
dir[i] = '\0';
}
/* Is file, not directory */
static int
isfile(wchar_t *filename) /* Is file, not directory */
isfile(const wchar_t *filename)
{
struct stat buf;
if (_Py_wstat(filename, &buf) != 0) {
@ -179,15 +181,16 @@ isfile(wchar_t *filename) /* Is file, not directory */
}
/* Is module -- check for .pyc too */
static int
ismodule(wchar_t *filename) /* Is module -- check for .pyc too */
ismodule(wchar_t *filename, size_t filename_len)
{
if (isfile(filename)) {
return 1;
}
/* Check for the compiled version of prefix. */
if (wcslen(filename) < MAXPATHLEN) {
if (wcslen(filename) + 2 <= filename_len) {
wcscat(filename, L"c");
if (isfile(filename)) {
return 1;
@ -199,7 +202,7 @@ ismodule(wchar_t *filename) /* Is module -- check for .pyc too */
/* Is executable file */
static int
isxfile(wchar_t *filename)
isxfile(const wchar_t *filename)
{
struct stat buf;
if (_Py_wstat(filename, &buf) != 0) {
@ -231,58 +234,71 @@ isdir(wchar_t *filename)
/* Add a path component, by appending stuff to buffer.
buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
NUL-terminated string with no more than MAXPATHLEN characters (not counting
the trailing NUL). It's a fatal error if it contains a string longer than
that (callers must be careful!). If these requirements are met, it's
guaranteed that buffer will still be a NUL-terminated string with no more
than MAXPATHLEN characters at exit. If stuff is too long, only as much of
stuff as fits will be appended.
*/
buflen: 'buffer' length in characters including trailing NUL. */
static _PyInitError
joinpath(wchar_t *buffer, wchar_t *stuff)
joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen)
{
size_t n, k;
if (stuff[0] == SEP) {
n = 0;
}
else {
if (stuff[0] != SEP) {
n = wcslen(buffer);
if (n > 0 && buffer[n-1] != SEP && n < MAXPATHLEN) {
if (n >= buflen) {
return PATHLEN_ERR();
}
if (n > 0 && buffer[n-1] != SEP) {
buffer[n++] = SEP;
}
}
if (n > MAXPATHLEN) {
return PATHLEN_ERR();
else {
n = 0;
}
k = wcslen(stuff);
if (n + k > MAXPATHLEN) {
k = MAXPATHLEN - n;
if (n + k >= buflen) {
return PATHLEN_ERR();
}
wcsncpy(buffer+n, stuff, k);
buffer[n+k] = '\0';
return _Py_INIT_OK();
}
static inline int
safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
{
size_t srclen = wcslen(src);
if (n <= srclen) {
dst[0] = L'\0';
return -1;
}
memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
return 0;
}
/* copy_absolute requires that path be allocated at least
MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. */
'pathlen' characters (including trailing NUL). */
static _PyInitError
copy_absolute(wchar_t *path, wchar_t *p, size_t pathlen)
copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen)
{
if (p[0] == SEP) {
wcscpy(path, p);
if (safe_wcscpy(path, p, pathlen) < 0) {
return PATHLEN_ERR();
}
}
else {
if (!_Py_wgetcwd(path, pathlen)) {
/* unable to get the current directory */
wcscpy(path, p);
if (safe_wcscpy(path, p, pathlen) < 0) {
return PATHLEN_ERR();
}
return _Py_INIT_OK();
}
if (p[0] == '.' && p[1] == SEP) {
p += 2;
}
_PyInitError err = joinpath(path, p);
_PyInitError err = joinpath(path, p, pathlen);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -291,56 +307,54 @@ copy_absolute(wchar_t *path, wchar_t *p, size_t pathlen)
}
/* absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. */
/* path_len: path length in characters including trailing NUL */
static _PyInitError
absolutize(wchar_t *path)
absolutize(wchar_t *path, size_t path_len)
{
wchar_t buffer[MAXPATHLEN+1];
if (path[0] == SEP) {
return _Py_INIT_OK();
}
_PyInitError err = copy_absolute(buffer, path, MAXPATHLEN+1);
wchar_t abs_path[MAXPATHLEN+1];
_PyInitError err = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
if (_Py_INIT_FAILED(err)) {
return err;
}
wcscpy(path, buffer);
if (safe_wcscpy(path, abs_path, path_len) < 0) {
return PATHLEN_ERR();
}
return _Py_INIT_OK();
}
#if defined(__CYGWIN__) || defined(__MINGW32__)
/* add_exe_suffix requires that progpath be allocated at least
MAXPATHLEN + 1 bytes.
*/
#ifndef EXE_SUFFIX
#define EXE_SUFFIX L".exe"
#endif
/* pathlen: 'path' length in characters including trailing NUL */
static _PyInitError
add_exe_suffix(wchar_t *progpath)
add_exe_suffix(wchar_t *progpath, size_t progpathlen)
{
/* Check for already have an executable suffix */
size_t n = wcslen(progpath);
size_t s = wcslen(EXE_SUFFIX);
if (wcsncasecmp(EXE_SUFFIX, progpath+n-s, s) != 0) {
if (n + s > MAXPATHLEN) {
return PATHLEN_ERR();
}
/* Save original path for revert */
wchar_t orig[MAXPATHLEN+1];
wcsncpy(orig, progpath, MAXPATHLEN);
wcsncpy(progpath+n, EXE_SUFFIX, s);
progpath[n+s] = '\0';
if (!isxfile(progpath)) {
/* Path that added suffix is invalid */
wcsncpy(progpath, orig, MAXPATHLEN);
}
if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
return _Py_INIT_OK();
}
if (n + s >= progpathlen) {
return PATHLEN_ERR();
}
wcsncpy(progpath + n, EXE_SUFFIX, s);
progpath[n+s] = '\0';
if (!isxfile(progpath)) {
/* Path that added suffix is invalid: truncate (remove suffix) */
progpath[n] = '\0';
}
return _Py_INIT_OK();
}
#endif
@ -350,8 +364,9 @@ add_exe_suffix(wchar_t *progpath)
bytes long.
*/
static _PyInitError
search_for_prefix(const _PyCoreConfig *core_config,
PyCalculatePath *calculate, wchar_t *prefix, int *found)
search_for_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate,
wchar_t *prefix, size_t prefix_len,
int *found)
{
_PyInitError err;
size_t n;
@ -359,17 +374,18 @@ search_for_prefix(const _PyCoreConfig *core_config,
/* If PYTHONHOME is set, we believe it unconditionally */
if (core_config->home) {
wcsncpy(prefix, core_config->home, MAXPATHLEN);
prefix[MAXPATHLEN] = L'\0';
if (safe_wcscpy(prefix, core_config->home, prefix_len) < 0) {
return PATHLEN_ERR();
}
wchar_t *delim = wcschr(prefix, DELIM);
if (delim) {
*delim = L'\0';
}
err = joinpath(prefix, calculate->lib_python);
err = joinpath(prefix, calculate->lib_python, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = joinpath(prefix, LANDMARK);
err = joinpath(prefix, LANDMARK, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -378,9 +394,10 @@ search_for_prefix(const _PyCoreConfig *core_config,
}
/* Check to see if argv[0] is in the build directory */
wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN);
prefix[MAXPATHLEN] = L'\0';
err = joinpath(prefix, L"Modules/Setup.local");
if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
return PATHLEN_ERR();
}
err = joinpath(prefix, L"Modules/Setup.local", prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -389,24 +406,25 @@ search_for_prefix(const _PyCoreConfig *core_config,
/* 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';
err = joinpath(prefix, vpath);
if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
return PATHLEN_ERR();
}
err = joinpath(prefix, vpath, prefix_len);
PyMem_RawFree(vpath);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = joinpath(prefix, L"Lib");
err = joinpath(prefix, L"Lib", prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = joinpath(prefix, LANDMARK);
err = joinpath(prefix, LANDMARK, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
if (ismodule(prefix)) {
if (ismodule(prefix, prefix_len)) {
*found = -1;
return _Py_INIT_OK();
}
@ -414,23 +432,23 @@ search_for_prefix(const _PyCoreConfig *core_config,
}
/* Search from argv0_path, until root is found */
err = copy_absolute(prefix, calculate->argv0_path, MAXPATHLEN+1);
err = copy_absolute(prefix, calculate->argv0_path, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
do {
n = wcslen(prefix);
err = joinpath(prefix, calculate->lib_python);
err = joinpath(prefix, calculate->lib_python, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = joinpath(prefix, LANDMARK);
err = joinpath(prefix, LANDMARK, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
if (ismodule(prefix)) {
if (ismodule(prefix, prefix_len)) {
*found = 1;
return _Py_INIT_OK();
}
@ -439,18 +457,19 @@ search_for_prefix(const _PyCoreConfig *core_config,
} while (prefix[0]);
/* Look at configure's PREFIX */
wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
prefix[MAXPATHLEN] = L'\0';
err = joinpath(prefix, calculate->lib_python);
if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
return PATHLEN_ERR();
}
err = joinpath(prefix, calculate->lib_python, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = joinpath(prefix, LANDMARK);
err = joinpath(prefix, LANDMARK, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
if (ismodule(prefix)) {
if (ismodule(prefix, prefix_len)) {
*found = 1;
return _Py_INIT_OK();
}
@ -463,11 +482,12 @@ search_for_prefix(const _PyCoreConfig *core_config,
static _PyInitError
calculate_prefix(const _PyCoreConfig *core_config,
PyCalculatePath *calculate, wchar_t *prefix)
PyCalculatePath *calculate, wchar_t *prefix, size_t prefix_len)
{
_PyInitError err;
err = search_for_prefix(core_config, calculate, prefix, &calculate->prefix_found);
err = search_for_prefix(core_config, calculate, prefix, prefix_len,
&calculate->prefix_found);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -477,8 +497,10 @@ calculate_prefix(const _PyCoreConfig *core_config,
fprintf(stderr,
"Could not find platform independent libraries <prefix>\n");
}
wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
err = joinpath(prefix, calculate->lib_python);
if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
return PATHLEN_ERR();
}
err = joinpath(prefix, calculate->lib_python, prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -490,8 +512,9 @@ calculate_prefix(const _PyCoreConfig *core_config,
}
static void
calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix)
static _PyInitError
calculate_reduce_prefix(PyCalculatePath *calculate,
wchar_t *prefix, size_t prefix_len)
{
/* Reduce prefix and exec_prefix to their essence,
* e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
@ -508,8 +531,11 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix)
}
}
else {
wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
return PATHLEN_ERR();
}
}
return _Py_INIT_OK();
}
@ -518,7 +544,8 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix)
*/
static _PyInitError
search_for_exec_prefix(const _PyCoreConfig *core_config,
PyCalculatePath *calculate, wchar_t *exec_prefix,
PyCalculatePath *calculate,
wchar_t *exec_prefix, size_t exec_prefix_len,
int *found)
{
_PyInitError err;
@ -528,17 +555,20 @@ search_for_exec_prefix(const _PyCoreConfig *core_config,
if (core_config->home) {
wchar_t *delim = wcschr(core_config->home, DELIM);
if (delim) {
wcsncpy(exec_prefix, delim+1, MAXPATHLEN);
if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
return PATHLEN_ERR();
}
}
else {
wcsncpy(exec_prefix, core_config->home, MAXPATHLEN);
if (safe_wcscpy(exec_prefix, core_config->home, exec_prefix_len) < 0) {
return PATHLEN_ERR();
}
}
exec_prefix[MAXPATHLEN] = L'\0';
err = joinpath(exec_prefix, calculate->lib_python);
err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = joinpath(exec_prefix, L"lib-dynload");
err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -549,9 +579,10 @@ search_for_exec_prefix(const _PyCoreConfig *core_config,
/* 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. */
wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN);
exec_prefix[MAXPATHLEN] = L'\0';
err = joinpath(exec_prefix, L"pybuilddir.txt");
if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) {
return PATHLEN_ERR();
}
err = joinpath(exec_prefix, L"pybuilddir.txt", exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -562,21 +593,22 @@ search_for_exec_prefix(const _PyCoreConfig *core_config,
errno = 0;
}
else {
char buf[MAXPATHLEN+1];
n = fread(buf, 1, MAXPATHLEN, f);
char buf[MAXPATHLEN + 1];
n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, f);
buf[n] = '\0';
fclose(f);
size_t dec_len;
wchar_t *pybuilddir;
size_t dec_len;
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);
if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) {
return PATHLEN_ERR();
}
err = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
PyMem_RawFree(pybuilddir );
if (_Py_INIT_FAILED(err)) {
return err;
@ -588,18 +620,18 @@ search_for_exec_prefix(const _PyCoreConfig *core_config,
}
/* Search from argv0_path, until root is found */
err = copy_absolute(exec_prefix, calculate->argv0_path, MAXPATHLEN+1);
err = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
do {
n = wcslen(exec_prefix);
err = joinpath(exec_prefix, calculate->lib_python);
err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = joinpath(exec_prefix, L"lib-dynload");
err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -612,13 +644,14 @@ search_for_exec_prefix(const _PyCoreConfig *core_config,
} while (exec_prefix[0]);
/* Look at configure's EXEC_PREFIX */
wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
exec_prefix[MAXPATHLEN] = L'\0';
err = joinpath(exec_prefix, calculate->lib_python);
if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
return PATHLEN_ERR();
}
err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = joinpath(exec_prefix, L"lib-dynload");
err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -635,11 +668,13 @@ search_for_exec_prefix(const _PyCoreConfig *core_config,
static _PyInitError
calculate_exec_prefix(const _PyCoreConfig *core_config,
PyCalculatePath *calculate, wchar_t *exec_prefix)
PyCalculatePath *calculate,
wchar_t *exec_prefix, size_t exec_prefix_len)
{
_PyInitError err;
err = search_for_exec_prefix(core_config, calculate, exec_prefix,
err = search_for_exec_prefix(core_config, calculate,
exec_prefix, exec_prefix_len,
&calculate->exec_prefix_found);
if (_Py_INIT_FAILED(err)) {
return err;
@ -650,8 +685,10 @@ calculate_exec_prefix(const _PyCoreConfig *core_config,
fprintf(stderr,
"Could not find platform dependent libraries <exec_prefix>\n");
}
wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
err = joinpath(exec_prefix, L"lib/lib-dynload");
if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
return PATHLEN_ERR();
}
err = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -661,8 +698,9 @@ calculate_exec_prefix(const _PyCoreConfig *core_config,
}
static void
calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
static _PyInitError
calculate_reduce_exec_prefix(PyCalculatePath *calculate,
wchar_t *exec_prefix, size_t exec_prefix_len)
{
if (calculate->exec_prefix_found > 0) {
reduce(exec_prefix);
@ -673,8 +711,11 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
}
}
else {
wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
return PATHLEN_ERR();
}
}
return _Py_INIT_OK();
}
@ -683,16 +724,17 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
PyCalculatePath *calculate, _PyPathConfig *config)
{
_PyInitError err;
wchar_t program_full_path[MAXPATHLEN+1];
wchar_t program_full_path[MAXPATHLEN + 1];
const size_t program_full_path_len = Py_ARRAY_LENGTH(program_full_path);
memset(program_full_path, 0, sizeof(program_full_path));
#ifdef __APPLE__
char execpath[MAXPATHLEN + 1];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
uint32_t nsexeclength = MAXPATHLEN;
uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
#else
unsigned long nsexeclength = MAXPATHLEN;
unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
#endif
char execpath[MAXPATHLEN+1];
#endif
/* If there is no slash in the argv0 path, then we have to
@ -701,7 +743,10 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
* $PATH isn't exported, you lose.
*/
if (wcschr(core_config->program_name, SEP)) {
wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN);
if (safe_wcscpy(program_full_path, core_config->program_name,
program_full_path_len) < 0) {
return PATHLEN_ERR();
}
}
#ifdef __APPLE__
/* On Mac OS X, if a script uses an interpreter of the form
@ -722,7 +767,10 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
if (path == NULL) {
return DECODE_LOCALE_ERR("executable path", len);
}
wcsncpy(program_full_path, path, MAXPATHLEN);
if (safe_wcscpy(program_full_path, path, program_full_path_len) < 0) {
PyMem_RawFree(path);
return PATHLEN_ERR();
}
PyMem_RawFree(path);
}
#endif /* __APPLE__ */
@ -733,17 +781,21 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
if (delim) {
size_t len = delim - path;
if (len > MAXPATHLEN) {
len = MAXPATHLEN;
if (len >= program_full_path_len) {
return PATHLEN_ERR();
}
wcsncpy(program_full_path, path, len);
program_full_path[len] = '\0';
}
else {
wcsncpy(program_full_path, path, MAXPATHLEN);
if (safe_wcscpy(program_full_path, path,
program_full_path_len) < 0) {
return PATHLEN_ERR();
}
}
err = joinpath(program_full_path, core_config->program_name);
err = joinpath(program_full_path, core_config->program_name,
program_full_path_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -763,7 +815,7 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
program_full_path[0] = '\0';
}
if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
err = absolutize(program_full_path);
err = absolutize(program_full_path, program_full_path_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -775,7 +827,7 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
* path (bpo-28441).
*/
if (program_full_path[0] != '\0') {
err = add_exe_suffix(program_full_path);
err = add_exe_suffix(program_full_path, program_full_path_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -793,8 +845,10 @@ calculate_program_full_path(const _PyCoreConfig *core_config,
static _PyInitError
calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path)
{
wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN);
calculate->argv0_path[MAXPATHLEN] = '\0';
const size_t argv0_path_len = Py_ARRAY_LENGTH(calculate->argv0_path);
if (safe_wcscpy(calculate->argv0_path, program_full_path, argv0_path_len) < 0) {
return PATHLEN_ERR();
}
#ifdef WITH_NEXT_FRAMEWORK
NSModule pythonModule;
@ -823,50 +877,61 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_pat
return DECODE_LOCALE_ERR("framework location", len);
}
wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN);
if (safe_wcscpy(calculate->argv0_path, wbuf, argv0_path_len) < 0) {
return PATHLEN_ERR();
}
reduce(calculate->argv0_path);
err = joinpath(calculate->argv0_path, calculate->lib_python);
err = joinpath(calculate->argv0_path, calculate->lib_python, argv0_path_len);
if (_Py_INIT_FAILED(err)) {
PyMem_RawFree(wbuf);
return err;
}
err = joinpath(calculate->argv0_path, LANDMARK);
err = joinpath(calculate->argv0_path, LANDMARK, argv0_path_len);
if (_Py_INIT_FAILED(err)) {
PyMem_RawFree(wbuf);
return err;
}
if (!ismodule(calculate->argv0_path)) {
if (!ismodule(calculate->argv0_path,
Py_ARRAY_LENGTH(calculate->argv0_path))) {
/* We are in the build directory so use the name of the
executable - we know that the absolute path is passed */
wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN);
if (safe_wcscpy(calculate->argv0_path, program_full_path,
argv0_path_len) < 0) {
return PATHLEN_ERR();
}
}
else {
/* Use the location of the library as the program_full_path */
wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN);
if (safe_wcscpy(calculate->argv0_path, wbuf, argv0_path_len) < 0) {
return PATHLEN_ERR();
}
}
PyMem_RawFree(wbuf);
}
#endif
#if HAVE_READLINK
wchar_t tmpbuffer[MAXPATHLEN+1];
int linklen = _Py_wreadlink(program_full_path, tmpbuffer, MAXPATHLEN);
wchar_t tmpbuffer[MAXPATHLEN + 1];
const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
int linklen = _Py_wreadlink(program_full_path, tmpbuffer, buflen);
while (linklen != -1) {
if (tmpbuffer[0] == SEP) {
/* tmpbuffer should never be longer than MAXPATHLEN,
but extra check does not hurt */
wcsncpy(calculate->argv0_path, tmpbuffer, MAXPATHLEN);
if (safe_wcscpy(calculate->argv0_path, tmpbuffer, argv0_path_len) < 0) {
return PATHLEN_ERR();
}
}
else {
/* Interpret relative to program_full_path */
_PyInitError err;
reduce(calculate->argv0_path);
err = joinpath(calculate->argv0_path, tmpbuffer);
err = joinpath(calculate->argv0_path, tmpbuffer, argv0_path_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
}
linklen = _Py_wreadlink(calculate->argv0_path, tmpbuffer, MAXPATHLEN);
linklen = _Py_wreadlink(calculate->argv0_path, tmpbuffer, buflen);
}
#endif /* HAVE_READLINK */
@ -886,12 +951,15 @@ calculate_read_pyenv(PyCalculatePath *calculate)
{
_PyInitError err;
wchar_t tmpbuffer[MAXPATHLEN+1];
const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
wchar_t *env_cfg = L"pyvenv.cfg";
FILE *env_file;
wcscpy(tmpbuffer, calculate->argv0_path);
if (safe_wcscpy(tmpbuffer, calculate->argv0_path, buflen) < 0) {
return PATHLEN_ERR();
}
err = joinpath(tmpbuffer, env_cfg);
err = joinpath(tmpbuffer, env_cfg, buflen);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -901,7 +969,7 @@ calculate_read_pyenv(PyCalculatePath *calculate)
reduce(tmpbuffer);
reduce(tmpbuffer);
err = joinpath(tmpbuffer, env_cfg);
err = joinpath(tmpbuffer, env_cfg, buflen);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -917,8 +985,11 @@ calculate_read_pyenv(PyCalculatePath *calculate)
}
/* Look for a 'home' variable and set argv0_path to it, if found */
if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, MAXPATHLEN)) {
wcscpy(calculate->argv0_path, tmpbuffer);
if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, buflen)) {
if (safe_wcscpy(calculate->argv0_path, tmpbuffer,
Py_ARRAY_LENGTH(calculate->argv0_path)) < 0) {
return PATHLEN_ERR();
}
}
fclose(env_file);
return _Py_INIT_OK();
@ -929,8 +1000,10 @@ 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';
const size_t zip_path_len = Py_ARRAY_LENGTH(calculate->zip_path);
if (safe_wcscpy(calculate->zip_path, prefix, zip_path_len) < 0) {
return PATHLEN_ERR();
}
if (calculate->prefix_found > 0) {
/* Use the reduced prefix returned by Py_GetPrefix() */
@ -938,9 +1011,11 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
reduce(calculate->zip_path);
}
else {
wcsncpy(calculate->zip_path, calculate->prefix, MAXPATHLEN);
if (safe_wcscpy(calculate->zip_path, calculate->prefix, zip_path_len) < 0) {
return PATHLEN_ERR();
}
}
err = joinpath(calculate->zip_path, L"lib/python00.zip");
err = joinpath(calculate->zip_path, L"lib/python00.zip", zip_path_len);
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -1111,7 +1186,8 @@ calculate_path_impl(const _PyCoreConfig *core_config,
wchar_t prefix[MAXPATHLEN+1];
memset(prefix, 0, sizeof(prefix));
err = calculate_prefix(core_config, calculate, prefix);
err = calculate_prefix(core_config, calculate,
prefix, Py_ARRAY_LENGTH(prefix));
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -1123,7 +1199,8 @@ calculate_path_impl(const _PyCoreConfig *core_config,
wchar_t exec_prefix[MAXPATHLEN+1];
memset(exec_prefix, 0, sizeof(exec_prefix));
err = calculate_exec_prefix(core_config, calculate, exec_prefix);
err = calculate_exec_prefix(core_config, calculate,
exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
if (_Py_INIT_FAILED(err)) {
return err;
}
@ -1141,14 +1218,21 @@ calculate_path_impl(const _PyCoreConfig *core_config,
return err;
}
calculate_reduce_prefix(calculate, prefix);
err = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix));
if (_Py_INIT_FAILED(err)) {
return err;
}
config->prefix = _PyMem_RawWcsdup(prefix);
if (config->prefix == NULL) {
return _Py_INIT_NO_MEMORY();
}
calculate_reduce_exec_prefix(calculate, exec_prefix);
err = calculate_reduce_exec_prefix(calculate,
exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
if (_Py_INIT_FAILED(err)) {
return err;
}
config->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
if (config->exec_prefix == NULL) {