mirror of https://github.com/python/cpython
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:
parent
5f9cf23502
commit
faddaedd05
|
@ -0,0 +1,2 @@
|
|||
Python initialization now fails with an error, rather than silently
|
||||
truncating paths, if a path is too long.
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue