• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "Python.h"
2 #include "pycore_fileutils.h"     // _Py_HasFileSystemDefaultEncodeErrors
3 #include "pycore_getopt.h"        // _PyOS_GetOpt()
4 #include "pycore_initconfig.h"    // _PyStatus_OK()
5 #include "pycore_interp.h"        // _PyInterpreterState.runtime
6 #include "pycore_long.h"          // _PY_LONG_MAX_STR_DIGITS_THRESHOLD
7 #include "pycore_pathconfig.h"    // _Py_path_config
8 #include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
9 #include "pycore_pylifecycle.h"   // _Py_PreInitializeFromConfig()
10 #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator()
11 #include "pycore_pystate.h"       // _PyThreadState_GET()
12 #include "pycore_pystats.h"       // _Py_StatsOn()
13 
14 #include "osdefs.h"               // DELIM
15 
16 #include <locale.h>               // setlocale()
17 #include <stdlib.h>               // getenv()
18 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
19 #  ifdef HAVE_IO_H
20 #    include <io.h>
21 #  endif
22 #  ifdef HAVE_FCNTL_H
23 #    include <fcntl.h>            // O_BINARY
24 #  endif
25 #endif
26 
27 #include "config_common.h"
28 
29 
30 /* --- PyConfig spec ---------------------------------------------- */
31 
32 typedef enum {
33     PyConfig_MEMBER_INT = 0,
34     PyConfig_MEMBER_UINT = 1,
35     PyConfig_MEMBER_ULONG = 2,
36     PyConfig_MEMBER_BOOL = 3,
37 
38     PyConfig_MEMBER_WSTR = 10,
39     PyConfig_MEMBER_WSTR_OPT = 11,
40     PyConfig_MEMBER_WSTR_LIST = 12,
41 } PyConfigMemberType;
42 
43 typedef struct {
44     const char *name;
45     size_t offset;
46     PyConfigMemberType type;
47 } PyConfigSpec;
48 
49 #define SPEC(MEMBER, TYPE) \
50     {#MEMBER, offsetof(PyConfig, MEMBER), PyConfig_MEMBER_##TYPE}
51 
52 // Update _test_embed_set_config when adding new members
53 static const PyConfigSpec PYCONFIG_SPEC[] = {
54     SPEC(_config_init, UINT),
55     SPEC(isolated, BOOL),
56     SPEC(use_environment, BOOL),
57     SPEC(dev_mode, BOOL),
58     SPEC(install_signal_handlers, BOOL),
59     SPEC(use_hash_seed, BOOL),
60     SPEC(hash_seed, ULONG),
61     SPEC(faulthandler, BOOL),
62     SPEC(tracemalloc, UINT),
63     SPEC(perf_profiling, UINT),
64     SPEC(import_time, BOOL),
65     SPEC(code_debug_ranges, BOOL),
66     SPEC(show_ref_count, BOOL),
67     SPEC(dump_refs, BOOL),
68     SPEC(dump_refs_file, WSTR_OPT),
69     SPEC(malloc_stats, BOOL),
70     SPEC(filesystem_encoding, WSTR),
71     SPEC(filesystem_errors, WSTR),
72     SPEC(pycache_prefix, WSTR_OPT),
73     SPEC(parse_argv, BOOL),
74     SPEC(orig_argv, WSTR_LIST),
75     SPEC(argv, WSTR_LIST),
76     SPEC(xoptions, WSTR_LIST),
77     SPEC(warnoptions, WSTR_LIST),
78     SPEC(site_import, BOOL),
79     SPEC(bytes_warning, UINT),
80     SPEC(warn_default_encoding, BOOL),
81     SPEC(inspect, BOOL),
82     SPEC(interactive, BOOL),
83     SPEC(optimization_level, UINT),
84     SPEC(parser_debug, BOOL),
85     SPEC(write_bytecode, BOOL),
86     SPEC(verbose, UINT),
87     SPEC(quiet, BOOL),
88     SPEC(user_site_directory, BOOL),
89     SPEC(configure_c_stdio, BOOL),
90     SPEC(buffered_stdio, BOOL),
91     SPEC(stdio_encoding, WSTR),
92     SPEC(stdio_errors, WSTR),
93 #ifdef MS_WINDOWS
94     SPEC(legacy_windows_stdio, BOOL),
95 #endif
96     SPEC(check_hash_pycs_mode, WSTR),
97     SPEC(use_frozen_modules, BOOL),
98     SPEC(safe_path, BOOL),
99     SPEC(int_max_str_digits, INT),
100     SPEC(cpu_count, INT),
101 #ifdef Py_GIL_DISABLED
102     SPEC(enable_gil, INT),
103 #endif
104     SPEC(pathconfig_warnings, BOOL),
105     SPEC(program_name, WSTR),
106     SPEC(pythonpath_env, WSTR_OPT),
107     SPEC(home, WSTR_OPT),
108     SPEC(platlibdir, WSTR),
109     SPEC(sys_path_0, WSTR_OPT),
110     SPEC(module_search_paths_set, BOOL),
111     SPEC(module_search_paths, WSTR_LIST),
112     SPEC(stdlib_dir, WSTR_OPT),
113     SPEC(executable, WSTR_OPT),
114     SPEC(base_executable, WSTR_OPT),
115     SPEC(prefix, WSTR_OPT),
116     SPEC(base_prefix, WSTR_OPT),
117     SPEC(exec_prefix, WSTR_OPT),
118     SPEC(base_exec_prefix, WSTR_OPT),
119     SPEC(skip_source_first_line, BOOL),
120     SPEC(run_command, WSTR_OPT),
121     SPEC(run_module, WSTR_OPT),
122     SPEC(run_filename, WSTR_OPT),
123     SPEC(_install_importlib, BOOL),
124     SPEC(_init_main, BOOL),
125     SPEC(_is_python_build, BOOL),
126 #ifdef Py_STATS
127     SPEC(_pystats, BOOL),
128 #endif
129 #ifdef Py_DEBUG
130     SPEC(run_presite, WSTR_OPT),
131 #endif
132     {NULL, 0, 0},
133 };
134 
135 #undef SPEC
136 
137 
138 /* --- Command line options --------------------------------------- */
139 
140 /* Short usage message (with %s for argv0) */
141 static const char usage_line[] =
142 "usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
143 
144 /* Long help message */
145 /* Lines sorted by option name; keep in sync with usage_envvars* below */
146 static const char usage_help[] = "\
147 Options (and corresponding environment variables):\n\
148 -b     : issue warnings about converting bytes/bytearray to str and comparing\n\
149          bytes/bytearray with str or bytes with int. (-bb: issue errors)\n\
150 -B     : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\n\
151 -c cmd : program passed in as string (terminates option list)\n\
152 -d     : turn on parser debugging output (for experts only, only works on\n\
153          debug builds); also PYTHONDEBUG=x\n\
154 -E     : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
155 -h     : print this help message and exit (also -? or --help)\n\
156 -i     : inspect interactively after running script; forces a prompt even\n\
157          if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
158 -I     : isolate Python from the user's environment (implies -E and -s)\n\
159 -m mod : run library module as a script (terminates option list)\n\
160 -O     : remove assert and __debug__-dependent statements; add .opt-1 before\n\
161          .pyc extension; also PYTHONOPTIMIZE=x\n\
162 -OO    : do -O changes and also discard docstrings; add .opt-2 before\n\
163          .pyc extension\n\
164 -P     : don't prepend a potentially unsafe path to sys.path; also\n\
165          PYTHONSAFEPATH\n\
166 -q     : don't print version and copyright messages on interactive startup\n\
167 -s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE=x\n\
168 -S     : don't imply 'import site' on initialization\n\
169 -u     : force the stdout and stderr streams to be unbuffered;\n\
170          this option has no effect on stdin; also PYTHONUNBUFFERED=x\n\
171 -v     : verbose (trace import statements); also PYTHONVERBOSE=x\n\
172          can be supplied multiple times to increase verbosity\n\
173 -V     : print the Python version number and exit (also --version)\n\
174          when given twice, print more information about the build\n\
175 -W arg : warning control; arg is action:message:category:module:lineno\n\
176          also PYTHONWARNINGS=arg\n\
177 -x     : skip first line of source, allowing use of non-Unix forms of #!cmd\n\
178 -X opt : set implementation-specific option\n\
179 --check-hash-based-pycs always|default|never:\n\
180          control how Python invalidates hash-based .pyc files\n\
181 --help-env: print help about Python environment variables and exit\n\
182 --help-xoptions: print help about implementation-specific -X options and exit\n\
183 --help-all: print complete help information and exit\n\
184 \n\
185 Arguments:\n\
186 file   : program read from script file\n\
187 -      : program read from stdin (default; interactive mode if a tty)\n\
188 arg ...: arguments passed to program in sys.argv[1:]\n\
189 ";
190 
191 static const char usage_xoptions[] = "\
192 The following implementation-specific options are available:\n\
193 -X cpu_count=N: override the return value of os.cpu_count();\n\
194          -X cpu_count=default cancels overriding; also PYTHON_CPU_COUNT\n\
195 -X dev : enable Python Development Mode; also PYTHONDEVMODE\n\
196 -X faulthandler: dump the Python traceback on fatal errors;\n\
197          also PYTHONFAULTHANDLER\n\
198 -X frozen_modules=[on|off]: whether to use frozen modules; the default is \"on\"\n\
199          for installed Python and \"off\" for a local build;\n\
200          also PYTHON_FROZEN_MODULES\n\
201 "
202 #ifdef Py_GIL_DISABLED
203 "-X gil=[0|1]: enable (1) or disable (0) the GIL; also PYTHON_GIL\n"
204 #endif
205 "\
206 -X importtime: show how long each import takes; also PYTHONPROFILEIMPORTTIME\n\
207 -X int_max_str_digits=N: limit the size of int<->str conversions;\n\
208          0 disables the limit; also PYTHONINTMAXSTRDIGITS\n\
209 -X no_debug_ranges: don't include extra location information in code objects;\n\
210          also PYTHONNODEBUGRANGES\n\
211 -X perf: support the Linux \"perf\" profiler; also PYTHONPERFSUPPORT=1\n\
212 "
213 #ifdef Py_DEBUG
214 "-X presite=MOD: import this module before site; also PYTHON_PRESITE\n"
215 #endif
216 "\
217 -X pycache_prefix=PATH: write .pyc files to a parallel tree instead of to the\n\
218          code tree; also PYTHONPYCACHEPREFIX\n\
219 "
220 #ifdef Py_STATS
221 "-X pystats: enable pystats collection at startup; also PYTHONSTATS\n"
222 #endif
223 "\
224 -X showrefcount: output the total reference count and number of used\n\
225          memory blocks when the program finishes or after each statement in\n\
226          the interactive interpreter; only works on debug builds\n\
227 -X tracemalloc[=N]: trace Python memory allocations; N sets a traceback limit\n\
228          of N frames (default: 1); also PYTHONTRACEMALLOC=N\n\
229 -X utf8[=0|1]: enable (1) or disable (0) UTF-8 mode; also PYTHONUTF8\n\
230 -X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None';\n\
231          also PYTHONWARNDEFAULTENCODING\
232 ";
233 
234 /* Envvars that don't have equivalent command-line options are listed first */
235 static const char usage_envvars[] =
236 "Environment variables that change behavior:\n"
237 "PYTHONSTARTUP   : file executed on interactive startup (no default)\n"
238 "PYTHONPATH      : '%lc'-separated list of directories prefixed to the\n"
239 "                  default module search path.  The result is sys.path.\n"
240 "PYTHONHOME      : alternate <prefix> directory (or <prefix>%lc<exec_prefix>).\n"
241 "                  The default module search path uses %s.\n"
242 "PYTHONPLATLIBDIR: override sys.platlibdir\n"
243 "PYTHONCASEOK    : ignore case in 'import' statements (Windows)\n"
244 "PYTHONIOENCODING: encoding[:errors] used for stdin/stdout/stderr\n"
245 "PYTHONHASHSEED  : if this variable is set to 'random', a random value is used\n"
246 "                  to seed the hashes of str and bytes objects.  It can also be\n"
247 "                  set to an integer in the range [0,4294967295] to get hash\n"
248 "                  values with a predictable seed.\n"
249 "PYTHONMALLOC    : set the Python memory allocators and/or install debug hooks\n"
250 "                  on Python memory allocators.  Use PYTHONMALLOC=debug to\n"
251 "                  install debug hooks.\n"
252 "PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n"
253 "                  coercion behavior.  Use PYTHONCOERCECLOCALE=warn to request\n"
254 "                  display of locale coercion and locale compatibility warnings\n"
255 "                  on stderr.\n"
256 "PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n"
257 "                  debugger.  It can be set to the callable of your debugger of\n"
258 "                  choice.\n"
259 "PYTHON_COLORS   : if this variable is set to 1, the interpreter will colorize\n"
260 "                  various kinds of output.  Setting it to 0 deactivates\n"
261 "                  this behavior.\n"
262 "PYTHON_HISTORY  : the location of a .python_history file.\n"
263 "\n"
264 "These variables have equivalent command-line options (see --help for details):\n"
265 "PYTHON_CPU_COUNT: override the return value of os.cpu_count() (-X cpu_count)\n"
266 "PYTHONDEBUG     : enable parser debug mode (-d)\n"
267 "PYTHONDEVMODE   : enable Python Development Mode (-X dev)\n"
268 "PYTHONDONTWRITEBYTECODE: don't write .pyc files (-B)\n"
269 "PYTHONFAULTHANDLER: dump the Python traceback on fatal errors (-X faulthandler)\n"
270 "PYTHON_FROZEN_MODULES: whether to use frozen modules; the default is \"on\"\n"
271 "                  for installed Python and \"off\" for a local build\n"
272 "                  (-X frozen_modules)\n"
273 #ifdef Py_GIL_DISABLED
274 "PYTHON_GIL      : when set to 0, disables the GIL (-X gil)\n"
275 #endif
276 "PYTHONINSPECT   : inspect interactively after running script (-i)\n"
277 "PYTHONINTMAXSTRDIGITS: limit the size of int<->str conversions;\n"
278 "                  0 disables the limit (-X int_max_str_digits=N)\n"
279 "PYTHONNODEBUGRANGES: don't include extra location information in code objects\n"
280 "                  (-X no_debug_ranges)\n"
281 "PYTHONNOUSERSITE: disable user site directory (-s)\n"
282 "PYTHONOPTIMIZE  : enable level 1 optimizations (-O)\n"
283 "PYTHONPERFSUPPORT: support the Linux \"perf\" profiler (-X perf)\n"
284 #ifdef Py_DEBUG
285 "PYTHON_PRESITE: import this module before site (-X presite)\n"
286 #endif
287 "PYTHONPROFILEIMPORTTIME: show how long each import takes (-X importtime)\n"
288 "PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files\n"
289 "                  (-X pycache_prefix)\n"
290 "PYTHONSAFEPATH  : don't prepend a potentially unsafe path to sys.path.\n"
291 #ifdef Py_STATS
292 "PYTHONSTATS     : turns on statistics gathering (-X pystats)\n"
293 #endif
294 "PYTHONTRACEMALLOC: trace Python memory allocations (-X tracemalloc)\n"
295 "PYTHONUNBUFFERED: disable stdout/stderr buffering (-u)\n"
296 "PYTHONUTF8      : control the UTF-8 mode (-X utf8)\n"
297 "PYTHONVERBOSE   : trace import statements (-v)\n"
298 "PYTHONWARNDEFAULTENCODING: enable opt-in EncodingWarning for 'encoding=None'\n"
299 "                  (-X warn_default_encoding)\n"
300 "PYTHONWARNINGS  : warning control (-W)\n"
301 ;
302 
303 #if defined(MS_WINDOWS)
304 #  define PYTHONHOMEHELP "<prefix>\\python{major}{minor}"
305 #else
306 #  define PYTHONHOMEHELP "<prefix>/lib/pythonX.X"
307 #endif
308 
309 
310 /* --- Global configuration variables ----------------------------- */
311 
312 /* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change
313    stdin and stdout error handler to "surrogateescape". */
314 int Py_UTF8Mode = 0;
315 int Py_DebugFlag = 0; /* Needed by parser.c */
316 int Py_VerboseFlag = 0; /* Needed by import.c */
317 int Py_QuietFlag = 0; /* Needed by sysmodule.c */
318 int Py_InteractiveFlag = 0; /* Previously, was used by Py_FdIsInteractive() */
319 int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */
320 int Py_OptimizeFlag = 0; /* Needed by compile.c */
321 int Py_NoSiteFlag = 0; /* Suppress 'import site' */
322 int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */
323 int Py_FrozenFlag = 0; /* Needed by getpath.c */
324 int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */
325 int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */
326 int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
327 int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
328 int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
329 int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
330 #ifdef MS_WINDOWS
331 int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */
332 int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */
333 #endif
334 
335 
336 static PyObject *
_Py_GetGlobalVariablesAsDict(void)337 _Py_GetGlobalVariablesAsDict(void)
338 {
339 _Py_COMP_DIAG_PUSH
340 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
341     PyObject *dict, *obj;
342 
343     dict = PyDict_New();
344     if (dict == NULL) {
345         return NULL;
346     }
347 
348 #define SET_ITEM(KEY, EXPR) \
349         do { \
350             obj = (EXPR); \
351             if (obj == NULL) { \
352                 return NULL; \
353             } \
354             int res = PyDict_SetItemString(dict, (KEY), obj); \
355             Py_DECREF(obj); \
356             if (res < 0) { \
357                 goto fail; \
358             } \
359         } while (0)
360 #define SET_ITEM_INT(VAR) \
361     SET_ITEM(#VAR, PyLong_FromLong(VAR))
362 #define FROM_STRING(STR) \
363     ((STR != NULL) ? \
364         PyUnicode_FromString(STR) \
365         : Py_NewRef(Py_None))
366 #define SET_ITEM_STR(VAR) \
367     SET_ITEM(#VAR, FROM_STRING(VAR))
368 
369     SET_ITEM_STR(Py_FileSystemDefaultEncoding);
370     SET_ITEM_INT(Py_HasFileSystemDefaultEncoding);
371     SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors);
372     SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors);
373 
374     SET_ITEM_INT(Py_UTF8Mode);
375     SET_ITEM_INT(Py_DebugFlag);
376     SET_ITEM_INT(Py_VerboseFlag);
377     SET_ITEM_INT(Py_QuietFlag);
378     SET_ITEM_INT(Py_InteractiveFlag);
379     SET_ITEM_INT(Py_InspectFlag);
380 
381     SET_ITEM_INT(Py_OptimizeFlag);
382     SET_ITEM_INT(Py_NoSiteFlag);
383     SET_ITEM_INT(Py_BytesWarningFlag);
384     SET_ITEM_INT(Py_FrozenFlag);
385     SET_ITEM_INT(Py_IgnoreEnvironmentFlag);
386     SET_ITEM_INT(Py_DontWriteBytecodeFlag);
387     SET_ITEM_INT(Py_NoUserSiteDirectory);
388     SET_ITEM_INT(Py_UnbufferedStdioFlag);
389     SET_ITEM_INT(Py_HashRandomizationFlag);
390     SET_ITEM_INT(Py_IsolatedFlag);
391 
392 #ifdef MS_WINDOWS
393     SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag);
394     SET_ITEM_INT(Py_LegacyWindowsStdioFlag);
395 #endif
396 
397     return dict;
398 
399 fail:
400     Py_DECREF(dict);
401     return NULL;
402 
403 #undef FROM_STRING
404 #undef SET_ITEM
405 #undef SET_ITEM_INT
406 #undef SET_ITEM_STR
407 _Py_COMP_DIAG_POP
408 }
409 
410 char*
Py_GETENV(const char * name)411 Py_GETENV(const char *name)
412 {
413 _Py_COMP_DIAG_PUSH
414 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
415     if (Py_IgnoreEnvironmentFlag) {
416         return NULL;
417     }
418     return getenv(name);
419 _Py_COMP_DIAG_POP
420 }
421 
422 /* --- PyStatus ----------------------------------------------- */
423 
PyStatus_Ok(void)424 PyStatus PyStatus_Ok(void)
425 { return _PyStatus_OK(); }
426 
PyStatus_Error(const char * err_msg)427 PyStatus PyStatus_Error(const char *err_msg)
428 {
429     assert(err_msg != NULL);
430     return (PyStatus){._type = _PyStatus_TYPE_ERROR,
431                       .err_msg = err_msg};
432 }
433 
PyStatus_NoMemory(void)434 PyStatus PyStatus_NoMemory(void)
435 { return PyStatus_Error("memory allocation failed"); }
436 
PyStatus_Exit(int exitcode)437 PyStatus PyStatus_Exit(int exitcode)
438 { return _PyStatus_EXIT(exitcode); }
439 
440 
PyStatus_IsError(PyStatus status)441 int PyStatus_IsError(PyStatus status)
442 { return _PyStatus_IS_ERROR(status); }
443 
PyStatus_IsExit(PyStatus status)444 int PyStatus_IsExit(PyStatus status)
445 { return _PyStatus_IS_EXIT(status); }
446 
PyStatus_Exception(PyStatus status)447 int PyStatus_Exception(PyStatus status)
448 { return _PyStatus_EXCEPTION(status); }
449 
450 void
_PyErr_SetFromPyStatus(PyStatus status)451 _PyErr_SetFromPyStatus(PyStatus status)
452 {
453     if (!_PyStatus_IS_ERROR(status)) {
454         PyErr_Format(PyExc_SystemError,
455                      "_PyErr_SetFromPyStatus() status is not an error");
456         return;
457     }
458 
459     const char *err_msg = status.err_msg;
460     if (err_msg == NULL || strlen(err_msg) == 0) {
461         PyErr_Format(PyExc_SystemError,
462                      "_PyErr_SetFromPyStatus() status has no error message");
463         return;
464     }
465 
466     if (strcmp(err_msg, _PyStatus_NO_MEMORY_ERRMSG) == 0) {
467         PyErr_NoMemory();
468         return;
469     }
470 
471     const char *func = status.func;
472     if (func) {
473         PyErr_Format(PyExc_RuntimeError, "%s: %s", func, err_msg);
474     }
475     else {
476         PyErr_Format(PyExc_RuntimeError, "%s", err_msg);
477     }
478 }
479 
480 
481 /* --- PyWideStringList ------------------------------------------------ */
482 
483 #ifndef NDEBUG
484 int
_PyWideStringList_CheckConsistency(const PyWideStringList * list)485 _PyWideStringList_CheckConsistency(const PyWideStringList *list)
486 {
487     assert(list->length >= 0);
488     if (list->length != 0) {
489         assert(list->items != NULL);
490     }
491     for (Py_ssize_t i = 0; i < list->length; i++) {
492         assert(list->items[i] != NULL);
493     }
494     return 1;
495 }
496 #endif   /* Py_DEBUG */
497 
498 
499 void
_PyWideStringList_Clear(PyWideStringList * list)500 _PyWideStringList_Clear(PyWideStringList *list)
501 {
502     assert(_PyWideStringList_CheckConsistency(list));
503     for (Py_ssize_t i=0; i < list->length; i++) {
504         PyMem_RawFree(list->items[i]);
505     }
506     PyMem_RawFree(list->items);
507     list->length = 0;
508     list->items = NULL;
509 }
510 
511 
512 int
_PyWideStringList_Copy(PyWideStringList * list,const PyWideStringList * list2)513 _PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
514 {
515     assert(_PyWideStringList_CheckConsistency(list));
516     assert(_PyWideStringList_CheckConsistency(list2));
517 
518     if (list2->length == 0) {
519         _PyWideStringList_Clear(list);
520         return 0;
521     }
522 
523     PyWideStringList copy = _PyWideStringList_INIT;
524 
525     size_t size = list2->length * sizeof(list2->items[0]);
526     copy.items = PyMem_RawMalloc(size);
527     if (copy.items == NULL) {
528         return -1;
529     }
530 
531     for (Py_ssize_t i=0; i < list2->length; i++) {
532         wchar_t *item = _PyMem_RawWcsdup(list2->items[i]);
533         if (item == NULL) {
534             _PyWideStringList_Clear(&copy);
535             return -1;
536         }
537         copy.items[i] = item;
538         copy.length = i + 1;
539     }
540 
541     _PyWideStringList_Clear(list);
542     *list = copy;
543     return 0;
544 }
545 
546 
547 PyStatus
PyWideStringList_Insert(PyWideStringList * list,Py_ssize_t index,const wchar_t * item)548 PyWideStringList_Insert(PyWideStringList *list,
549                         Py_ssize_t index, const wchar_t *item)
550 {
551     Py_ssize_t len = list->length;
552     if (len == PY_SSIZE_T_MAX) {
553         /* length+1 would overflow */
554         return _PyStatus_NO_MEMORY();
555     }
556     if (index < 0) {
557         return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0");
558     }
559     if (index > len) {
560         index = len;
561     }
562 
563     wchar_t *item2 = _PyMem_RawWcsdup(item);
564     if (item2 == NULL) {
565         return _PyStatus_NO_MEMORY();
566     }
567 
568     size_t size = (len + 1) * sizeof(list->items[0]);
569     wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);
570     if (items2 == NULL) {
571         PyMem_RawFree(item2);
572         return _PyStatus_NO_MEMORY();
573     }
574 
575     if (index < len) {
576         memmove(&items2[index + 1],
577                 &items2[index],
578                 (len - index) * sizeof(items2[0]));
579     }
580 
581     items2[index] = item2;
582     list->items = items2;
583     list->length++;
584     return _PyStatus_OK();
585 }
586 
587 
588 PyStatus
PyWideStringList_Append(PyWideStringList * list,const wchar_t * item)589 PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
590 {
591     return PyWideStringList_Insert(list, list->length, item);
592 }
593 
594 
595 PyStatus
_PyWideStringList_Extend(PyWideStringList * list,const PyWideStringList * list2)596 _PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2)
597 {
598     for (Py_ssize_t i = 0; i < list2->length; i++) {
599         PyStatus status = PyWideStringList_Append(list, list2->items[i]);
600         if (_PyStatus_EXCEPTION(status)) {
601             return status;
602         }
603     }
604     return _PyStatus_OK();
605 }
606 
607 
608 static int
_PyWideStringList_Find(PyWideStringList * list,const wchar_t * item)609 _PyWideStringList_Find(PyWideStringList *list, const wchar_t *item)
610 {
611     for (Py_ssize_t i = 0; i < list->length; i++) {
612         if (wcscmp(list->items[i], item) == 0) {
613             return 1;
614         }
615     }
616     return 0;
617 }
618 
619 
620 PyObject*
_PyWideStringList_AsList(const PyWideStringList * list)621 _PyWideStringList_AsList(const PyWideStringList *list)
622 {
623     assert(_PyWideStringList_CheckConsistency(list));
624 
625     PyObject *pylist = PyList_New(list->length);
626     if (pylist == NULL) {
627         return NULL;
628     }
629 
630     for (Py_ssize_t i = 0; i < list->length; i++) {
631         PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
632         if (item == NULL) {
633             Py_DECREF(pylist);
634             return NULL;
635         }
636         PyList_SET_ITEM(pylist, i, item);
637     }
638     return pylist;
639 }
640 
641 
642 /* --- Py_GetArgcArgv() ------------------------------------------- */
643 
644 void
_Py_ClearArgcArgv(void)645 _Py_ClearArgcArgv(void)
646 {
647     PyMemAllocatorEx old_alloc;
648     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
649 
650     _PyWideStringList_Clear(&_PyRuntime.orig_argv);
651 
652     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
653 }
654 
655 
656 static int
_Py_SetArgcArgv(Py_ssize_t argc,wchar_t * const * argv)657 _Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
658 {
659     const PyWideStringList argv_list = {.length = argc, .items = (wchar_t **)argv};
660     int res;
661 
662     PyMemAllocatorEx old_alloc;
663     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
664 
665     // XXX _PyRuntime.orig_argv only gets cleared by Py_Main(),
666     // so it currently leaks for embedders.
667     res = _PyWideStringList_Copy(&_PyRuntime.orig_argv, &argv_list);
668 
669     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
670     return res;
671 }
672 
673 
674 // _PyConfig_Write() calls _Py_SetArgcArgv() with PyConfig.orig_argv.
675 void
Py_GetArgcArgv(int * argc,wchar_t *** argv)676 Py_GetArgcArgv(int *argc, wchar_t ***argv)
677 {
678     *argc = (int)_PyRuntime.orig_argv.length;
679     *argv = _PyRuntime.orig_argv.items;
680 }
681 
682 
683 /* --- PyConfig ---------------------------------------------- */
684 
685 #define MAX_HASH_SEED 4294967295UL
686 
687 
688 #ifndef NDEBUG
689 static int
config_check_consistency(const PyConfig * config)690 config_check_consistency(const PyConfig *config)
691 {
692     /* Check config consistency */
693     assert(config->isolated >= 0);
694     assert(config->use_environment >= 0);
695     assert(config->dev_mode >= 0);
696     assert(config->install_signal_handlers >= 0);
697     assert(config->use_hash_seed >= 0);
698     assert(config->hash_seed <= MAX_HASH_SEED);
699     assert(config->faulthandler >= 0);
700     assert(config->tracemalloc >= 0);
701     assert(config->import_time >= 0);
702     assert(config->code_debug_ranges >= 0);
703     assert(config->show_ref_count >= 0);
704     assert(config->dump_refs >= 0);
705     assert(config->malloc_stats >= 0);
706     assert(config->site_import >= 0);
707     assert(config->bytes_warning >= 0);
708     assert(config->warn_default_encoding >= 0);
709     assert(config->inspect >= 0);
710     assert(config->interactive >= 0);
711     assert(config->optimization_level >= 0);
712     assert(config->parser_debug >= 0);
713     assert(config->write_bytecode >= 0);
714     assert(config->verbose >= 0);
715     assert(config->quiet >= 0);
716     assert(config->user_site_directory >= 0);
717     assert(config->parse_argv >= 0);
718     assert(config->configure_c_stdio >= 0);
719     assert(config->buffered_stdio >= 0);
720     assert(_PyWideStringList_CheckConsistency(&config->orig_argv));
721     assert(_PyWideStringList_CheckConsistency(&config->argv));
722     /* sys.argv must be non-empty: empty argv is replaced with [''] */
723     assert(config->argv.length >= 1);
724     assert(_PyWideStringList_CheckConsistency(&config->xoptions));
725     assert(_PyWideStringList_CheckConsistency(&config->warnoptions));
726     assert(_PyWideStringList_CheckConsistency(&config->module_search_paths));
727     assert(config->module_search_paths_set >= 0);
728     assert(config->filesystem_encoding != NULL);
729     assert(config->filesystem_errors != NULL);
730     assert(config->stdio_encoding != NULL);
731     assert(config->stdio_errors != NULL);
732 #ifdef MS_WINDOWS
733     assert(config->legacy_windows_stdio >= 0);
734 #endif
735     /* -c and -m options are exclusive */
736     assert(!(config->run_command != NULL && config->run_module != NULL));
737     assert(config->check_hash_pycs_mode != NULL);
738     assert(config->_install_importlib >= 0);
739     assert(config->pathconfig_warnings >= 0);
740     assert(config->_is_python_build >= 0);
741     assert(config->safe_path >= 0);
742     assert(config->int_max_str_digits >= 0);
743     // cpu_count can be -1 if the user doesn't override it.
744     assert(config->cpu_count != 0);
745     // config->use_frozen_modules is initialized later
746     // by _PyConfig_InitImportConfig().
747 #ifdef Py_STATS
748     assert(config->_pystats >= 0);
749 #endif
750     return 1;
751 }
752 #endif
753 
754 
755 /* Free memory allocated in config, but don't clear all attributes */
756 void
PyConfig_Clear(PyConfig * config)757 PyConfig_Clear(PyConfig *config)
758 {
759 #define CLEAR(ATTR) \
760     do { \
761         PyMem_RawFree(ATTR); \
762         ATTR = NULL; \
763     } while (0)
764 
765     CLEAR(config->pycache_prefix);
766     CLEAR(config->pythonpath_env);
767     CLEAR(config->home);
768     CLEAR(config->program_name);
769 
770     _PyWideStringList_Clear(&config->argv);
771     _PyWideStringList_Clear(&config->warnoptions);
772     _PyWideStringList_Clear(&config->xoptions);
773     _PyWideStringList_Clear(&config->module_search_paths);
774     config->module_search_paths_set = 0;
775     CLEAR(config->stdlib_dir);
776 
777     CLEAR(config->executable);
778     CLEAR(config->base_executable);
779     CLEAR(config->prefix);
780     CLEAR(config->base_prefix);
781     CLEAR(config->exec_prefix);
782     CLEAR(config->base_exec_prefix);
783     CLEAR(config->platlibdir);
784     CLEAR(config->sys_path_0);
785 
786     CLEAR(config->filesystem_encoding);
787     CLEAR(config->filesystem_errors);
788     CLEAR(config->stdio_encoding);
789     CLEAR(config->stdio_errors);
790     CLEAR(config->run_command);
791     CLEAR(config->run_module);
792     CLEAR(config->run_filename);
793     CLEAR(config->check_hash_pycs_mode);
794 #ifdef Py_DEBUG
795     CLEAR(config->run_presite);
796 #endif
797 
798     _PyWideStringList_Clear(&config->orig_argv);
799 #undef CLEAR
800 }
801 
802 
803 void
_PyConfig_InitCompatConfig(PyConfig * config)804 _PyConfig_InitCompatConfig(PyConfig *config)
805 {
806     memset(config, 0, sizeof(*config));
807 
808     config->_config_init = (int)_PyConfig_INIT_COMPAT;
809     config->isolated = -1;
810     config->use_environment = -1;
811     config->dev_mode = -1;
812     config->install_signal_handlers = 1;
813     config->use_hash_seed = -1;
814     config->faulthandler = -1;
815     config->tracemalloc = -1;
816     config->perf_profiling = -1;
817     config->module_search_paths_set = 0;
818     config->parse_argv = 0;
819     config->site_import = -1;
820     config->bytes_warning = -1;
821     config->warn_default_encoding = 0;
822     config->inspect = -1;
823     config->interactive = -1;
824     config->optimization_level = -1;
825     config->parser_debug= -1;
826     config->write_bytecode = -1;
827     config->verbose = -1;
828     config->quiet = -1;
829     config->user_site_directory = -1;
830     config->configure_c_stdio = 0;
831     config->buffered_stdio = -1;
832     config->_install_importlib = 1;
833     config->check_hash_pycs_mode = NULL;
834     config->pathconfig_warnings = -1;
835     config->_init_main = 1;
836 #ifdef MS_WINDOWS
837     config->legacy_windows_stdio = -1;
838 #endif
839 #ifdef Py_DEBUG
840     config->use_frozen_modules = 0;
841 #else
842     config->use_frozen_modules = 1;
843 #endif
844     config->safe_path = 0;
845     config->int_max_str_digits = -1;
846     config->_is_python_build = 0;
847     config->code_debug_ranges = 1;
848     config->cpu_count = -1;
849 #ifdef Py_GIL_DISABLED
850     config->enable_gil = _PyConfig_GIL_DEFAULT;
851 #endif
852 }
853 
854 
855 static void
config_init_defaults(PyConfig * config)856 config_init_defaults(PyConfig *config)
857 {
858     _PyConfig_InitCompatConfig(config);
859 
860     config->isolated = 0;
861     config->use_environment = 1;
862     config->site_import = 1;
863     config->bytes_warning = 0;
864     config->inspect = 0;
865     config->interactive = 0;
866     config->optimization_level = 0;
867     config->parser_debug= 0;
868     config->write_bytecode = 1;
869     config->verbose = 0;
870     config->quiet = 0;
871     config->user_site_directory = 1;
872     config->buffered_stdio = 1;
873     config->pathconfig_warnings = 1;
874 #ifdef MS_WINDOWS
875     config->legacy_windows_stdio = 0;
876 #endif
877 }
878 
879 
880 void
PyConfig_InitPythonConfig(PyConfig * config)881 PyConfig_InitPythonConfig(PyConfig *config)
882 {
883     config_init_defaults(config);
884 
885     config->_config_init = (int)_PyConfig_INIT_PYTHON;
886     config->configure_c_stdio = 1;
887     config->parse_argv = 1;
888 }
889 
890 
891 void
PyConfig_InitIsolatedConfig(PyConfig * config)892 PyConfig_InitIsolatedConfig(PyConfig *config)
893 {
894     config_init_defaults(config);
895 
896     config->_config_init = (int)_PyConfig_INIT_ISOLATED;
897     config->isolated = 1;
898     config->use_environment = 0;
899     config->user_site_directory = 0;
900     config->dev_mode = 0;
901     config->install_signal_handlers = 0;
902     config->use_hash_seed = 0;
903     config->faulthandler = 0;
904     config->tracemalloc = 0;
905     config->perf_profiling = 0;
906     config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
907     config->safe_path = 1;
908     config->pathconfig_warnings = 0;
909 #ifdef MS_WINDOWS
910     config->legacy_windows_stdio = 0;
911 #endif
912 }
913 
914 
915 /* Copy str into *config_str (duplicate the string) */
916 PyStatus
PyConfig_SetString(PyConfig * config,wchar_t ** config_str,const wchar_t * str)917 PyConfig_SetString(PyConfig *config, wchar_t **config_str, const wchar_t *str)
918 {
919     PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
920     if (_PyStatus_EXCEPTION(status)) {
921         return status;
922     }
923 
924     wchar_t *str2;
925     if (str != NULL) {
926         str2 = _PyMem_RawWcsdup(str);
927         if (str2 == NULL) {
928             return _PyStatus_NO_MEMORY();
929         }
930     }
931     else {
932         str2 = NULL;
933     }
934     PyMem_RawFree(*config_str);
935     *config_str = str2;
936     return _PyStatus_OK();
937 }
938 
939 
940 static PyStatus
config_set_bytes_string(PyConfig * config,wchar_t ** config_str,const char * str,const char * decode_err_msg)941 config_set_bytes_string(PyConfig *config, wchar_t **config_str,
942                         const char *str, const char *decode_err_msg)
943 {
944     PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
945     if (_PyStatus_EXCEPTION(status)) {
946         return status;
947     }
948 
949     wchar_t *str2;
950     if (str != NULL) {
951         size_t len;
952         str2 = Py_DecodeLocale(str, &len);
953         if (str2 == NULL) {
954             if (len == (size_t)-2) {
955                 return _PyStatus_ERR(decode_err_msg);
956             }
957             else {
958                 return  _PyStatus_NO_MEMORY();
959             }
960         }
961     }
962     else {
963         str2 = NULL;
964     }
965     PyMem_RawFree(*config_str);
966     *config_str = str2;
967     return _PyStatus_OK();
968 }
969 
970 
971 #define CONFIG_SET_BYTES_STR(config, config_str, str, NAME) \
972     config_set_bytes_string(config, config_str, str, "cannot decode " NAME)
973 
974 
975 /* Decode str using Py_DecodeLocale() and set the result into *config_str.
976    Pre-initialize Python if needed to ensure that encodings are properly
977    configured. */
978 PyStatus
PyConfig_SetBytesString(PyConfig * config,wchar_t ** config_str,const char * str)979 PyConfig_SetBytesString(PyConfig *config, wchar_t **config_str,
980                         const char *str)
981 {
982     return CONFIG_SET_BYTES_STR(config, config_str, str, "string");
983 }
984 
985 
986 PyStatus
_PyConfig_Copy(PyConfig * config,const PyConfig * config2)987 _PyConfig_Copy(PyConfig *config, const PyConfig *config2)
988 {
989     PyConfig_Clear(config);
990 
991     PyStatus status;
992     const PyConfigSpec *spec = PYCONFIG_SPEC;
993     for (; spec->name != NULL; spec++) {
994         char *member = (char *)config + spec->offset;
995         char *member2 = (char *)config2 + spec->offset;
996         switch (spec->type) {
997         case PyConfig_MEMBER_INT:
998         case PyConfig_MEMBER_UINT:
999         case PyConfig_MEMBER_BOOL:
1000         {
1001             *(int*)member = *(int*)member2;
1002             break;
1003         }
1004         case PyConfig_MEMBER_ULONG:
1005         {
1006             *(unsigned long*)member = *(unsigned long*)member2;
1007             break;
1008         }
1009         case PyConfig_MEMBER_WSTR:
1010         case PyConfig_MEMBER_WSTR_OPT:
1011         {
1012             const wchar_t *str = *(const wchar_t**)member2;
1013             status = PyConfig_SetString(config, (wchar_t**)member, str);
1014             if (_PyStatus_EXCEPTION(status)) {
1015                 return status;
1016             }
1017             break;
1018         }
1019         case PyConfig_MEMBER_WSTR_LIST:
1020         {
1021             if (_PyWideStringList_Copy((PyWideStringList*)member,
1022                                        (const PyWideStringList*)member2) < 0) {
1023                 return _PyStatus_NO_MEMORY();
1024             }
1025             break;
1026         }
1027         default:
1028             Py_UNREACHABLE();
1029         }
1030     }
1031     return _PyStatus_OK();
1032 }
1033 
1034 
1035 PyObject *
_PyConfig_AsDict(const PyConfig * config)1036 _PyConfig_AsDict(const PyConfig *config)
1037 {
1038     PyObject *dict = PyDict_New();
1039     if (dict == NULL) {
1040         return NULL;
1041     }
1042 
1043     const PyConfigSpec *spec = PYCONFIG_SPEC;
1044     for (; spec->name != NULL; spec++) {
1045         char *member = (char *)config + spec->offset;
1046         PyObject *obj;
1047         switch (spec->type) {
1048         case PyConfig_MEMBER_INT:
1049         case PyConfig_MEMBER_UINT:
1050         {
1051             int value = *(int*)member;
1052             obj = PyLong_FromLong(value);
1053             break;
1054         }
1055         case PyConfig_MEMBER_BOOL:
1056         {
1057             int value = *(int*)member;
1058             obj = PyBool_FromLong(value);
1059             break;
1060         }
1061         case PyConfig_MEMBER_ULONG:
1062         {
1063             unsigned long value = *(unsigned long*)member;
1064             obj = PyLong_FromUnsignedLong(value);
1065             break;
1066         }
1067         case PyConfig_MEMBER_WSTR:
1068         case PyConfig_MEMBER_WSTR_OPT:
1069         {
1070             const wchar_t *wstr = *(const wchar_t**)member;
1071             if (wstr != NULL) {
1072                 obj = PyUnicode_FromWideChar(wstr, -1);
1073             }
1074             else {
1075                 obj = Py_NewRef(Py_None);
1076             }
1077             break;
1078         }
1079         case PyConfig_MEMBER_WSTR_LIST:
1080         {
1081             const PyWideStringList *list = (const PyWideStringList*)member;
1082             obj = _PyWideStringList_AsList(list);
1083             break;
1084         }
1085         default:
1086             Py_UNREACHABLE();
1087         }
1088 
1089         if (obj == NULL) {
1090             Py_DECREF(dict);
1091             return NULL;
1092         }
1093         int res = PyDict_SetItemString(dict, spec->name, obj);
1094         Py_DECREF(obj);
1095         if (res < 0) {
1096             Py_DECREF(dict);
1097             return NULL;
1098         }
1099     }
1100     return dict;
1101 }
1102 
1103 
1104 static void
config_dict_invalid_value(const char * name)1105 config_dict_invalid_value(const char *name)
1106 {
1107     PyErr_Format(PyExc_ValueError, "invalid config value: %s", name);
1108 }
1109 
1110 
1111 static int
config_dict_get_int(PyObject * dict,const char * name,int * result)1112 config_dict_get_int(PyObject *dict, const char *name, int *result)
1113 {
1114     PyObject *item = config_dict_get(dict, name);
1115     if (item == NULL) {
1116         return -1;
1117     }
1118     int value = PyLong_AsInt(item);
1119     Py_DECREF(item);
1120     if (value == -1 && PyErr_Occurred()) {
1121         if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1122             config_dict_invalid_type(name);
1123         }
1124         else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
1125             config_dict_invalid_value(name);
1126         }
1127         return -1;
1128     }
1129     *result = value;
1130     return 0;
1131 }
1132 
1133 
1134 static int
config_dict_get_ulong(PyObject * dict,const char * name,unsigned long * result)1135 config_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result)
1136 {
1137     PyObject *item = config_dict_get(dict, name);
1138     if (item == NULL) {
1139         return -1;
1140     }
1141     unsigned long value = PyLong_AsUnsignedLong(item);
1142     Py_DECREF(item);
1143     if (value == (unsigned long)-1 && PyErr_Occurred()) {
1144         if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1145             config_dict_invalid_type(name);
1146         }
1147         else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
1148             config_dict_invalid_value(name);
1149         }
1150         return -1;
1151     }
1152     *result = value;
1153     return 0;
1154 }
1155 
1156 
1157 static int
config_dict_get_wstr(PyObject * dict,const char * name,PyConfig * config,wchar_t ** result)1158 config_dict_get_wstr(PyObject *dict, const char *name, PyConfig *config,
1159                      wchar_t **result)
1160 {
1161     PyObject *item = config_dict_get(dict, name);
1162     if (item == NULL) {
1163         return -1;
1164     }
1165 
1166     PyStatus status;
1167     if (item == Py_None) {
1168         status = PyConfig_SetString(config, result, NULL);
1169     }
1170     else if (!PyUnicode_Check(item)) {
1171         config_dict_invalid_type(name);
1172         goto error;
1173     }
1174     else {
1175         wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1176         if (wstr == NULL) {
1177             goto error;
1178         }
1179         status = PyConfig_SetString(config, result, wstr);
1180         PyMem_Free(wstr);
1181     }
1182     if (_PyStatus_EXCEPTION(status)) {
1183         PyErr_NoMemory();
1184         goto error;
1185     }
1186     Py_DECREF(item);
1187     return 0;
1188 
1189 error:
1190     Py_DECREF(item);
1191     return -1;
1192 }
1193 
1194 
1195 static int
config_dict_get_wstrlist(PyObject * dict,const char * name,PyConfig * config,PyWideStringList * result)1196 config_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config,
1197                          PyWideStringList *result)
1198 {
1199     PyObject *list = config_dict_get(dict, name);
1200     if (list == NULL) {
1201         return -1;
1202     }
1203 
1204     if (!PyList_CheckExact(list)) {
1205         Py_DECREF(list);
1206         config_dict_invalid_type(name);
1207         return -1;
1208     }
1209 
1210     PyWideStringList wstrlist = _PyWideStringList_INIT;
1211     for (Py_ssize_t i=0; i < PyList_GET_SIZE(list); i++) {
1212         PyObject *item = PyList_GET_ITEM(list, i);
1213 
1214         if (item == Py_None) {
1215             config_dict_invalid_value(name);
1216             goto error;
1217         }
1218         else if (!PyUnicode_Check(item)) {
1219             config_dict_invalid_type(name);
1220             goto error;
1221         }
1222         wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1223         if (wstr == NULL) {
1224             goto error;
1225         }
1226         PyStatus status = PyWideStringList_Append(&wstrlist, wstr);
1227         PyMem_Free(wstr);
1228         if (_PyStatus_EXCEPTION(status)) {
1229             PyErr_NoMemory();
1230             goto error;
1231         }
1232     }
1233 
1234     if (_PyWideStringList_Copy(result, &wstrlist) < 0) {
1235         PyErr_NoMemory();
1236         goto error;
1237     }
1238     _PyWideStringList_Clear(&wstrlist);
1239     Py_DECREF(list);
1240     return 0;
1241 
1242 error:
1243     _PyWideStringList_Clear(&wstrlist);
1244     Py_DECREF(list);
1245     return -1;
1246 }
1247 
1248 
1249 int
_PyConfig_FromDict(PyConfig * config,PyObject * dict)1250 _PyConfig_FromDict(PyConfig *config, PyObject *dict)
1251 {
1252     if (!PyDict_Check(dict)) {
1253         PyErr_SetString(PyExc_TypeError, "dict expected");
1254         return -1;
1255     }
1256 
1257     const PyConfigSpec *spec = PYCONFIG_SPEC;
1258     for (; spec->name != NULL; spec++) {
1259         char *member = (char *)config + spec->offset;
1260         switch (spec->type) {
1261         case PyConfig_MEMBER_INT:
1262         case PyConfig_MEMBER_UINT:
1263         case PyConfig_MEMBER_BOOL:
1264         {
1265             int value;
1266             if (config_dict_get_int(dict, spec->name, &value) < 0) {
1267                 return -1;
1268             }
1269             if (spec->type == PyConfig_MEMBER_BOOL
1270                 || spec->type == PyConfig_MEMBER_UINT)
1271             {
1272                 if (value < 0) {
1273                     config_dict_invalid_value(spec->name);
1274                     return -1;
1275                 }
1276             }
1277             *(int*)member = value;
1278             break;
1279         }
1280         case PyConfig_MEMBER_ULONG:
1281         {
1282             if (config_dict_get_ulong(dict, spec->name,
1283                                       (unsigned long*)member) < 0) {
1284                 return -1;
1285             }
1286             break;
1287         }
1288         case PyConfig_MEMBER_WSTR:
1289         {
1290             wchar_t **wstr = (wchar_t**)member;
1291             if (config_dict_get_wstr(dict, spec->name, config, wstr) < 0) {
1292                 return -1;
1293             }
1294             if (*wstr == NULL) {
1295                 config_dict_invalid_value(spec->name);
1296                 return -1;
1297             }
1298             break;
1299         }
1300         case PyConfig_MEMBER_WSTR_OPT:
1301         {
1302             wchar_t **wstr = (wchar_t**)member;
1303             if (config_dict_get_wstr(dict, spec->name, config, wstr) < 0) {
1304                 return -1;
1305             }
1306             break;
1307         }
1308         case PyConfig_MEMBER_WSTR_LIST:
1309         {
1310             if (config_dict_get_wstrlist(dict, spec->name, config,
1311                                          (PyWideStringList*)member) < 0) {
1312                 return -1;
1313             }
1314             break;
1315         }
1316         default:
1317             Py_UNREACHABLE();
1318         }
1319     }
1320 
1321     if (!(config->_config_init == _PyConfig_INIT_COMPAT
1322           || config->_config_init == _PyConfig_INIT_PYTHON
1323           || config->_config_init == _PyConfig_INIT_ISOLATED))
1324     {
1325         config_dict_invalid_value("_config_init");
1326         return -1;
1327     }
1328 
1329     if (config->hash_seed > MAX_HASH_SEED) {
1330         config_dict_invalid_value("hash_seed");
1331         return -1;
1332     }
1333     return 0;
1334 }
1335 
1336 
1337 static const char*
config_get_env(const PyConfig * config,const char * name)1338 config_get_env(const PyConfig *config, const char *name)
1339 {
1340     return _Py_GetEnv(config->use_environment, name);
1341 }
1342 
1343 
1344 /* Get a copy of the environment variable as wchar_t*.
1345    Return 0 on success, but *dest can be NULL.
1346    Return -1 on memory allocation failure. Return -2 on decoding error. */
1347 static PyStatus
config_get_env_dup(PyConfig * config,wchar_t ** dest,wchar_t * wname,char * name,const char * decode_err_msg)1348 config_get_env_dup(PyConfig *config,
1349                    wchar_t **dest,
1350                    wchar_t *wname, char *name,
1351                    const char *decode_err_msg)
1352 {
1353     assert(*dest == NULL);
1354     assert(config->use_environment >= 0);
1355 
1356     if (!config->use_environment) {
1357         *dest = NULL;
1358         return _PyStatus_OK();
1359     }
1360 
1361 #ifdef MS_WINDOWS
1362     const wchar_t *var = _wgetenv(wname);
1363     if (!var || var[0] == '\0') {
1364         *dest = NULL;
1365         return _PyStatus_OK();
1366     }
1367 
1368     return PyConfig_SetString(config, dest, var);
1369 #else
1370     const char *var = getenv(name);
1371     if (!var || var[0] == '\0') {
1372         *dest = NULL;
1373         return _PyStatus_OK();
1374     }
1375 
1376     return config_set_bytes_string(config, dest, var, decode_err_msg);
1377 #endif
1378 }
1379 
1380 
1381 #define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \
1382     config_get_env_dup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME)
1383 
1384 
1385 static void
config_get_global_vars(PyConfig * config)1386 config_get_global_vars(PyConfig *config)
1387 {
1388 _Py_COMP_DIAG_PUSH
1389 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1390     if (config->_config_init != _PyConfig_INIT_COMPAT) {
1391         /* Python and Isolated configuration ignore global variables */
1392         return;
1393     }
1394 
1395 #define COPY_FLAG(ATTR, VALUE) \
1396         if (config->ATTR == -1) { \
1397             config->ATTR = VALUE; \
1398         }
1399 #define COPY_NOT_FLAG(ATTR, VALUE) \
1400         if (config->ATTR == -1) { \
1401             config->ATTR = !(VALUE); \
1402         }
1403 
1404     COPY_FLAG(isolated, Py_IsolatedFlag);
1405     COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
1406     COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
1407     COPY_FLAG(inspect, Py_InspectFlag);
1408     COPY_FLAG(interactive, Py_InteractiveFlag);
1409     COPY_FLAG(optimization_level, Py_OptimizeFlag);
1410     COPY_FLAG(parser_debug, Py_DebugFlag);
1411     COPY_FLAG(verbose, Py_VerboseFlag);
1412     COPY_FLAG(quiet, Py_QuietFlag);
1413 #ifdef MS_WINDOWS
1414     COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
1415 #endif
1416     COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
1417 
1418     COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
1419     COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
1420     COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
1421     COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
1422 
1423 #undef COPY_FLAG
1424 #undef COPY_NOT_FLAG
1425 _Py_COMP_DIAG_POP
1426 }
1427 
1428 
1429 /* Set Py_xxx global configuration variables from 'config' configuration. */
1430 static void
config_set_global_vars(const PyConfig * config)1431 config_set_global_vars(const PyConfig *config)
1432 {
1433 _Py_COMP_DIAG_PUSH
1434 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1435 #define COPY_FLAG(ATTR, VAR) \
1436         if (config->ATTR != -1) { \
1437             VAR = config->ATTR; \
1438         }
1439 #define COPY_NOT_FLAG(ATTR, VAR) \
1440         if (config->ATTR != -1) { \
1441             VAR = !config->ATTR; \
1442         }
1443 
1444     COPY_FLAG(isolated, Py_IsolatedFlag);
1445     COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
1446     COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
1447     COPY_FLAG(inspect, Py_InspectFlag);
1448     COPY_FLAG(interactive, Py_InteractiveFlag);
1449     COPY_FLAG(optimization_level, Py_OptimizeFlag);
1450     COPY_FLAG(parser_debug, Py_DebugFlag);
1451     COPY_FLAG(verbose, Py_VerboseFlag);
1452     COPY_FLAG(quiet, Py_QuietFlag);
1453 #ifdef MS_WINDOWS
1454     COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
1455 #endif
1456     COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
1457 
1458     COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
1459     COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
1460     COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
1461     COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
1462 
1463     /* Random or non-zero hash seed */
1464     Py_HashRandomizationFlag = (config->use_hash_seed == 0 ||
1465                                 config->hash_seed != 0);
1466 
1467 #undef COPY_FLAG
1468 #undef COPY_NOT_FLAG
1469 _Py_COMP_DIAG_POP
1470 }
1471 
1472 
1473 static const wchar_t*
config_get_xoption(const PyConfig * config,wchar_t * name)1474 config_get_xoption(const PyConfig *config, wchar_t *name)
1475 {
1476     return _Py_get_xoption(&config->xoptions, name);
1477 }
1478 
1479 static const wchar_t*
config_get_xoption_value(const PyConfig * config,wchar_t * name)1480 config_get_xoption_value(const PyConfig *config, wchar_t *name)
1481 {
1482     const wchar_t *xoption = config_get_xoption(config, name);
1483     if (xoption == NULL) {
1484         return NULL;
1485     }
1486     const wchar_t *sep = wcschr(xoption, L'=');
1487     return sep ? sep + 1 : L"";
1488 }
1489 
1490 
1491 static PyStatus
config_init_hash_seed(PyConfig * config)1492 config_init_hash_seed(PyConfig *config)
1493 {
1494     static_assert(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc),
1495                   "_Py_HashSecret_t has wrong size");
1496 
1497     const char *seed_text = config_get_env(config, "PYTHONHASHSEED");
1498 
1499     /* Convert a text seed to a numeric one */
1500     if (seed_text && strcmp(seed_text, "random") != 0) {
1501         const char *endptr = seed_text;
1502         unsigned long seed;
1503         errno = 0;
1504         seed = strtoul(seed_text, (char **)&endptr, 10);
1505         if (*endptr != '\0'
1506             || seed > MAX_HASH_SEED
1507             || (errno == ERANGE && seed == ULONG_MAX))
1508         {
1509             return _PyStatus_ERR("PYTHONHASHSEED must be \"random\" "
1510                                 "or an integer in range [0; 4294967295]");
1511         }
1512         /* Use a specific hash */
1513         config->use_hash_seed = 1;
1514         config->hash_seed = seed;
1515     }
1516     else {
1517         /* Use a random hash */
1518         config->use_hash_seed = 0;
1519         config->hash_seed = 0;
1520     }
1521     return _PyStatus_OK();
1522 }
1523 
1524 
1525 static int
config_wstr_to_int(const wchar_t * wstr,int * result)1526 config_wstr_to_int(const wchar_t *wstr, int *result)
1527 {
1528     const wchar_t *endptr = wstr;
1529     errno = 0;
1530     long value = wcstol(wstr, (wchar_t **)&endptr, 10);
1531     if (*endptr != '\0' || errno == ERANGE) {
1532         return -1;
1533     }
1534     if (value < INT_MIN || value > INT_MAX) {
1535         return -1;
1536     }
1537 
1538     *result = (int)value;
1539     return 0;
1540 }
1541 
1542 static PyStatus
config_read_gil(PyConfig * config,size_t len,wchar_t first_char)1543 config_read_gil(PyConfig *config, size_t len, wchar_t first_char)
1544 {
1545     if (len == 1 && first_char == L'0') {
1546 #ifdef Py_GIL_DISABLED
1547         config->enable_gil = _PyConfig_GIL_DISABLE;
1548 #else
1549         return _PyStatus_ERR("Disabling the GIL is not supported by this build");
1550 #endif
1551     }
1552     else if (len == 1 && first_char == L'1') {
1553 #ifdef Py_GIL_DISABLED
1554         config->enable_gil = _PyConfig_GIL_ENABLE;
1555 #else
1556         return _PyStatus_OK();
1557 #endif
1558     }
1559     else {
1560         return _PyStatus_ERR("PYTHON_GIL / -X gil must be \"0\" or \"1\"");
1561     }
1562     return _PyStatus_OK();
1563 }
1564 
1565 static PyStatus
config_read_env_vars(PyConfig * config)1566 config_read_env_vars(PyConfig *config)
1567 {
1568     PyStatus status;
1569     int use_env = config->use_environment;
1570 
1571     /* Get environment variables */
1572     _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG");
1573     _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE");
1574     _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE");
1575     _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT");
1576 
1577     int dont_write_bytecode = 0;
1578     _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
1579     if (dont_write_bytecode) {
1580         config->write_bytecode = 0;
1581     }
1582 
1583     int no_user_site_directory = 0;
1584     _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE");
1585     if (no_user_site_directory) {
1586         config->user_site_directory = 0;
1587     }
1588 
1589     int unbuffered_stdio = 0;
1590     _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED");
1591     if (unbuffered_stdio) {
1592         config->buffered_stdio = 0;
1593     }
1594 
1595 #ifdef MS_WINDOWS
1596     _Py_get_env_flag(use_env, &config->legacy_windows_stdio,
1597                      "PYTHONLEGACYWINDOWSSTDIO");
1598 #endif
1599 
1600     if (config_get_env(config, "PYTHONDUMPREFS")) {
1601         config->dump_refs = 1;
1602     }
1603     if (config_get_env(config, "PYTHONMALLOCSTATS")) {
1604         config->malloc_stats = 1;
1605     }
1606 
1607     if (config->dump_refs_file == NULL) {
1608         status = CONFIG_GET_ENV_DUP(config, &config->dump_refs_file,
1609                                     L"PYTHONDUMPREFSFILE", "PYTHONDUMPREFSFILE");
1610         if (_PyStatus_EXCEPTION(status)) {
1611             return status;
1612         }
1613     }
1614 
1615     if (config->pythonpath_env == NULL) {
1616         status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,
1617                                     L"PYTHONPATH", "PYTHONPATH");
1618         if (_PyStatus_EXCEPTION(status)) {
1619             return status;
1620         }
1621     }
1622 
1623     if(config->platlibdir == NULL) {
1624         status = CONFIG_GET_ENV_DUP(config, &config->platlibdir,
1625                                     L"PYTHONPLATLIBDIR", "PYTHONPLATLIBDIR");
1626         if (_PyStatus_EXCEPTION(status)) {
1627             return status;
1628         }
1629     }
1630 
1631     if (config->use_hash_seed < 0) {
1632         status = config_init_hash_seed(config);
1633         if (_PyStatus_EXCEPTION(status)) {
1634             return status;
1635         }
1636     }
1637 
1638     if (config_get_env(config, "PYTHONSAFEPATH")) {
1639         config->safe_path = 1;
1640     }
1641 
1642     const char *gil = config_get_env(config, "PYTHON_GIL");
1643     if (gil != NULL) {
1644         size_t len = strlen(gil);
1645         status = config_read_gil(config, len, gil[0]);
1646         if (_PyStatus_EXCEPTION(status)) {
1647             return status;
1648         }
1649     }
1650 
1651     return _PyStatus_OK();
1652 }
1653 
1654 static PyStatus
config_init_cpu_count(PyConfig * config)1655 config_init_cpu_count(PyConfig *config)
1656 {
1657     const char *env = config_get_env(config, "PYTHON_CPU_COUNT");
1658     if (env) {
1659         int cpu_count = -1;
1660         if (strcmp(env, "default") == 0) {
1661             cpu_count = -1;
1662         }
1663         else if (_Py_str_to_int(env, &cpu_count) < 0 || cpu_count < 1) {
1664             goto error;
1665         }
1666         config->cpu_count = cpu_count;
1667     }
1668 
1669     const wchar_t *xoption = config_get_xoption(config, L"cpu_count");
1670     if (xoption) {
1671         int cpu_count = -1;
1672         const wchar_t *sep = wcschr(xoption, L'=');
1673         if (sep) {
1674             if (wcscmp(sep + 1, L"default") == 0) {
1675                 cpu_count = -1;
1676             }
1677             else if (config_wstr_to_int(sep + 1, &cpu_count) < 0 || cpu_count < 1) {
1678                 goto error;
1679             }
1680         }
1681         else {
1682             goto error;
1683         }
1684         config->cpu_count = cpu_count;
1685     }
1686     return _PyStatus_OK();
1687 
1688 error:
1689     return _PyStatus_ERR("-X cpu_count=n option: n is missing or an invalid number, "
1690                          "n must be greater than 0");
1691 }
1692 
1693 static PyStatus
config_init_perf_profiling(PyConfig * config)1694 config_init_perf_profiling(PyConfig *config)
1695 {
1696     int active = 0;
1697     const char *env = config_get_env(config, "PYTHONPERFSUPPORT");
1698     if (env) {
1699         if (_Py_str_to_int(env, &active) != 0) {
1700             active = 0;
1701         }
1702         if (active) {
1703             config->perf_profiling = 1;
1704         }
1705     }
1706     const wchar_t *xoption = config_get_xoption(config, L"perf");
1707     if (xoption) {
1708         config->perf_profiling = 1;
1709     }
1710     env = config_get_env(config, "PYTHON_PERF_JIT_SUPPORT");
1711     if (env) {
1712         if (_Py_str_to_int(env, &active) != 0) {
1713             active = 0;
1714         }
1715         if (active) {
1716             config->perf_profiling = 2;
1717         }
1718     }
1719     xoption = config_get_xoption(config, L"perf_jit");
1720     if (xoption) {
1721         config->perf_profiling = 2;
1722     }
1723 
1724     return _PyStatus_OK();
1725 
1726 }
1727 
1728 static PyStatus
config_init_tracemalloc(PyConfig * config)1729 config_init_tracemalloc(PyConfig *config)
1730 {
1731     int nframe;
1732     int valid;
1733 
1734     const char *env = config_get_env(config, "PYTHONTRACEMALLOC");
1735     if (env) {
1736         if (!_Py_str_to_int(env, &nframe)) {
1737             valid = (nframe >= 0);
1738         }
1739         else {
1740             valid = 0;
1741         }
1742         if (!valid) {
1743             return _PyStatus_ERR("PYTHONTRACEMALLOC: invalid number of frames");
1744         }
1745         config->tracemalloc = nframe;
1746     }
1747 
1748     const wchar_t *xoption = config_get_xoption(config, L"tracemalloc");
1749     if (xoption) {
1750         const wchar_t *sep = wcschr(xoption, L'=');
1751         if (sep) {
1752             if (!config_wstr_to_int(sep + 1, &nframe)) {
1753                 valid = (nframe >= 0);
1754             }
1755             else {
1756                 valid = 0;
1757             }
1758             if (!valid) {
1759                 return _PyStatus_ERR("-X tracemalloc=NFRAME: "
1760                                      "invalid number of frames");
1761             }
1762         }
1763         else {
1764             /* -X tracemalloc behaves as -X tracemalloc=1 */
1765             nframe = 1;
1766         }
1767         config->tracemalloc = nframe;
1768     }
1769     return _PyStatus_OK();
1770 }
1771 
1772 static PyStatus
config_init_int_max_str_digits(PyConfig * config)1773 config_init_int_max_str_digits(PyConfig *config)
1774 {
1775     int maxdigits;
1776 
1777     const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS");
1778     if (env) {
1779         bool valid = 0;
1780         if (!_Py_str_to_int(env, &maxdigits)) {
1781             valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
1782         }
1783         if (!valid) {
1784 #define STRINGIFY(VAL) _STRINGIFY(VAL)
1785 #define _STRINGIFY(VAL) #VAL
1786             return _PyStatus_ERR(
1787                     "PYTHONINTMAXSTRDIGITS: invalid limit; must be >= "
1788                     STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
1789                     " or 0 for unlimited.");
1790         }
1791         config->int_max_str_digits = maxdigits;
1792     }
1793 
1794     const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits");
1795     if (xoption) {
1796         const wchar_t *sep = wcschr(xoption, L'=');
1797         bool valid = 0;
1798         if (sep) {
1799             if (!config_wstr_to_int(sep + 1, &maxdigits)) {
1800                 valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
1801             }
1802         }
1803         if (!valid) {
1804             return _PyStatus_ERR(
1805                     "-X int_max_str_digits: invalid limit; must be >= "
1806                     STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
1807                     " or 0 for unlimited.");
1808 #undef _STRINGIFY
1809 #undef STRINGIFY
1810         }
1811         config->int_max_str_digits = maxdigits;
1812     }
1813     if (config->int_max_str_digits < 0) {
1814         config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
1815     }
1816     return _PyStatus_OK();
1817 }
1818 
1819 static PyStatus
config_init_pycache_prefix(PyConfig * config)1820 config_init_pycache_prefix(PyConfig *config)
1821 {
1822     assert(config->pycache_prefix == NULL);
1823 
1824     const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix");
1825     if (xoption) {
1826         const wchar_t *sep = wcschr(xoption, L'=');
1827         if (sep && wcslen(sep) > 1) {
1828             config->pycache_prefix = _PyMem_RawWcsdup(sep + 1);
1829             if (config->pycache_prefix == NULL) {
1830                 return _PyStatus_NO_MEMORY();
1831             }
1832         }
1833         else {
1834             // PYTHONPYCACHEPREFIX env var ignored
1835             // if "-X pycache_prefix=" option is used
1836             config->pycache_prefix = NULL;
1837         }
1838         return _PyStatus_OK();
1839     }
1840 
1841     return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix,
1842                               L"PYTHONPYCACHEPREFIX",
1843                               "PYTHONPYCACHEPREFIX");
1844 }
1845 
1846 
1847 #ifdef Py_DEBUG
1848 static PyStatus
config_init_run_presite(PyConfig * config)1849 config_init_run_presite(PyConfig *config)
1850 {
1851     assert(config->run_presite == NULL);
1852 
1853     const wchar_t *xoption = config_get_xoption(config, L"presite");
1854     if (xoption) {
1855         const wchar_t *sep = wcschr(xoption, L'=');
1856         if (sep && wcslen(sep) > 1) {
1857             config->run_presite = _PyMem_RawWcsdup(sep + 1);
1858             if (config->run_presite == NULL) {
1859                 return _PyStatus_NO_MEMORY();
1860             }
1861         }
1862         else {
1863             // PYTHON_PRESITE env var ignored
1864             // if "-X presite=" option is used
1865             config->run_presite = NULL;
1866         }
1867         return _PyStatus_OK();
1868     }
1869 
1870     return CONFIG_GET_ENV_DUP(config, &config->run_presite,
1871                               L"PYTHON_PRESITE",
1872                               "PYTHON_PRESITE");
1873 }
1874 #endif
1875 
1876 
1877 static PyStatus
config_read_complex_options(PyConfig * config)1878 config_read_complex_options(PyConfig *config)
1879 {
1880     /* More complex options configured by env var and -X option */
1881     if (config->faulthandler < 0) {
1882         if (config_get_env(config, "PYTHONFAULTHANDLER")
1883            || config_get_xoption(config, L"faulthandler")) {
1884             config->faulthandler = 1;
1885         }
1886     }
1887     if (config_get_env(config, "PYTHONPROFILEIMPORTTIME")
1888        || config_get_xoption(config, L"importtime")) {
1889         config->import_time = 1;
1890     }
1891 
1892     if (config_get_env(config, "PYTHONNODEBUGRANGES")
1893        || config_get_xoption(config, L"no_debug_ranges")) {
1894         config->code_debug_ranges = 0;
1895     }
1896 
1897     PyStatus status;
1898     if (config->tracemalloc < 0) {
1899         status = config_init_tracemalloc(config);
1900         if (_PyStatus_EXCEPTION(status)) {
1901             return status;
1902         }
1903     }
1904 
1905     if (config->perf_profiling < 0) {
1906         status = config_init_perf_profiling(config);
1907         if (_PyStatus_EXCEPTION(status)) {
1908             return status;
1909         }
1910     }
1911 
1912     if (config->int_max_str_digits < 0) {
1913         status = config_init_int_max_str_digits(config);
1914         if (_PyStatus_EXCEPTION(status)) {
1915             return status;
1916         }
1917     }
1918 
1919     if (config->cpu_count < 0) {
1920         status = config_init_cpu_count(config);
1921         if (_PyStatus_EXCEPTION(status)) {
1922             return status;
1923         }
1924     }
1925 
1926     if (config->pycache_prefix == NULL) {
1927         status = config_init_pycache_prefix(config);
1928         if (_PyStatus_EXCEPTION(status)) {
1929             return status;
1930         }
1931     }
1932 
1933 #ifdef Py_DEBUG
1934     if (config->run_presite == NULL) {
1935         status = config_init_run_presite(config);
1936         if (_PyStatus_EXCEPTION(status)) {
1937             return status;
1938         }
1939     }
1940 #endif
1941 
1942     return _PyStatus_OK();
1943 }
1944 
1945 
1946 static const wchar_t *
config_get_stdio_errors(const PyPreConfig * preconfig)1947 config_get_stdio_errors(const PyPreConfig *preconfig)
1948 {
1949     if (preconfig->utf8_mode) {
1950         /* UTF-8 Mode uses UTF-8/surrogateescape */
1951         return L"surrogateescape";
1952     }
1953 
1954 #ifndef MS_WINDOWS
1955     const char *loc = setlocale(LC_CTYPE, NULL);
1956     if (loc != NULL) {
1957         /* surrogateescape is the default in the legacy C and POSIX locales */
1958         if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) {
1959             return L"surrogateescape";
1960         }
1961 
1962 #ifdef PY_COERCE_C_LOCALE
1963         /* surrogateescape is the default in locale coercion target locales */
1964         if (_Py_IsLocaleCoercionTarget(loc)) {
1965             return L"surrogateescape";
1966         }
1967 #endif
1968     }
1969 
1970     return L"strict";
1971 #else
1972     /* On Windows, always use surrogateescape by default */
1973     return L"surrogateescape";
1974 #endif
1975 }
1976 
1977 
1978 // See also config_get_fs_encoding()
1979 static PyStatus
config_get_locale_encoding(PyConfig * config,const PyPreConfig * preconfig,wchar_t ** locale_encoding)1980 config_get_locale_encoding(PyConfig *config, const PyPreConfig *preconfig,
1981                            wchar_t **locale_encoding)
1982 {
1983     wchar_t *encoding;
1984     if (preconfig->utf8_mode) {
1985         encoding = _PyMem_RawWcsdup(L"utf-8");
1986     }
1987     else {
1988         encoding = _Py_GetLocaleEncoding();
1989     }
1990     if (encoding == NULL) {
1991         return _PyStatus_NO_MEMORY();
1992     }
1993     PyStatus status = PyConfig_SetString(config, locale_encoding, encoding);
1994     PyMem_RawFree(encoding);
1995     return status;
1996 }
1997 
1998 
1999 static PyStatus
config_init_stdio_encoding(PyConfig * config,const PyPreConfig * preconfig)2000 config_init_stdio_encoding(PyConfig *config,
2001                            const PyPreConfig *preconfig)
2002 {
2003     PyStatus status;
2004 
2005     // Exit if encoding and errors are defined
2006     if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {
2007         return _PyStatus_OK();
2008     }
2009 
2010     /* PYTHONIOENCODING environment variable */
2011     const char *opt = config_get_env(config, "PYTHONIOENCODING");
2012     if (opt) {
2013         char *pythonioencoding = _PyMem_RawStrdup(opt);
2014         if (pythonioencoding == NULL) {
2015             return _PyStatus_NO_MEMORY();
2016         }
2017 
2018         char *errors = strchr(pythonioencoding, ':');
2019         if (errors) {
2020             *errors = '\0';
2021             errors++;
2022             if (!errors[0]) {
2023                 errors = NULL;
2024             }
2025         }
2026 
2027         /* Does PYTHONIOENCODING contain an encoding? */
2028         if (pythonioencoding[0]) {
2029             if (config->stdio_encoding == NULL) {
2030                 status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
2031                                               pythonioencoding,
2032                                               "PYTHONIOENCODING environment variable");
2033                 if (_PyStatus_EXCEPTION(status)) {
2034                     PyMem_RawFree(pythonioencoding);
2035                     return status;
2036                 }
2037             }
2038 
2039             /* If the encoding is set but not the error handler,
2040                use "strict" error handler by default.
2041                PYTHONIOENCODING=latin1 behaves as
2042                PYTHONIOENCODING=latin1:strict. */
2043             if (!errors) {
2044                 errors = "strict";
2045             }
2046         }
2047 
2048         if (config->stdio_errors == NULL && errors != NULL) {
2049             status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
2050                                           errors,
2051                                           "PYTHONIOENCODING environment variable");
2052             if (_PyStatus_EXCEPTION(status)) {
2053                 PyMem_RawFree(pythonioencoding);
2054                 return status;
2055             }
2056         }
2057 
2058         PyMem_RawFree(pythonioencoding);
2059     }
2060 
2061     /* Choose the default error handler based on the current locale. */
2062     if (config->stdio_encoding == NULL) {
2063         status = config_get_locale_encoding(config, preconfig,
2064                                             &config->stdio_encoding);
2065         if (_PyStatus_EXCEPTION(status)) {
2066             return status;
2067         }
2068     }
2069     if (config->stdio_errors == NULL) {
2070         const wchar_t *errors = config_get_stdio_errors(preconfig);
2071         assert(errors != NULL);
2072 
2073         status = PyConfig_SetString(config, &config->stdio_errors, errors);
2074         if (_PyStatus_EXCEPTION(status)) {
2075             return status;
2076         }
2077     }
2078 
2079     return _PyStatus_OK();
2080 }
2081 
2082 
2083 // See also config_get_locale_encoding()
2084 static PyStatus
config_get_fs_encoding(PyConfig * config,const PyPreConfig * preconfig,wchar_t ** fs_encoding)2085 config_get_fs_encoding(PyConfig *config, const PyPreConfig *preconfig,
2086                        wchar_t **fs_encoding)
2087 {
2088 #ifdef _Py_FORCE_UTF8_FS_ENCODING
2089     return PyConfig_SetString(config, fs_encoding, L"utf-8");
2090 #elif defined(MS_WINDOWS)
2091     const wchar_t *encoding;
2092     if (preconfig->legacy_windows_fs_encoding) {
2093         // Legacy Windows filesystem encoding: mbcs/replace
2094         encoding = L"mbcs";
2095     }
2096     else {
2097         // Windows defaults to utf-8/surrogatepass (PEP 529)
2098         encoding = L"utf-8";
2099     }
2100      return PyConfig_SetString(config, fs_encoding, encoding);
2101 #else  // !MS_WINDOWS
2102     if (preconfig->utf8_mode) {
2103         return PyConfig_SetString(config, fs_encoding, L"utf-8");
2104     }
2105 
2106     if (_Py_GetForceASCII()) {
2107         return PyConfig_SetString(config, fs_encoding, L"ascii");
2108     }
2109 
2110     return config_get_locale_encoding(config, preconfig, fs_encoding);
2111 #endif  // !MS_WINDOWS
2112 }
2113 
2114 
2115 static PyStatus
config_init_fs_encoding(PyConfig * config,const PyPreConfig * preconfig)2116 config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig)
2117 {
2118     PyStatus status;
2119 
2120     if (config->filesystem_encoding == NULL) {
2121         status = config_get_fs_encoding(config, preconfig,
2122                                         &config->filesystem_encoding);
2123         if (_PyStatus_EXCEPTION(status)) {
2124             return status;
2125         }
2126     }
2127 
2128     if (config->filesystem_errors == NULL) {
2129         const wchar_t *errors;
2130 #ifdef MS_WINDOWS
2131         if (preconfig->legacy_windows_fs_encoding) {
2132             errors = L"replace";
2133         }
2134         else {
2135             errors = L"surrogatepass";
2136         }
2137 #else
2138         errors = L"surrogateescape";
2139 #endif
2140         status = PyConfig_SetString(config, &config->filesystem_errors, errors);
2141         if (_PyStatus_EXCEPTION(status)) {
2142             return status;
2143         }
2144     }
2145     return _PyStatus_OK();
2146 }
2147 
2148 
2149 static PyStatus
config_init_import(PyConfig * config,int compute_path_config)2150 config_init_import(PyConfig *config, int compute_path_config)
2151 {
2152     PyStatus status;
2153 
2154     status = _PyConfig_InitPathConfig(config, compute_path_config);
2155     if (_PyStatus_EXCEPTION(status)) {
2156         return status;
2157     }
2158 
2159     const char *env = config_get_env(config, "PYTHON_FROZEN_MODULES");
2160     if (env == NULL) {
2161     }
2162     else if (strcmp(env, "on") == 0) {
2163         config->use_frozen_modules = 1;
2164     }
2165     else if (strcmp(env, "off") == 0) {
2166         config->use_frozen_modules = 0;
2167     } else {
2168         return PyStatus_Error("bad value for PYTHON_FROZEN_MODULES "
2169                               "(expected \"on\" or \"off\")");
2170     }
2171 
2172     /* -X frozen_modules=[on|off] */
2173     const wchar_t *value = config_get_xoption_value(config, L"frozen_modules");
2174     if (value == NULL) {
2175     }
2176     else if (wcscmp(value, L"on") == 0) {
2177         config->use_frozen_modules = 1;
2178     }
2179     else if (wcscmp(value, L"off") == 0) {
2180         config->use_frozen_modules = 0;
2181     }
2182     else if (wcslen(value) == 0) {
2183         // "-X frozen_modules" and "-X frozen_modules=" both imply "on".
2184         config->use_frozen_modules = 1;
2185     }
2186     else {
2187         return PyStatus_Error("bad value for option -X frozen_modules "
2188                               "(expected \"on\" or \"off\")");
2189     }
2190 
2191     assert(config->use_frozen_modules >= 0);
2192     return _PyStatus_OK();
2193 }
2194 
2195 PyStatus
_PyConfig_InitImportConfig(PyConfig * config)2196 _PyConfig_InitImportConfig(PyConfig *config)
2197 {
2198     return config_init_import(config, 1);
2199 }
2200 
2201 
2202 static PyStatus
config_read(PyConfig * config,int compute_path_config)2203 config_read(PyConfig *config, int compute_path_config)
2204 {
2205     PyStatus status;
2206     const PyPreConfig *preconfig = &_PyRuntime.preconfig;
2207 
2208     if (config->use_environment) {
2209         status = config_read_env_vars(config);
2210         if (_PyStatus_EXCEPTION(status)) {
2211             return status;
2212         }
2213     }
2214 
2215     /* -X options */
2216     if (config_get_xoption(config, L"showrefcount")) {
2217         config->show_ref_count = 1;
2218     }
2219 
2220     const wchar_t *x_gil = config_get_xoption_value(config, L"gil");
2221     if (x_gil != NULL) {
2222         size_t len = wcslen(x_gil);
2223         status = config_read_gil(config, len, x_gil[0]);
2224         if (_PyStatus_EXCEPTION(status)) {
2225             return status;
2226         }
2227     }
2228 
2229 #ifdef Py_STATS
2230     if (config_get_xoption(config, L"pystats")) {
2231         config->_pystats = 1;
2232     }
2233     else if (config_get_env(config, "PYTHONSTATS")) {
2234         config->_pystats = 1;
2235     }
2236     if (config->_pystats < 0) {
2237         config->_pystats = 0;
2238     }
2239 #endif
2240 
2241     status = config_read_complex_options(config);
2242     if (_PyStatus_EXCEPTION(status)) {
2243         return status;
2244     }
2245 
2246     if (config->_install_importlib) {
2247         status = config_init_import(config, compute_path_config);
2248         if (_PyStatus_EXCEPTION(status)) {
2249             return status;
2250         }
2251     }
2252 
2253     /* default values */
2254     if (config->dev_mode) {
2255         if (config->faulthandler < 0) {
2256             config->faulthandler = 1;
2257         }
2258     }
2259     if (config->faulthandler < 0) {
2260         config->faulthandler = 0;
2261     }
2262     if (config->tracemalloc < 0) {
2263         config->tracemalloc = 0;
2264     }
2265     if (config->perf_profiling < 0) {
2266         config->perf_profiling = 0;
2267     }
2268     if (config->use_hash_seed < 0) {
2269         config->use_hash_seed = 0;
2270         config->hash_seed = 0;
2271     }
2272 
2273     if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) {
2274         status = config_init_fs_encoding(config, preconfig);
2275         if (_PyStatus_EXCEPTION(status)) {
2276             return status;
2277         }
2278     }
2279 
2280     status = config_init_stdio_encoding(config, preconfig);
2281     if (_PyStatus_EXCEPTION(status)) {
2282         return status;
2283     }
2284 
2285     if (config->argv.length < 1) {
2286         /* Ensure at least one (empty) argument is seen */
2287         status = PyWideStringList_Append(&config->argv, L"");
2288         if (_PyStatus_EXCEPTION(status)) {
2289             return status;
2290         }
2291     }
2292 
2293     if (config->check_hash_pycs_mode == NULL) {
2294         status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
2295                                     L"default");
2296         if (_PyStatus_EXCEPTION(status)) {
2297             return status;
2298         }
2299     }
2300 
2301     if (config->configure_c_stdio < 0) {
2302         config->configure_c_stdio = 1;
2303     }
2304 
2305     // Only parse arguments once.
2306     if (config->parse_argv == 1) {
2307         config->parse_argv = 2;
2308     }
2309 
2310     return _PyStatus_OK();
2311 }
2312 
2313 
2314 static void
config_init_stdio(const PyConfig * config)2315 config_init_stdio(const PyConfig *config)
2316 {
2317 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
2318     /* don't translate newlines (\r\n <=> \n) */
2319     _setmode(fileno(stdin), O_BINARY);
2320     _setmode(fileno(stdout), O_BINARY);
2321     _setmode(fileno(stderr), O_BINARY);
2322 #endif
2323 
2324     if (!config->buffered_stdio) {
2325 #ifdef HAVE_SETVBUF
2326         setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
2327         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
2328         setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
2329 #else /* !HAVE_SETVBUF */
2330         setbuf(stdin,  (char *)NULL);
2331         setbuf(stdout, (char *)NULL);
2332         setbuf(stderr, (char *)NULL);
2333 #endif /* !HAVE_SETVBUF */
2334     }
2335     else if (config->interactive) {
2336 #ifdef MS_WINDOWS
2337         /* Doesn't have to have line-buffered -- use unbuffered */
2338         /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
2339         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
2340 #else /* !MS_WINDOWS */
2341 #ifdef HAVE_SETVBUF
2342         setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
2343         setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
2344 #endif /* HAVE_SETVBUF */
2345 #endif /* !MS_WINDOWS */
2346         /* Leave stderr alone - it should be unbuffered anyway. */
2347     }
2348 }
2349 
2350 
2351 /* Write the configuration:
2352 
2353    - set Py_xxx global configuration variables
2354    - initialize C standard streams (stdin, stdout, stderr) */
2355 PyStatus
_PyConfig_Write(const PyConfig * config,_PyRuntimeState * runtime)2356 _PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime)
2357 {
2358     config_set_global_vars(config);
2359 
2360     if (config->configure_c_stdio) {
2361         config_init_stdio(config);
2362     }
2363 
2364     /* Write the new pre-configuration into _PyRuntime */
2365     PyPreConfig *preconfig = &runtime->preconfig;
2366     preconfig->isolated = config->isolated;
2367     preconfig->use_environment = config->use_environment;
2368     preconfig->dev_mode = config->dev_mode;
2369 
2370     if (_Py_SetArgcArgv(config->orig_argv.length,
2371                         config->orig_argv.items) < 0)
2372     {
2373         return _PyStatus_NO_MEMORY();
2374     }
2375 
2376 #ifdef Py_STATS
2377     if (config->_pystats) {
2378         _Py_StatsOn();
2379     }
2380 #endif
2381 
2382     return _PyStatus_OK();
2383 }
2384 
2385 
2386 /* --- PyConfig command line parser -------------------------- */
2387 
2388 static void
config_usage(int error,const wchar_t * program)2389 config_usage(int error, const wchar_t* program)
2390 {
2391     FILE *f = error ? stderr : stdout;
2392 
2393     fprintf(f, usage_line, program);
2394     if (error)
2395         fprintf(f, "Try `python -h' for more information.\n");
2396     else {
2397         fputs(usage_help, f);
2398     }
2399 }
2400 
2401 static void
config_envvars_usage(void)2402 config_envvars_usage(void)
2403 {
2404     printf(usage_envvars, (wint_t)DELIM, (wint_t)DELIM, PYTHONHOMEHELP);
2405 }
2406 
2407 static void
config_xoptions_usage(void)2408 config_xoptions_usage(void)
2409 {
2410     puts(usage_xoptions);
2411 }
2412 
2413 static void
config_complete_usage(const wchar_t * program)2414 config_complete_usage(const wchar_t* program)
2415 {
2416    config_usage(0, program);
2417    putchar('\n');
2418    config_envvars_usage();
2419    putchar('\n');
2420    config_xoptions_usage();
2421 }
2422 
2423 
2424 /* Parse the command line arguments */
2425 static PyStatus
config_parse_cmdline(PyConfig * config,PyWideStringList * warnoptions,Py_ssize_t * opt_index)2426 config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions,
2427                      Py_ssize_t *opt_index)
2428 {
2429     PyStatus status;
2430     const PyWideStringList *argv = &config->argv;
2431     int print_version = 0;
2432     const wchar_t* program = config->program_name;
2433     if (!program && argv->length >= 1) {
2434         program = argv->items[0];
2435     }
2436 
2437     _PyOS_ResetGetOpt();
2438     do {
2439         int longindex = -1;
2440         int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
2441         if (c == EOF) {
2442             break;
2443         }
2444 
2445         if (c == 'c') {
2446             if (config->run_command == NULL) {
2447                 /* -c is the last option; following arguments
2448                    that look like options are left for the
2449                    command to interpret. */
2450                 size_t len = wcslen(_PyOS_optarg) + 1 + 1;
2451                 wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len);
2452                 if (command == NULL) {
2453                     return _PyStatus_NO_MEMORY();
2454                 }
2455                 memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t));
2456                 command[len - 2] = '\n';
2457                 command[len - 1] = 0;
2458                 config->run_command = command;
2459             }
2460             break;
2461         }
2462 
2463         if (c == 'm') {
2464             /* -m is the last option; following arguments
2465                that look like options are left for the
2466                module to interpret. */
2467             if (config->run_module == NULL) {
2468                 config->run_module = _PyMem_RawWcsdup(_PyOS_optarg);
2469                 if (config->run_module == NULL) {
2470                     return _PyStatus_NO_MEMORY();
2471                 }
2472             }
2473             break;
2474         }
2475 
2476         switch (c) {
2477         // Integers represent long options, see Python/getopt.c
2478         case 0:
2479             // check-hash-based-pycs
2480             if (wcscmp(_PyOS_optarg, L"always") == 0
2481                 || wcscmp(_PyOS_optarg, L"never") == 0
2482                 || wcscmp(_PyOS_optarg, L"default") == 0)
2483             {
2484                 status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
2485                                             _PyOS_optarg);
2486                 if (_PyStatus_EXCEPTION(status)) {
2487                     return status;
2488                 }
2489             } else {
2490                 fprintf(stderr, "--check-hash-based-pycs must be one of "
2491                         "'default', 'always', or 'never'\n");
2492                 config_usage(1, program);
2493                 return _PyStatus_EXIT(2);
2494             }
2495             break;
2496 
2497         case 1:
2498             // help-all
2499             config_complete_usage(program);
2500             return _PyStatus_EXIT(0);
2501 
2502         case 2:
2503             // help-env
2504             config_envvars_usage();
2505             return _PyStatus_EXIT(0);
2506 
2507         case 3:
2508             // help-xoptions
2509             config_xoptions_usage();
2510             return _PyStatus_EXIT(0);
2511 
2512         case 'b':
2513             config->bytes_warning++;
2514             break;
2515 
2516         case 'd':
2517             config->parser_debug++;
2518             break;
2519 
2520         case 'i':
2521             config->inspect++;
2522             config->interactive++;
2523             break;
2524 
2525         case 'E':
2526         case 'I':
2527         case 'X':
2528             /* option handled by _PyPreCmdline_Read() */
2529             break;
2530 
2531         /* case 'J': reserved for Jython */
2532 
2533         case 'O':
2534             config->optimization_level++;
2535             break;
2536 
2537         case 'P':
2538             config->safe_path = 1;
2539             break;
2540 
2541         case 'B':
2542             config->write_bytecode = 0;
2543             break;
2544 
2545         case 's':
2546             config->user_site_directory = 0;
2547             break;
2548 
2549         case 'S':
2550             config->site_import = 0;
2551             break;
2552 
2553         case 't':
2554             /* ignored for backwards compatibility */
2555             break;
2556 
2557         case 'u':
2558             config->buffered_stdio = 0;
2559             break;
2560 
2561         case 'v':
2562             config->verbose++;
2563             break;
2564 
2565         case 'x':
2566             config->skip_source_first_line = 1;
2567             break;
2568 
2569         case 'h':
2570         case '?':
2571             config_usage(0, program);
2572             return _PyStatus_EXIT(0);
2573 
2574         case 'V':
2575             print_version++;
2576             break;
2577 
2578         case 'W':
2579             status = PyWideStringList_Append(warnoptions, _PyOS_optarg);
2580             if (_PyStatus_EXCEPTION(status)) {
2581                 return status;
2582             }
2583             break;
2584 
2585         case 'q':
2586             config->quiet++;
2587             break;
2588 
2589         case 'R':
2590             config->use_hash_seed = 0;
2591             break;
2592 
2593         /* This space reserved for other options */
2594 
2595         default:
2596             /* unknown argument: parsing failed */
2597             config_usage(1, program);
2598             return _PyStatus_EXIT(2);
2599         }
2600     } while (1);
2601 
2602     if (print_version) {
2603         printf("Python %s\n",
2604                 (print_version >= 2) ? Py_GetVersion() : PY_VERSION);
2605         return _PyStatus_EXIT(0);
2606     }
2607 
2608     if (config->run_command == NULL && config->run_module == NULL
2609         && _PyOS_optind < argv->length
2610         && wcscmp(argv->items[_PyOS_optind], L"-") != 0
2611         && config->run_filename == NULL)
2612     {
2613         config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]);
2614         if (config->run_filename == NULL) {
2615             return _PyStatus_NO_MEMORY();
2616         }
2617     }
2618 
2619     if (config->run_command != NULL || config->run_module != NULL) {
2620         /* Backup _PyOS_optind */
2621         _PyOS_optind--;
2622     }
2623 
2624     *opt_index = _PyOS_optind;
2625 
2626     return _PyStatus_OK();
2627 }
2628 
2629 
2630 #ifdef MS_WINDOWS
2631 #  define WCSTOK wcstok_s
2632 #else
2633 #  define WCSTOK wcstok
2634 #endif
2635 
2636 /* Get warning options from PYTHONWARNINGS environment variable. */
2637 static PyStatus
config_init_env_warnoptions(PyConfig * config,PyWideStringList * warnoptions)2638 config_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions)
2639 {
2640     PyStatus status;
2641     /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */
2642     wchar_t *env = NULL;
2643     status = CONFIG_GET_ENV_DUP(config, &env,
2644                              L"PYTHONWARNINGS", "PYTHONWARNINGS");
2645     if (_PyStatus_EXCEPTION(status)) {
2646         return status;
2647     }
2648 
2649     /* env var is not set or is empty */
2650     if (env == NULL) {
2651         return _PyStatus_OK();
2652     }
2653 
2654 
2655     wchar_t *warning, *context = NULL;
2656     for (warning = WCSTOK(env, L",", &context);
2657          warning != NULL;
2658          warning = WCSTOK(NULL, L",", &context))
2659     {
2660         status = PyWideStringList_Append(warnoptions, warning);
2661         if (_PyStatus_EXCEPTION(status)) {
2662             PyMem_RawFree(env);
2663             return status;
2664         }
2665     }
2666     PyMem_RawFree(env);
2667     return _PyStatus_OK();
2668 }
2669 
2670 
2671 static PyStatus
warnoptions_append(PyConfig * config,PyWideStringList * options,const wchar_t * option)2672 warnoptions_append(PyConfig *config, PyWideStringList *options,
2673                    const wchar_t *option)
2674 {
2675     /* config_init_warnoptions() add existing config warnoptions at the end:
2676        ensure that the new option is not already present in this list to
2677        prevent change the options order when config_init_warnoptions() is
2678        called twice. */
2679     if (_PyWideStringList_Find(&config->warnoptions, option)) {
2680         /* Already present: do nothing */
2681         return _PyStatus_OK();
2682     }
2683     if (_PyWideStringList_Find(options, option)) {
2684         /* Already present: do nothing */
2685         return _PyStatus_OK();
2686     }
2687     return PyWideStringList_Append(options, option);
2688 }
2689 
2690 
2691 static PyStatus
warnoptions_extend(PyConfig * config,PyWideStringList * options,const PyWideStringList * options2)2692 warnoptions_extend(PyConfig *config, PyWideStringList *options,
2693                    const PyWideStringList *options2)
2694 {
2695     const Py_ssize_t len = options2->length;
2696     wchar_t *const *items = options2->items;
2697 
2698     for (Py_ssize_t i = 0; i < len; i++) {
2699         PyStatus status = warnoptions_append(config, options, items[i]);
2700         if (_PyStatus_EXCEPTION(status)) {
2701             return status;
2702         }
2703     }
2704     return _PyStatus_OK();
2705 }
2706 
2707 
2708 static PyStatus
config_init_warnoptions(PyConfig * config,const PyWideStringList * cmdline_warnoptions,const PyWideStringList * env_warnoptions,const PyWideStringList * sys_warnoptions)2709 config_init_warnoptions(PyConfig *config,
2710                         const PyWideStringList *cmdline_warnoptions,
2711                         const PyWideStringList *env_warnoptions,
2712                         const PyWideStringList *sys_warnoptions)
2713 {
2714     PyStatus status;
2715     PyWideStringList options = _PyWideStringList_INIT;
2716 
2717     /* Priority of warnings options, lowest to highest:
2718      *
2719      * - any implicit filters added by _warnings.c/warnings.py
2720      * - PyConfig.dev_mode: "default" filter
2721      * - PYTHONWARNINGS environment variable
2722      * - '-W' command line options
2723      * - PyConfig.bytes_warning ('-b' and '-bb' command line options):
2724      *   "default::BytesWarning" or "error::BytesWarning" filter
2725      * - early PySys_AddWarnOption() calls
2726      * - PyConfig.warnoptions
2727      *
2728      * PyConfig.warnoptions is copied to sys.warnoptions. Since the warnings
2729      * module works on the basis of "the most recently added filter will be
2730      * checked first", we add the lowest precedence entries first so that later
2731      * entries override them.
2732      */
2733 
2734     if (config->dev_mode) {
2735         status = warnoptions_append(config, &options, L"default");
2736         if (_PyStatus_EXCEPTION(status)) {
2737             goto error;
2738         }
2739     }
2740 
2741     status = warnoptions_extend(config, &options, env_warnoptions);
2742     if (_PyStatus_EXCEPTION(status)) {
2743         goto error;
2744     }
2745 
2746     status = warnoptions_extend(config, &options, cmdline_warnoptions);
2747     if (_PyStatus_EXCEPTION(status)) {
2748         goto error;
2749     }
2750 
2751     /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
2752      * don't even try to emit a warning, so we skip setting the filter in that
2753      * case.
2754      */
2755     if (config->bytes_warning) {
2756         const wchar_t *filter;
2757         if (config->bytes_warning> 1) {
2758             filter = L"error::BytesWarning";
2759         }
2760         else {
2761             filter = L"default::BytesWarning";
2762         }
2763         status = warnoptions_append(config, &options, filter);
2764         if (_PyStatus_EXCEPTION(status)) {
2765             goto error;
2766         }
2767     }
2768 
2769     status = warnoptions_extend(config, &options, sys_warnoptions);
2770     if (_PyStatus_EXCEPTION(status)) {
2771         goto error;
2772     }
2773 
2774     /* Always add all PyConfig.warnoptions options */
2775     status = _PyWideStringList_Extend(&options, &config->warnoptions);
2776     if (_PyStatus_EXCEPTION(status)) {
2777         goto error;
2778     }
2779 
2780     _PyWideStringList_Clear(&config->warnoptions);
2781     config->warnoptions = options;
2782     return _PyStatus_OK();
2783 
2784 error:
2785     _PyWideStringList_Clear(&options);
2786     return status;
2787 }
2788 
2789 
2790 static PyStatus
config_update_argv(PyConfig * config,Py_ssize_t opt_index)2791 config_update_argv(PyConfig *config, Py_ssize_t opt_index)
2792 {
2793     const PyWideStringList *cmdline_argv = &config->argv;
2794     PyWideStringList config_argv = _PyWideStringList_INIT;
2795 
2796     /* Copy argv to be able to modify it (to force -c/-m) */
2797     if (cmdline_argv->length <= opt_index) {
2798         /* Ensure at least one (empty) argument is seen */
2799         PyStatus status = PyWideStringList_Append(&config_argv, L"");
2800         if (_PyStatus_EXCEPTION(status)) {
2801             return status;
2802         }
2803     }
2804     else {
2805         PyWideStringList slice;
2806         slice.length = cmdline_argv->length - opt_index;
2807         slice.items = &cmdline_argv->items[opt_index];
2808         if (_PyWideStringList_Copy(&config_argv, &slice) < 0) {
2809             return _PyStatus_NO_MEMORY();
2810         }
2811     }
2812     assert(config_argv.length >= 1);
2813 
2814     wchar_t *arg0 = NULL;
2815     if (config->run_command != NULL) {
2816         /* Force sys.argv[0] = '-c' */
2817         arg0 = L"-c";
2818     }
2819     else if (config->run_module != NULL) {
2820         /* Force sys.argv[0] = '-m'*/
2821         arg0 = L"-m";
2822     }
2823 
2824     if (arg0 != NULL) {
2825         arg0 = _PyMem_RawWcsdup(arg0);
2826         if (arg0 == NULL) {
2827             _PyWideStringList_Clear(&config_argv);
2828             return _PyStatus_NO_MEMORY();
2829         }
2830 
2831         PyMem_RawFree(config_argv.items[0]);
2832         config_argv.items[0] = arg0;
2833     }
2834 
2835     _PyWideStringList_Clear(&config->argv);
2836     config->argv = config_argv;
2837     return _PyStatus_OK();
2838 }
2839 
2840 
2841 static PyStatus
core_read_precmdline(PyConfig * config,_PyPreCmdline * precmdline)2842 core_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline)
2843 {
2844     PyStatus status;
2845 
2846     if (config->parse_argv == 1) {
2847         if (_PyWideStringList_Copy(&precmdline->argv, &config->argv) < 0) {
2848             return _PyStatus_NO_MEMORY();
2849         }
2850     }
2851 
2852     PyPreConfig preconfig;
2853 
2854     status = _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig);
2855     if (_PyStatus_EXCEPTION(status)) {
2856         return status;
2857     }
2858 
2859     _PyPreConfig_GetConfig(&preconfig, config);
2860 
2861     status = _PyPreCmdline_Read(precmdline, &preconfig);
2862     if (_PyStatus_EXCEPTION(status)) {
2863         return status;
2864     }
2865 
2866     status = _PyPreCmdline_SetConfig(precmdline, config);
2867     if (_PyStatus_EXCEPTION(status)) {
2868         return status;
2869     }
2870     return _PyStatus_OK();
2871 }
2872 
2873 
2874 /* Get run_filename absolute path */
2875 static PyStatus
config_run_filename_abspath(PyConfig * config)2876 config_run_filename_abspath(PyConfig *config)
2877 {
2878     if (!config->run_filename) {
2879         return _PyStatus_OK();
2880     }
2881 
2882 #ifndef MS_WINDOWS
2883     if (_Py_isabs(config->run_filename)) {
2884         /* path is already absolute */
2885         return _PyStatus_OK();
2886     }
2887 #endif
2888 
2889     wchar_t *abs_filename;
2890     if (_Py_abspath(config->run_filename, &abs_filename) < 0) {
2891         /* failed to get the absolute path of the command line filename:
2892            ignore the error, keep the relative path */
2893         return _PyStatus_OK();
2894     }
2895     if (abs_filename == NULL) {
2896         return _PyStatus_NO_MEMORY();
2897     }
2898 
2899     PyMem_RawFree(config->run_filename);
2900     config->run_filename = abs_filename;
2901     return _PyStatus_OK();
2902 }
2903 
2904 
2905 static PyStatus
config_read_cmdline(PyConfig * config)2906 config_read_cmdline(PyConfig *config)
2907 {
2908     PyStatus status;
2909     PyWideStringList cmdline_warnoptions = _PyWideStringList_INIT;
2910     PyWideStringList env_warnoptions = _PyWideStringList_INIT;
2911     PyWideStringList sys_warnoptions = _PyWideStringList_INIT;
2912 
2913     if (config->parse_argv < 0) {
2914         config->parse_argv = 1;
2915     }
2916 
2917     if (config->parse_argv == 1) {
2918         Py_ssize_t opt_index;
2919         status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index);
2920         if (_PyStatus_EXCEPTION(status)) {
2921             goto done;
2922         }
2923 
2924         status = config_run_filename_abspath(config);
2925         if (_PyStatus_EXCEPTION(status)) {
2926             goto done;
2927         }
2928 
2929         status = config_update_argv(config, opt_index);
2930         if (_PyStatus_EXCEPTION(status)) {
2931             goto done;
2932         }
2933     }
2934     else {
2935         status = config_run_filename_abspath(config);
2936         if (_PyStatus_EXCEPTION(status)) {
2937             goto done;
2938         }
2939     }
2940 
2941     if (config->use_environment) {
2942         status = config_init_env_warnoptions(config, &env_warnoptions);
2943         if (_PyStatus_EXCEPTION(status)) {
2944             goto done;
2945         }
2946     }
2947 
2948     /* Handle early PySys_AddWarnOption() calls */
2949     status = _PySys_ReadPreinitWarnOptions(&sys_warnoptions);
2950     if (_PyStatus_EXCEPTION(status)) {
2951         goto done;
2952     }
2953 
2954     status = config_init_warnoptions(config,
2955                                      &cmdline_warnoptions,
2956                                      &env_warnoptions,
2957                                      &sys_warnoptions);
2958     if (_PyStatus_EXCEPTION(status)) {
2959         goto done;
2960     }
2961 
2962     status = _PyStatus_OK();
2963 
2964 done:
2965     _PyWideStringList_Clear(&cmdline_warnoptions);
2966     _PyWideStringList_Clear(&env_warnoptions);
2967     _PyWideStringList_Clear(&sys_warnoptions);
2968     return status;
2969 }
2970 
2971 
2972 PyStatus
_PyConfig_SetPyArgv(PyConfig * config,const _PyArgv * args)2973 _PyConfig_SetPyArgv(PyConfig *config, const _PyArgv *args)
2974 {
2975     PyStatus status = _Py_PreInitializeFromConfig(config, args);
2976     if (_PyStatus_EXCEPTION(status)) {
2977         return status;
2978     }
2979 
2980     return _PyArgv_AsWstrList(args, &config->argv);
2981 }
2982 
2983 
2984 /* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python
2985    if needed to ensure that encodings are properly configured. */
2986 PyStatus
PyConfig_SetBytesArgv(PyConfig * config,Py_ssize_t argc,char * const * argv)2987 PyConfig_SetBytesArgv(PyConfig *config, Py_ssize_t argc, char * const *argv)
2988 {
2989     _PyArgv args = {
2990         .argc = argc,
2991         .use_bytes_argv = 1,
2992         .bytes_argv = argv,
2993         .wchar_argv = NULL};
2994     return _PyConfig_SetPyArgv(config, &args);
2995 }
2996 
2997 
2998 PyStatus
PyConfig_SetArgv(PyConfig * config,Py_ssize_t argc,wchar_t * const * argv)2999 PyConfig_SetArgv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
3000 {
3001     _PyArgv args = {
3002         .argc = argc,
3003         .use_bytes_argv = 0,
3004         .bytes_argv = NULL,
3005         .wchar_argv = argv};
3006     return _PyConfig_SetPyArgv(config, &args);
3007 }
3008 
3009 
3010 PyStatus
PyConfig_SetWideStringList(PyConfig * config,PyWideStringList * list,Py_ssize_t length,wchar_t ** items)3011 PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list,
3012                            Py_ssize_t length, wchar_t **items)
3013 {
3014     PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
3015     if (_PyStatus_EXCEPTION(status)) {
3016         return status;
3017     }
3018 
3019     PyWideStringList list2 = {.length = length, .items = items};
3020     if (_PyWideStringList_Copy(list, &list2) < 0) {
3021         return _PyStatus_NO_MEMORY();
3022     }
3023     return _PyStatus_OK();
3024 }
3025 
3026 
3027 /* Read the configuration into PyConfig from:
3028 
3029    * Command line arguments
3030    * Environment variables
3031    * Py_xxx global configuration variables
3032 
3033    The only side effects are to modify config and to call _Py_SetArgcArgv(). */
3034 PyStatus
_PyConfig_Read(PyConfig * config,int compute_path_config)3035 _PyConfig_Read(PyConfig *config, int compute_path_config)
3036 {
3037     PyStatus status;
3038 
3039     status = _Py_PreInitializeFromConfig(config, NULL);
3040     if (_PyStatus_EXCEPTION(status)) {
3041         return status;
3042     }
3043 
3044     config_get_global_vars(config);
3045 
3046     if (config->orig_argv.length == 0
3047         && !(config->argv.length == 1
3048              && wcscmp(config->argv.items[0], L"") == 0))
3049     {
3050         if (_PyWideStringList_Copy(&config->orig_argv, &config->argv) < 0) {
3051             return _PyStatus_NO_MEMORY();
3052         }
3053     }
3054 
3055     _PyPreCmdline precmdline = _PyPreCmdline_INIT;
3056     status = core_read_precmdline(config, &precmdline);
3057     if (_PyStatus_EXCEPTION(status)) {
3058         goto done;
3059     }
3060 
3061     assert(config->isolated >= 0);
3062     if (config->isolated) {
3063         config->safe_path = 1;
3064         config->use_environment = 0;
3065         config->user_site_directory = 0;
3066     }
3067 
3068     status = config_read_cmdline(config);
3069     if (_PyStatus_EXCEPTION(status)) {
3070         goto done;
3071     }
3072 
3073     /* Handle early PySys_AddXOption() calls */
3074     status = _PySys_ReadPreinitXOptions(config);
3075     if (_PyStatus_EXCEPTION(status)) {
3076         goto done;
3077     }
3078 
3079     status = config_read(config, compute_path_config);
3080     if (_PyStatus_EXCEPTION(status)) {
3081         goto done;
3082     }
3083 
3084     assert(config_check_consistency(config));
3085 
3086     status = _PyStatus_OK();
3087 
3088 done:
3089     _PyPreCmdline_Clear(&precmdline);
3090     return status;
3091 }
3092 
3093 
3094 PyStatus
PyConfig_Read(PyConfig * config)3095 PyConfig_Read(PyConfig *config)
3096 {
3097     return _PyConfig_Read(config, 0);
3098 }
3099 
3100 
3101 PyObject*
_Py_GetConfigsAsDict(void)3102 _Py_GetConfigsAsDict(void)
3103 {
3104     PyObject *result = NULL;
3105     PyObject *dict = NULL;
3106 
3107     result = PyDict_New();
3108     if (result == NULL) {
3109         goto error;
3110     }
3111 
3112     /* global result */
3113     dict = _Py_GetGlobalVariablesAsDict();
3114     if (dict == NULL) {
3115         goto error;
3116     }
3117     if (PyDict_SetItemString(result, "global_config", dict) < 0) {
3118         goto error;
3119     }
3120     Py_CLEAR(dict);
3121 
3122     /* pre config */
3123     PyInterpreterState *interp = _PyInterpreterState_GET();
3124     const PyPreConfig *pre_config = &interp->runtime->preconfig;
3125     dict = _PyPreConfig_AsDict(pre_config);
3126     if (dict == NULL) {
3127         goto error;
3128     }
3129     if (PyDict_SetItemString(result, "pre_config", dict) < 0) {
3130         goto error;
3131     }
3132     Py_CLEAR(dict);
3133 
3134     /* core config */
3135     const PyConfig *config = _PyInterpreterState_GetConfig(interp);
3136     dict = _PyConfig_AsDict(config);
3137     if (dict == NULL) {
3138         goto error;
3139     }
3140     if (PyDict_SetItemString(result, "config", dict) < 0) {
3141         goto error;
3142     }
3143     Py_CLEAR(dict);
3144 
3145     return result;
3146 
3147 error:
3148     Py_XDECREF(result);
3149     Py_XDECREF(dict);
3150     return NULL;
3151 }
3152 
3153 
3154 static void
init_dump_ascii_wstr(const wchar_t * str)3155 init_dump_ascii_wstr(const wchar_t *str)
3156 {
3157     if (str == NULL) {
3158         PySys_WriteStderr("(not set)");
3159         return;
3160     }
3161 
3162     PySys_WriteStderr("'");
3163     for (; *str != L'\0'; str++) {
3164         unsigned int ch = (unsigned int)*str;
3165         if (ch == L'\'') {
3166             PySys_WriteStderr("\\'");
3167         } else if (0x20 <= ch && ch < 0x7f) {
3168             PySys_WriteStderr("%c", ch);
3169         }
3170         else if (ch <= 0xff) {
3171             PySys_WriteStderr("\\x%02x", ch);
3172         }
3173 #if SIZEOF_WCHAR_T > 2
3174         else if (ch > 0xffff) {
3175             PySys_WriteStderr("\\U%08x", ch);
3176         }
3177 #endif
3178         else {
3179             PySys_WriteStderr("\\u%04x", ch);
3180         }
3181     }
3182     PySys_WriteStderr("'");
3183 }
3184 
3185 
3186 /* Dump the Python path configuration into sys.stderr */
3187 void
_Py_DumpPathConfig(PyThreadState * tstate)3188 _Py_DumpPathConfig(PyThreadState *tstate)
3189 {
3190     PyObject *exc = _PyErr_GetRaisedException(tstate);
3191 
3192     PySys_WriteStderr("Python path configuration:\n");
3193 
3194 #define DUMP_CONFIG(NAME, FIELD) \
3195         do { \
3196             PySys_WriteStderr("  " NAME " = "); \
3197             init_dump_ascii_wstr(config->FIELD); \
3198             PySys_WriteStderr("\n"); \
3199         } while (0)
3200 
3201     const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
3202     DUMP_CONFIG("PYTHONHOME", home);
3203     DUMP_CONFIG("PYTHONPATH", pythonpath_env);
3204     DUMP_CONFIG("program name", program_name);
3205     PySys_WriteStderr("  isolated = %i\n", config->isolated);
3206     PySys_WriteStderr("  environment = %i\n", config->use_environment);
3207     PySys_WriteStderr("  user site = %i\n", config->user_site_directory);
3208     PySys_WriteStderr("  safe_path = %i\n", config->safe_path);
3209     PySys_WriteStderr("  import site = %i\n", config->site_import);
3210     PySys_WriteStderr("  is in build tree = %i\n", config->_is_python_build);
3211     DUMP_CONFIG("stdlib dir", stdlib_dir);
3212     DUMP_CONFIG("sys.path[0]", sys_path_0);
3213 #undef DUMP_CONFIG
3214 
3215 #define DUMP_SYS(NAME) \
3216         do { \
3217             obj = PySys_GetObject(#NAME); \
3218             PySys_FormatStderr("  sys.%s = ", #NAME); \
3219             if (obj != NULL) { \
3220                 PySys_FormatStderr("%A", obj); \
3221             } \
3222             else { \
3223                 PySys_WriteStderr("(not set)"); \
3224             } \
3225             PySys_FormatStderr("\n"); \
3226         } while (0)
3227 
3228     PyObject *obj;
3229     DUMP_SYS(_base_executable);
3230     DUMP_SYS(base_prefix);
3231     DUMP_SYS(base_exec_prefix);
3232     DUMP_SYS(platlibdir);
3233     DUMP_SYS(executable);
3234     DUMP_SYS(prefix);
3235     DUMP_SYS(exec_prefix);
3236 #undef DUMP_SYS
3237 
3238     PyObject *sys_path = PySys_GetObject("path");  /* borrowed reference */
3239     if (sys_path != NULL && PyList_Check(sys_path)) {
3240         PySys_WriteStderr("  sys.path = [\n");
3241         Py_ssize_t len = PyList_GET_SIZE(sys_path);
3242         for (Py_ssize_t i=0; i < len; i++) {
3243             PyObject *path = PyList_GET_ITEM(sys_path, i);
3244             PySys_FormatStderr("    %A,\n", path);
3245         }
3246         PySys_WriteStderr("  ]\n");
3247     }
3248 
3249     _PyErr_SetRaisedException(tstate, exc);
3250 }
3251