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