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