bpo-35239: _PySys_EndInit() copies module_search_path (GH-10532)


* The _PySys_EndInit() function now copies the
  config->module_search_path list, so config is longer modified when
  sys.path is updated.
* config->warnoptions list and config->xoptions dict are also copied
* test_embed: InitConfigTests now also tests
  main_config['module_search_path']
* Fix _Py_InitializeMainInterpreter(): don't use config->warnoptions
   but sys.warnoptions to decide if the warnings module should
   be imported at startup.
(cherry picked from commit 37cd982df02795905886ab36a2378ed557cb6f60)

Co-authored-by: Victor Stinner <vstinner@redhat.com>
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 498fa91..48d8fa4 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -2464,7 +2464,20 @@
     assert(config->exec_prefix != NULL);
     assert(config->base_exec_prefix != NULL);
 
-    SET_SYS_FROM_STRING_BORROW("path", config->module_search_path);
+#define COPY_LIST(KEY, ATTR) \
+    do { \
+        assert(PyList_Check(config->ATTR)); \
+        PyObject *list = PyList_GetSlice(config->ATTR, \
+                                         0, PyList_GET_SIZE(config->ATTR)); \
+        if (list == NULL) { \
+            return -1; \
+        } \
+        SET_SYS_FROM_STRING_BORROW(KEY, list); \
+        Py_DECREF(list); \
+    } while (0)
+
+    COPY_LIST("path", module_search_path);
+
     SET_SYS_FROM_STRING_BORROW("executable", config->executable);
     SET_SYS_FROM_STRING_BORROW("prefix", config->prefix);
     SET_SYS_FROM_STRING_BORROW("base_prefix", config->base_prefix);
@@ -2475,12 +2488,19 @@
         SET_SYS_FROM_STRING_BORROW("argv", config->argv);
     }
     if (config->warnoptions != NULL) {
-        SET_SYS_FROM_STRING_BORROW("warnoptions", config->warnoptions);
+        COPY_LIST("warnoptions", warnoptions);
     }
     if (config->xoptions != NULL) {
-        SET_SYS_FROM_STRING_BORROW("_xoptions", config->xoptions);
+        PyObject *dict = PyDict_Copy(config->xoptions);
+        if (dict == NULL) {
+            return -1;
+        }
+        SET_SYS_FROM_STRING_BORROW("_xoptions", dict);
+        Py_DECREF(dict);
     }
 
+#undef COPY_LIST
+
     /* Set flags to their final values */
     SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags());
     /* prevent user from creating new instances */