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