summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-03-19 01:58:14 (GMT)
committerGitHub <noreply@github.com>2019-03-19 01:58:14 (GMT)
commitfaddaedd05ca81a9fed3f315e7bc8dcf455824a2 (patch)
tree90679ab39bba190bd5cfa055ae3f564255d29495 /Modules
parent5f9cf23502febe0eb3bc02e45c7d2bfc79424757 (diff)
downloadcpython-faddaedd05ca81a9fed3f315e7bc8dcf455824a2.zip
cpython-faddaedd05ca81a9fed3f315e7bc8dcf455824a2.tar.gz
cpython-faddaedd05ca81a9fed3f315e7bc8dcf455824a2.tar.bz2
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.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/getpath.c384
1 files changed, 234 insertions, 150 deletions
diff --git a/Modules/getpath.c b/Modules/getpath.c
index 4364317..dd188c6 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -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);
+ if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
+ return _Py_INIT_OK();
+ }
- wcsncpy(progpath+n, EXE_SUFFIX, s);
- progpath[n+s] = '\0';
+ 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 */
- wcsncpy(progpath, orig, MAXPATHLEN);
- }
+ 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) {