[Python-checkins] bpo-36763: Add _PyCoreConfig_SetString() (GH-13035)

Victor Stinner webhook-mailer at python.org
Wed May 1 09:23:03 EDT 2019


https://github.com/python/cpython/commit/1a9f0d8efded4bf37c864ed572beff28c43c7c77
commit: 1a9f0d8efded4bf37c864ed572beff28c43c7c77
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-05-01T15:22:52+02:00
summary:

bpo-36763: Add _PyCoreConfig_SetString() (GH-13035)

Add 3 new config methods:

* _PyCoreConfig_SetString()
* _PyCoreConfig_SetWideString()
* _PyCoreConfig_SetWideStringFromString()

Changes:

* _PyCoreConfig_Copy() returns _PyInitError.
* Add CONFIG_GET_ENV_DUP().

files:
M Include/internal/pycore_coreconfig.h
M Python/coreconfig.c
M Python/pylifecycle.c

diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h
index b1d02eef4513..8af310d2b0ce 100644
--- a/Include/internal/pycore_coreconfig.h
+++ b/Include/internal/pycore_coreconfig.h
@@ -102,16 +102,24 @@ PyAPI_FUNC(_PyInitError) _PyPreConfig_Write(_PyPreConfig *config);
 /* --- _PyCoreConfig ---------------------------------------------- */
 
 PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
-PyAPI_FUNC(int) _PyCoreConfig_Copy(
+PyAPI_FUNC(_PyInitError) _PyCoreConfig_Copy(
     _PyCoreConfig *config,
     const _PyCoreConfig *config2);
+PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetString(
+    char **config_str,
+    const char *str);
+PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideString(
+    wchar_t **config_str,
+    const wchar_t *str);
+PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideStringFromString(
+    wchar_t **config_str,
+    const char *str);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPathConfig(_PyCoreConfig *config);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig(
     const _PyCoreConfig *config);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config);
 PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config,
     _PyRuntimeState *runtime);
-
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPyArgv(
     _PyCoreConfig *config,
     const _PyArgv *args);
diff --git a/Python/coreconfig.c b/Python/coreconfig.c
index 4bfe745ce449..7f388cbcdd0e 100644
--- a/Python/coreconfig.c
+++ b/Python/coreconfig.c
@@ -520,34 +520,111 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
 }
 
 
