bpo-38353: getpath.c: allocates strings on the heap (GH-16585)

* _Py_FindEnvConfigValue() now returns a string allocated
  by PyMem_RawMalloc().
* calculate_init() now decodes VPATH macro.
* Add calculate_open_pyenv() function.
* Add substring() and joinpath2() functions.

* Fix add_exe_suffix()

And a few cleanup changes.
This commit is contained in:
Victor Stinner 2019-10-04 19:53:43 +02:00 committed by GitHub
parent abd7cd856b
commit c02b41b1fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 427 additions and 319 deletions

View file

@ -56,11 +56,10 @@ extern PyStatus _PyPathConfig_Calculate(
extern int _PyPathConfig_ComputeSysPath0(
const PyWideStringList *argv,
PyObject **path0);
extern int _Py_FindEnvConfigValue(
extern PyStatus _Py_FindEnvConfigValue(
FILE *env_file,
const wchar_t *key,
wchar_t *value,
size_t value_size);
wchar_t **value_p);
#ifdef MS_WINDOWS
extern wchar_t* _Py_GetDLLPath(void);

File diff suppressed because it is too large Load diff

View file

@ -752,7 +752,7 @@ calculate_pth_file(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
executable's directory and then in the parent directory.
If found, open it for use when searching for prefixes.
*/
static void
static PyStatus
calculate_pyvenv_file(PyCalculatePath *calculate,
wchar_t *argv0_path, size_t argv0_path_len)
{
@ -775,17 +775,23 @@ calculate_pyvenv_file(PyCalculatePath *calculate,
env_file = _Py_wfopen(filename, L"r");
if (env_file == NULL) {
errno = 0;
return;
return _PyStatus_OK();
}
}
/* Look for a 'home' variable and set argv0_path to it, if found */
wchar_t home[MAXPATHLEN+1];
if (_Py_FindEnvConfigValue(env_file, L"home",
home, Py_ARRAY_LENGTH(home))) {
wchar_t *home = NULL;
PyStatus status = _Py_FindEnvConfigValue(env_file, L"home", &home);
if (_PyStatus_EXCEPTION(status)) {
fclose(env_file);
return status;
}
if (home) {
wcscpy_s(argv0_path, argv0_path_len, home);
PyMem_RawFree(home);
}
fclose(env_file);
return _PyStatus_OK();
}
@ -1022,7 +1028,11 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
goto done;
}
calculate_pyvenv_file(calculate, argv0_path, Py_ARRAY_LENGTH(argv0_path));
status = calculate_pyvenv_file(calculate,
argv0_path, Py_ARRAY_LENGTH(argv0_path));
if (_PyStatus_EXCEPTION(status)) {
return status;
}
/* Calculate zip archive path from DLL or exe path */
wchar_t zip_path[MAXPATHLEN+1];

View file

@ -777,12 +777,17 @@ _PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
#endif
/* Search for a prefix value in an environment file (pyvenv.cfg).
If found, copy it into the provided buffer. */
int
- If found, copy it into *value_p: string which must be freed by
PyMem_RawFree().
- If not found, *value_p is set to NULL.
*/
PyStatus
_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
wchar_t *value, size_t value_size)
wchar_t **value_p)
{
int result = 0; /* meaning not found */
*value_p = NULL;
char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
@ -812,18 +817,24 @@ _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, value_size - 1);
value[value_size - 1] = L'\0';
result = 1;
*value_p = _PyMem_RawWcsdup(tok);
PyMem_RawFree(tmpbuffer);
break;
if (*value_p == NULL) {
return _PyStatus_NO_MEMORY();
}
/* found */
return _PyStatus_OK();
}
}
}
PyMem_RawFree(tmpbuffer);
}
}
return result;
/* not found */
return _PyStatus_OK();
}
#ifdef __cplusplus