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