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( extern int _PyPathConfig_ComputeSysPath0(
const PyWideStringList *argv, const PyWideStringList *argv,
PyObject **path0); PyObject **path0);
extern int _Py_FindEnvConfigValue( extern PyStatus _Py_FindEnvConfigValue(
FILE *env_file, FILE *env_file,
const wchar_t *key, const wchar_t *key,
wchar_t *value, wchar_t **value_p);
size_t value_size);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
extern wchar_t* _Py_GetDLLPath(void); 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. executable's directory and then in the parent directory.
If found, open it for use when searching for prefixes. If found, open it for use when searching for prefixes.
*/ */
static void static PyStatus
calculate_pyvenv_file(PyCalculatePath *calculate, calculate_pyvenv_file(PyCalculatePath *calculate,
wchar_t *argv0_path, size_t argv0_path_len) 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"); env_file = _Py_wfopen(filename, L"r");
if (env_file == NULL) { if (env_file == NULL) {
errno = 0; errno = 0;
return; return _PyStatus_OK();
} }
} }
/* Look for a 'home' variable and set argv0_path to it, if found */ /* Look for a 'home' variable and set argv0_path to it, if found */
wchar_t home[MAXPATHLEN+1]; wchar_t *home = NULL;
if (_Py_FindEnvConfigValue(env_file, L"home", PyStatus status = _Py_FindEnvConfigValue(env_file, L"home", &home);
home, Py_ARRAY_LENGTH(home))) { if (_PyStatus_EXCEPTION(status)) {
fclose(env_file);
return status;
}
if (home) {
wcscpy_s(argv0_path, argv0_path_len, home); wcscpy_s(argv0_path, argv0_path_len, home);
PyMem_RawFree(home);
} }
fclose(env_file); fclose(env_file);
return _PyStatus_OK();
} }
@ -1022,7 +1028,11 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
goto done; 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 */ /* Calculate zip archive path from DLL or exe path */
wchar_t zip_path[MAXPATHLEN+1]; wchar_t zip_path[MAXPATHLEN+1];

View file

@ -777,12 +777,17 @@ _PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
#endif #endif
/* Search for a prefix value in an environment file (pyvenv.cfg). /* 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, _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. */ char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0'; 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"=")) { if ((tok != NULL) && !wcscmp(tok, L"=")) {
tok = WCSTOK(NULL, L"\r\n", &state); tok = WCSTOK(NULL, L"\r\n", &state);
if (tok != NULL) { if (tok != NULL) {
wcsncpy(value, tok, value_size - 1); *value_p = _PyMem_RawWcsdup(tok);
value[value_size - 1] = L'\0';
result = 1;
PyMem_RawFree(tmpbuffer); PyMem_RawFree(tmpbuffer);
break;
if (*value_p == NULL) {
return _PyStatus_NO_MEMORY();
}
/* found */
return _PyStatus_OK();
} }
} }
} }
PyMem_RawFree(tmpbuffer); PyMem_RawFree(tmpbuffer);
} }
} }
return result;
/* not found */
return _PyStatus_OK();
} }
#ifdef __cplusplus #ifdef __cplusplus