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

@ -0,0 +1,2 @@
Python initialization now fails with an error, rather than silently
truncating paths, if a path is too long.

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) {

View File

@ -1716,7 +1716,7 @@ _Py_wrealpath(const wchar_t *path,
}
#endif
/* Get the current directory. size is the buffer size in wide characters
/* Get the current directory. buflen is the buffer size in wide characters
including the null character. Decode the path from the locale encoding.
Return NULL on getcwd() error, on decoding error, or if 'buf' is

View File

@ -578,8 +578,8 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
int have_script_arg = 0;
int have_module_arg = 0;
#ifdef HAVE_READLINK
wchar_t link[MAXPATHLEN+1];
wchar_t argv0copy[2*MAXPATHLEN+1];
wchar_t link[MAXPATHLEN + 1];
wchar_t argv0copy[2 * MAXPATHLEN + 1];
int nr = 0;
#endif
#if defined(HAVE_REALPATH)
@ -607,7 +607,7 @@ _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
#ifdef HAVE_READLINK
if (have_script_arg)
nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
nr = _Py_wreadlink(argv0, link, Py_ARRAY_LENGTH(link));
if (nr > 0) {
/* It's a symlink */
link[nr] = '\0';
@ -692,11 +692,12 @@ _Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
wchar_t *value, size_t value_size)
{
int result = 0; /* meaning not found */
char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
fseek(env_file, 0, SEEK_SET);
while (!feof(env_file)) {
char * p = fgets(buffer, MAXPATHLEN*2, env_file);
char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
if (p == NULL) {
break;
@ -721,7 +722,8 @@ _Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
if ((tok != NULL) && !wcscmp(tok, L"=")) {
tok = WCSTOK(NULL, L"\r\n", &state);
if (tok != NULL) {
wcsncpy(value, tok, MAXPATHLEN);
wcsncpy(value, tok, value_size - 1);
value[value_size - 1] = L'\0';
result = 1;
PyMem_RawFree(tmpbuffer);
break;