-int
+/* Copy str into *config_str (duplicate the string) */
+_PyInitError
+_PyCoreConfig_SetString(char **config_str, const char *str)
+{
+    char *str2;
+    if (str != NULL) {
+        str2 = _PyMem_RawStrdup(str);
+        if (str2 == NULL) {
+            return _Py_INIT_NO_MEMORY();
+        }
+    }
+    else {
+        str2 = NULL;
+    }
+    PyMem_RawFree(*config_str);
+    *config_str = str2;
+    return _Py_INIT_OK();
+}
+
+
+/* Copy str into *config_str (duplicate the string) */
+_PyInitError
+_PyCoreConfig_SetWideString(wchar_t **config_str, const wchar_t *str)
+{
+    wchar_t *str2;
+    if (str != NULL) {
+        str2 = _PyMem_RawWcsdup(str);
+        if (str2 == NULL) {
+            return _Py_INIT_NO_MEMORY();
+        }
+    }
+    else {
+        str2 = NULL;
+    }
+    PyMem_RawFree(*config_str);
+    *config_str = str2;
+    return _Py_INIT_OK();
+}
+
+
+/* Decode str using Py_DecodeLocale() and set the result into *config_str */
+static _PyInitError
+_PyCoreConfig_SetWideStringFromStringErr(wchar_t **config_str, const char *str,
+                                         const char *decode_err_msg)
+{
+    wchar_t *str2;
+    if (str != NULL) {
+        size_t len;
+        str2 = Py_DecodeLocale(str, &len);
+        if (str2 == NULL) {
+            if (len == (size_t)-2) {
+                return _Py_INIT_ERR(decode_err_msg);
+            }
+            else {
+                return  _Py_INIT_NO_MEMORY();
+            }
+        }
+    }
+    else {
+        str2 = NULL;
+    }
+    PyMem_RawFree(*config_str);
+    *config_str = str2;
+    return _Py_INIT_OK();
+}
+
+
+_PyInitError
+_PyCoreConfig_SetWideStringFromString(wchar_t **config_str, const char *str)
+{
+    return _PyCoreConfig_SetWideStringFromStringErr(
+                config_str, str, "cannot decode string");
+}
+
+
+#define CONFIG_DECODE_LOCALE(config_str, str, NAME) \
+    _PyCoreConfig_SetWideStringFromStringErr(config_str, str, \
+                                             "cannot decode " NAME)
+
+
+_PyInitError
 _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
 {
+    _PyInitError err;
     _PyCoreConfig_Clear(config);
 
 #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
 #define COPY_STR_ATTR(ATTR) \
     do { \
-        if (config2->ATTR != NULL) { \
-            config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
-            if (config->ATTR == NULL) { \
-                return -1; \
-            } \
+        err = _PyCoreConfig_SetString(&config->ATTR, config2->ATTR); \
+        if (_Py_INIT_FAILED(err)) { \
+            return err; \
         } \
     } while (0)
 #define COPY_WSTR_ATTR(ATTR) \
     do { \
-        if (config2->ATTR != NULL) { \
-            config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \
-            if (config->ATTR == NULL) { \
-                return -1; \
-            } \
+        err = _PyCoreConfig_SetWideString(&config->ATTR, config2->ATTR); \
+        if (_Py_INIT_FAILED(err)) { \
+            return err; \
         } \
     } while (0)
 #define COPY_WSTRLIST(LIST) \
     do { \
         if (_PyWstrList_Copy(&config->LIST, &config2->LIST) < 0 ) { \
-            return -1; \
+            return _Py_INIT_NO_MEMORY(); \
         } \
     } while (0)
 
@@ -617,7 +694,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
 #undef COPY_STR_ATTR
 #undef COPY_WSTR_ATTR
 #undef COPY_WSTRLIST
-    return 0;
+    return _Py_INIT_OK();
 }
 
 
@@ -746,54 +823,44 @@ _PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name)
 /* Get a copy of the environment variable as wchar_t*.
    Return 0 on success, but *dest can be NULL.
    Return -1 on memory allocation failure. Return -2 on decoding error. */
-static int
+static _PyInitError
 _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config,
                         wchar_t **dest,
-                        wchar_t *wname, char *name)
+                        wchar_t *wname, char *name,
+                        const char *decode_err_msg)
 {
+    assert(*dest == NULL);
     assert(config->use_environment >= 0);
 
     if (!config->use_environment) {
         *dest = NULL;
-        return 0;
+        return _Py_INIT_OK();
     }
 
 #ifdef MS_WINDOWS
     const wchar_t *var = _wgetenv(wname);
     if (!var || var[0] == '\0') {
         *dest = NULL;
-        return 0;
-    }
-
-    wchar_t *copy = _PyMem_RawWcsdup(var);
-    if (copy == NULL) {
-        return -1;
+        return _Py_INIT_OK();
     }
 
-    *dest = copy;
+    return _PyCoreConfig_SetWideString(dest, var);
 #else
     const char *var = getenv(name);
     if (!var || var[0] == '\0') {
         *dest = NULL;
-        return 0;
+        return _Py_INIT_OK();
     }
 
-    size_t len;
-    wchar_t *wvar = Py_DecodeLocale(var, &len);
-    if (!wvar) {
-        if (len == (size_t)-2) {
-            return -2;
-        }
-        else {
-            return -1;
-        }
-    }
-    *dest = wvar;
+    return _PyCoreConfig_SetWideStringFromStringErr(dest, var, decode_err_msg);
 #endif
-    return 0;
 }
 
 
