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