+#define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \
+    _PyCoreConfig_GetEnvDup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME)
+
+
 static void
 _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config)
 {
@@ -876,6 +943,7 @@ _PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config)
 static _PyInitError
 config_init_program_name(_PyCoreConfig *config)
 {
+    _PyInitError err;
     assert(config->program_name == NULL);
 
     /* If Py_SetProgramName() was called, use its value */
@@ -900,13 +968,11 @@ config_init_program_name(_PyCoreConfig *config)
        script. */
     const char *p = _PyCoreConfig_GetEnv(config, "PYTHONEXECUTABLE");
     if (p != NULL) {
-        size_t len;
-        wchar_t* program_name = Py_DecodeLocale(p, &len);
-        if (program_name == NULL) {
-            return DECODE_LOCALE_ERR("PYTHONEXECUTABLE environment "
-                                     "variable", (Py_ssize_t)len);
+        err = CONFIG_DECODE_LOCALE(&config->program_name, p,
+                                   "PYTHONEXECUTABLE environment variable");
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
-        config->program_name = program_name;
         return _Py_INIT_OK();
     }
 #ifdef WITH_NEXT_FRAMEWORK
@@ -916,13 +982,11 @@ config_init_program_name(_PyCoreConfig *config)
             /* Used by Mac/Tools/pythonw.c to forward
              * the argv0 of the stub executable
              */
-            size_t len;
-            wchar_t* program_name = Py_DecodeLocale(pyvenv_launcher, &len);
-            if (program_name == NULL) {
-                return DECODE_LOCALE_ERR("__PYVENV_LAUNCHER__ environment "
-                                         "variable", (Py_ssize_t)len);
+            err = CONFIG_DECODE_LOCALE(&config->program_name, pyvenv_launcher,
+                                       "__PYVENV_LAUNCHER__ environment variable");
+            if (_Py_INIT_FAILED(err)) {
+                return err;
             }
-            config->program_name = program_name;
             return _Py_INIT_OK();
         }
     }
@@ -931,9 +995,10 @@ config_init_program_name(_PyCoreConfig *config)
 
     /* Use argv[0] by default, if available */
     if (config->program != NULL) {
-        config->program_name = _PyMem_RawWcsdup(config->program);
-        if (config->program_name == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        err = _PyCoreConfig_SetWideString(&config->program_name,
+                                          config->program);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
         return _Py_INIT_OK();
     }
@@ -944,9 +1009,9 @@ config_init_program_name(_PyCoreConfig *config)
 #else
     const wchar_t *default_program_name = L"python3";
 #endif
-    config->program_name = _PyMem_RawWcsdup(default_program_name);
-    if (config->program_name == NULL) {
-        return _Py_INIT_NO_MEMORY();
+    err = _PyCoreConfig_SetWideString(&config->program_name, default_program_name);
+    if (_Py_INIT_FAILED(err)) {
+        return err;
     }
     return _Py_INIT_OK();
 }
@@ -959,13 +1024,13 @@ config_init_executable(_PyCoreConfig *config)
     /* If Py_SetProgramFullPath() was called, use its value */
     const wchar_t *program_full_path = _Py_path_config.program_full_path;
     if (program_full_path != NULL) {
-        config->executable = _PyMem_RawWcsdup(program_full_path);
-        if (config->executable == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        _PyInitError err = _PyCoreConfig_SetWideString(&config->executable,
+                                                       program_full_path);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
         return _Py_INIT_OK();
     }
-
     return _Py_INIT_OK();
 }
 
@@ -985,20 +1050,15 @@ config_init_home(_PyCoreConfig *config)
     /* If Py_SetPythonHome() was called, use its value */
     wchar_t *home = _Py_path_config.home;
     if (home) {
-        config->home = _PyMem_RawWcsdup(home);
-        if (config->home == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        _PyInitError err = _PyCoreConfig_SetWideString(&config->home, home);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
         return _Py_INIT_OK();
     }
 
-    int res = _PyCoreConfig_GetEnvDup(config, &home,
-                                      L"PYTHONHOME", "PYTHONHOME");
-    if (res < 0) {
-        return DECODE_LOCALE_ERR("PYTHONHOME", res);
-    }
-    config->home = home;
-    return _Py_INIT_OK();
+    return CONFIG_GET_ENV_DUP(config, &config->home,
+                              L"PYTHONHOME", "PYTHONHOME");
 }
 
 
@@ -1055,6 +1115,7 @@ config_wstr_to_int(const wchar_t *wstr, int *result)
 static _PyInitError
 config_read_env_vars(_PyCoreConfig *config)
 {
+    _PyInitError err;
     int use_env = config->use_environment;
 
     /* Get environment variables */
@@ -1094,17 +1155,15 @@ config_read_env_vars(_PyCoreConfig *config)
     }
 
     if (config->module_search_path_env == NULL) {
-        wchar_t *path;
-        int res = _PyCoreConfig_GetEnvDup(config, &path,
-                                          L"PYTHONPATH", "PYTHONPATH");
-        if (res < 0) {
-            return DECODE_LOCALE_ERR("PYTHONPATH", res);
+        err = CONFIG_GET_ENV_DUP(config, &config->module_search_path_env,
+                                 L"PYTHONPATH", "PYTHONPATH");
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
-        config->module_search_path_env = path;
     }
 
     if (config->use_hash_seed < 0) {
-        _PyInitError err = config_init_hash_seed(config);
+        err = config_init_hash_seed(config);
         if (_Py_INIT_FAILED(err)) {
             return err;
         }
@@ -1174,24 +1233,16 @@ config_init_pycache_prefix(_PyCoreConfig *config)
             }
         }
         else {
-            // -X pycache_prefix= can cancel the env var
+            // PYTHONPYCACHEPREFIX env var ignored
+            // if "-X pycache_prefix=" option is used
             config->pycache_prefix = NULL;
         }
+        return _Py_INIT_OK();
     }
-    else {
-        wchar_t *env;
-        int res = _PyCoreConfig_GetEnvDup(config, &env,
-                                          L"PYTHONPYCACHEPREFIX",
-                                          "PYTHONPYCACHEPREFIX");
-        if (res < 0) {
-            return DECODE_LOCALE_ERR("PYTHONPYCACHEPREFIX", res);
-        }
 
-        if (env) {
-            config->pycache_prefix = env;
-        }
-    }
-    return _Py_INIT_OK();
+    return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix,
+                              L"PYTHONPYCACHEPREFIX",
+                              "PYTHONPYCACHEPREFIX");
 }
 
 
@@ -1270,11 +1321,9 @@ config_get_locale_encoding(char **locale_encoding)
                             "nl_langinfo(CODESET) failed");
     }
 #endif
-    *locale_encoding = _PyMem_RawStrdup(encoding);
-    if (*locale_encoding == NULL) {
-        return _Py_INIT_NO_MEMORY();
-    }
-    return _Py_INIT_OK();
+
+    assert(*locale_encoding == NULL);
+    return _PyCoreConfig_SetString(locale_encoding, encoding);
 }
 
 
@@ -1282,19 +1331,23 @@ static _PyInitError
 config_init_stdio_encoding(_PyCoreConfig *config,
                            const _PyPreConfig *preconfig)
 {
+    _PyInitError err;
+
     /* If Py_SetStandardStreamEncoding() have been called, use these
         parameters. */
     if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) {
-        config->stdio_encoding = _PyMem_RawStrdup(_Py_StandardStreamEncoding);
-        if (config->stdio_encoding == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        err = _PyCoreConfig_SetString(&config->stdio_encoding,
+                                      _Py_StandardStreamEncoding);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
     }
 
     if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) {
-        config->stdio_errors = _PyMem_RawStrdup(_Py_StandardStreamErrors);
-        if (config->stdio_errors == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        err = _PyCoreConfig_SetString(&config->stdio_errors,
+                                      _Py_StandardStreamErrors);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
     }
 
@@ -1305,27 +1358,30 @@ config_init_stdio_encoding(_PyCoreConfig *config,
     /* PYTHONIOENCODING environment variable */
     const char *opt = _PyCoreConfig_GetEnv(config, "PYTHONIOENCODING");
     if (opt) {
-        char *pythonioencoding = _PyMem_RawStrdup(opt);
-        if (pythonioencoding == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        /* _PyCoreConfig_SetString() requires dest to be initialized to NULL */
+        char *pythonioencoding = NULL;
+        err = _PyCoreConfig_SetString(&pythonioencoding, opt);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
 
-        char *err = strchr(pythonioencoding, ':');
-        if (err) {
-            *err = '\0';
-            err++;
-            if (!err[0]) {
-                err = NULL;
+        char *errors = strchr(pythonioencoding, ':');
+        if (errors) {
+            *errors = '\0';
+            errors++;
+            if (!errors[0]) {
+                errors = NULL;
             }
         }
 
         /* Does PYTHONIOENCODING contain an encoding? */
         if (pythonioencoding[0]) {
             if (config->stdio_encoding == NULL) {
-                config->stdio_encoding = _PyMem_RawStrdup(pythonioencoding);
-                if (config->stdio_encoding == NULL) {
+                err = _PyCoreConfig_SetString(&config->stdio_encoding,
+                                              pythonioencoding);
+                if (_Py_INIT_FAILED(err)) {
                     PyMem_RawFree(pythonioencoding);
-                    return _Py_INIT_NO_MEMORY();
+                    return err;
                 }
             }
 
@@ -1333,16 +1389,16 @@ config_init_stdio_encoding(_PyCoreConfig *config,
                use "strict" error handler by default.
                PYTHONIOENCODING=latin1 behaves as
                PYTHONIOENCODING=latin1:strict. */
-            if (!err) {
-                err = "strict";
+            if (!errors) {
+                errors = "strict";
             }
         }
 
-        if (config->stdio_errors == NULL && err != NULL) {
-            config->stdio_errors = _PyMem_RawStrdup(err);
-            if (config->stdio_errors == NULL) {
+        if (config->stdio_errors == NULL && errors != NULL) {
+            err = _PyCoreConfig_SetString(&config->stdio_errors, errors);
+            if (_Py_INIT_FAILED(err)) {
                 PyMem_RawFree(pythonioencoding);
-                return _Py_INIT_NO_MEMORY();
+                return err;
             }
         }
 
@@ -1352,31 +1408,35 @@ config_init_stdio_encoding(_PyCoreConfig *config,
     /* UTF-8 Mode uses UTF-8/surrogateescape */
     if (preconfig->utf8_mode) {
         if (config->stdio_encoding == NULL) {
-            config->stdio_encoding = _PyMem_RawStrdup("utf-8");
-            if (config->stdio_encoding == NULL) {
-                return _Py_INIT_NO_MEMORY();
+            err = _PyCoreConfig_SetString(&config->stdio_encoding,
+                                          "utf-8");
+            if (_Py_INIT_FAILED(err)) {
+                return err;
             }
         }
         if (config->stdio_errors == NULL) {
-            config->stdio_errors = _PyMem_RawStrdup("surrogateescape");
-            if (config->stdio_errors == NULL) {
-                return _Py_INIT_NO_MEMORY();
+            err = _PyCoreConfig_SetString(&config->stdio_errors,
+                                          "surrogateescape");
+            if (_Py_INIT_FAILED(err)) {
+                return err;
             }
         }
     }
 
     /* Choose the default error handler based on the current locale. */
     if (config->stdio_encoding == NULL) {
-        _PyInitError err = config_get_locale_encoding(&config->stdio_encoding);
+        err = config_get_locale_encoding(&config->stdio_encoding);
         if (_Py_INIT_FAILED(err)) {
             return err;
         }
     }
     if (config->stdio_errors == NULL) {
         const char *errors = config_get_stdio_errors(config);
-        config->stdio_errors = _PyMem_RawStrdup(errors);
-        if (config->stdio_errors == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        assert(errors != NULL);
+
+        err = _PyCoreConfig_SetString(&config->stdio_errors, errors);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
     }
 
@@ -1387,19 +1447,23 @@ config_init_stdio_encoding(_PyCoreConfig *config,
 static _PyInitError
 config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig)
 {
+    _PyInitError err;
+
 #ifdef MS_WINDOWS
     if (preconfig->legacy_windows_fs_encoding) {
         /* Legacy Windows filesystem encoding: mbcs/replace */
         if (config->filesystem_encoding == NULL) {
-            config->filesystem_encoding = _PyMem_RawStrdup("mbcs");
-            if (config->filesystem_encoding == NULL) {
-                return _Py_INIT_NO_MEMORY();
+            err = _PyCoreConfig_SetString(&config->filesystem_encoding,
+                                          "mbcs");
+            if (_Py_INIT_FAILED(err)) {
+                return err;
             }
         }
         if (config->filesystem_errors == NULL) {
-            config->filesystem_errors = _PyMem_RawStrdup("replace");
-            if (config->filesystem_errors == NULL) {
-                return _Py_INIT_NO_MEMORY();
+            err = _PyCoreConfig_SetString(&config->filesystem_errors,
+                                          "replace");
+            if (_Py_INIT_FAILED(err)) {
+                return err;
             }
         }
     }
@@ -1409,51 +1473,54 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig)
        Note: UTF-8 Mode takes the same code path and the Legacy Windows FS
              encoding has the priortiy over UTF-8 Mode. */
     if (config->filesystem_encoding == NULL) {
-        config->filesystem_encoding = _PyMem_RawStrdup("utf-8");
-        if (config->filesystem_encoding == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        err = _PyCoreConfig_SetString(&config->filesystem_encoding,
+                                      "utf-8");
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
     }
 
     if (config->filesystem_errors == NULL) {
-        config->filesystem_errors = _PyMem_RawStrdup("surrogatepass");
-        if (config->filesystem_errors == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        err = _PyCoreConfig_SetString(&config->filesystem_errors,
+                                      "surrogatepass");
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
     }
 #else
     if (config->filesystem_encoding == NULL) {
         if (preconfig->utf8_mode) {
             /* UTF-8 Mode use: utf-8/surrogateescape */
-            config->filesystem_encoding = _PyMem_RawStrdup("utf-8");
+            err = _PyCoreConfig_SetString(&config->filesystem_encoding,
+                                          "utf-8");
             /* errors defaults to surrogateescape above */
         }
         else if (_Py_GetForceASCII()) {
-            config->filesystem_encoding = _PyMem_RawStrdup("ascii");
+            err = _PyCoreConfig_SetString(&config->filesystem_encoding,
+                                          "ascii");
         }
         else {
             /* macOS and Android use UTF-8,
                other platforms use the locale encoding. */
 #if defined(__APPLE__) || defined(__ANDROID__)
-            config->filesystem_encoding = _PyMem_RawStrdup("utf-8");
+            err = _PyCoreConfig_SetString(&config->filesystem_encoding,
+                                          "utf-8");
 #else
-            _PyInitError err = config_get_locale_encoding(&config->filesystem_encoding);
-            if (_Py_INIT_FAILED(err)) {
-                return err;
-            }
+            err = config_get_locale_encoding(&config->filesystem_encoding);
 #endif
         }
 
-        if (config->filesystem_encoding == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
     }
 
     if (config->filesystem_errors == NULL) {
         /* by default, use the "surrogateescape" error handler */
-        config->filesystem_errors = _PyMem_RawStrdup("surrogateescape");
-        if (config->filesystem_errors == NULL) {
-            return _Py_INIT_NO_MEMORY();
+        err = _PyCoreConfig_SetString(&config->filesystem_errors,
+                                      "surrogateescape");
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
     }
 #endif
@@ -1828,13 +1895,16 @@ config_parse_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline,
 static _PyInitError
 config_init_env_warnoptions(const _PyCoreConfig *config, _PyWstrList *warnoptions)
 {
-    wchar_t *env;
-    int res = _PyCoreConfig_GetEnvDup(config, &env,
-                                      L"PYTHONWARNINGS", "PYTHONWARNINGS");
-    if (res < 0) {
-        return DECODE_LOCALE_ERR("PYTHONWARNINGS", res);
+    _PyInitError err;
+    /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */
+    wchar_t *env = NULL;
+    err = CONFIG_GET_ENV_DUP(config, &env,
+                             L"PYTHONWARNINGS", "PYTHONWARNINGS");
+    if (_Py_INIT_FAILED(err)) {
+        return err;
     }
 
+    /* env var is not set or is empty */
     if (env == NULL) {
         return _Py_INIT_OK();
     }
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index c874a509aa55..afa683b7e841 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -472,6 +472,7 @@ _Py_Initialize_ReconfigureCore(_PyRuntimeState *runtime,
                                PyInterpreterState **interp_p,
                                const _PyCoreConfig *core_config)
 {
+    _PyInitError err;
     PyThreadState *tstate = _PyThreadState_GET();
     if (!tstate) {
         return _Py_INIT_ERR("failed to read thread state");
@@ -485,13 +486,14 @@ _Py_Initialize_ReconfigureCore(_PyRuntimeState *runtime,
 
     _PyCoreConfig_Write(core_config, runtime);
 
-    if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) {
-        return _Py_INIT_NO_MEMORY();
+    err = _PyCoreConfig_Copy(&interp->core_config, core_config);
+    if (_Py_INIT_FAILED(err)) {
+        return err;
     }
     core_config = &interp->core_config;
 
     if (core_config->_install_importlib) {
-        _PyInitError err = _PyCoreConfig_SetPathConfig(core_config);
+        err = _PyCoreConfig_SetPathConfig(core_config);
         if (_Py_INIT_FAILED(err)) {
             return err;
         }
@@ -545,8 +547,9 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
     }
     *interp_p = interp;
 
-    if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) {
-        return _Py_INIT_NO_MEMORY();
+    _PyInitError err = _PyCoreConfig_Copy(&interp->core_config, core_config);
+    if (_Py_INIT_FAILED(err)) {
+        return err;
     }
     core_config = &interp->core_config;
 
@@ -804,8 +807,9 @@ pyinit_coreconfig(_PyRuntimeState *runtime,
     _PyInitError err;
 
     if (src_config) {
-        if (_PyCoreConfig_Copy(config, src_config) < 0) {
-            return _Py_INIT_NO_MEMORY();
+        err = _PyCoreConfig_Copy(config, src_config);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
         }
     }
 
@@ -1433,8 +1437,9 @@ new_interpreter(PyThreadState **tstate_p)
         core_config = &main_interp->core_config;
     }
 
-    if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) {
-        return _Py_INIT_NO_MEMORY();
+    err = _PyCoreConfig_Copy(&interp->core_config, core_config);
+    if (_Py_INIT_FAILED(err)) {
+        return err;
     }
     core_config = &interp->core_config;
 



More information about the Python-checkins mailing list