Skip to content

Commit 91e1bc1

Browse files
authored
bpo-41194: The _ast module cannot be loaded more than once (GH-21290)
Fix a crash in the _ast module: it can no longer be loaded more than once. It now uses a global state rather than a module state. * Move _ast module state: use a global state instead. * Set _astmodule.m_size to -1, so the extension cannot be loaded more than once.
1 parent 74419f0 commit 91e1bc1

File tree

3 files changed

+66
-77
lines changed

3 files changed

+66
-77
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in the ``_ast`` module: it can no longer be loaded more than once.
2+
It now uses a global state rather than a module state.

Parser/asdl_c.py

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ def visitModule(self, mod):
691691
Py_ssize_t i, numfields = 0;
692692
int res = -1;
693693
PyObject *key, *value, *fields;
694-
astmodulestate *state = astmodulestate_global;
694+
astmodulestate *state = get_global_ast_state();
695695
if (_PyObject_LookupAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) {
696696
goto cleanup;
697697
}
@@ -760,7 +760,7 @@ def visitModule(self, mod):
760760
static PyObject *
761761
ast_type_reduce(PyObject *self, PyObject *unused)
762762
{
763-
astmodulestate *state = astmodulestate_global;
763+
astmodulestate *state = get_global_ast_state();
764764
PyObject *dict;
765765
if (_PyObject_LookupAttr(self, state->__dict__, &dict) < 0) {
766766
return NULL;
@@ -971,19 +971,7 @@ def visitModule(self, mod):
971971

972972
self.emit("static int init_types(void)",0)
973973
self.emit("{", 0)
974-
self.emit("PyObject *module = PyState_FindModule(&_astmodule);", 1)
975-
self.emit("if (module == NULL) {", 1)
976-
self.emit("module = PyModule_Create(&_astmodule);", 2)
977-
self.emit("if (!module) {", 2)
978-
self.emit("return 0;", 3)
979-
self.emit("}", 2)
980-
self.emit("if (PyState_AddModule(module, &_astmodule) < 0) {", 2)
981-
self.emit("return 0;", 3)
982-
self.emit("}", 2)
983-
self.emit("}", 1)
984-
self.emit("", 0)
985-
986-
self.emit("astmodulestate *state = get_ast_state(module);", 1)
974+
self.emit("astmodulestate *state = get_global_ast_state();", 1)
987975
self.emit("if (state->initialized) return 1;", 1)
988976
self.emit("if (init_identifiers(state) < 0) return 0;", 1)
989977
self.emit("state->AST_type = PyType_FromSpec(&AST_type_spec);", 1)
@@ -1061,13 +1049,16 @@ def visitModule(self, mod):
10611049
self.emit("PyMODINIT_FUNC", 0)
10621050
self.emit("PyInit__ast(void)", 0)
10631051
self.emit("{", 0)
1064-
self.emit("PyObject *m;", 1)
1065-
self.emit("if (!init_types()) return NULL;", 1)
1066-
self.emit('m = PyState_FindModule(&_astmodule);', 1)
1067-
self.emit("if (!m) return NULL;", 1)
1052+
self.emit("PyObject *m = PyModule_Create(&_astmodule);", 1)
1053+
self.emit("if (!m) {", 1)
1054+
self.emit("return NULL;", 2)
1055+
self.emit("}", 1)
10681056
self.emit('astmodulestate *state = get_ast_state(m);', 1)
10691057
self.emit('', 1)
10701058

1059+
self.emit("if (!init_types()) {", 1)
1060+
self.emit("goto error;", 2)
1061+
self.emit("}", 1)
10711062
self.emit('if (PyModule_AddObject(m, "AST", state->AST_type) < 0) {', 1)
10721063
self.emit('goto error;', 2)
10731064
self.emit('}', 1)
@@ -1084,6 +1075,7 @@ def visitModule(self, mod):
10841075
for dfn in mod.dfns:
10851076
self.visit(dfn)
10861077
self.emit("return m;", 1)
1078+
self.emit("", 0)
10871079
self.emit("error:", 0)
10881080
self.emit("Py_DECREF(m);", 1)
10891081
self.emit("return NULL;", 1)
@@ -1263,9 +1255,11 @@ class PartingShots(StaticVisitor):
12631255
CODE = """
12641256
PyObject* PyAST_mod2obj(mod_ty t)
12651257
{
1266-
if (!init_types())
1258+
if (!init_types()) {
12671259
return NULL;
1268-
astmodulestate *state = astmodulestate_global;
1260+
}
1261+
1262+
astmodulestate *state = get_global_ast_state();
12691263
return ast2obj_mod(state, t);
12701264
}
12711265
@@ -1279,16 +1273,17 @@ class PartingShots(StaticVisitor):
12791273
return NULL;
12801274
}
12811275
1282-
astmodulestate *state = astmodulestate_global;
1276+
astmodulestate *state = get_global_ast_state();
12831277
PyObject *req_type[3];
12841278
req_type[0] = state->Module_type;
12851279
req_type[1] = state->Expression_type;
12861280
req_type[2] = state->Interactive_type;
12871281
12881282
assert(0 <= mode && mode <= 2);
12891283
1290-
if (!init_types())
1284+
if (!init_types()) {
12911285
return NULL;
1286+
}
12921287
12931288
isinstance = PyObject_IsInstance(ast, req_type[mode]);
12941289
if (isinstance == -1)
@@ -1308,9 +1303,11 @@ class PartingShots(StaticVisitor):
13081303
13091304
int PyAST_Check(PyObject* obj)
13101305
{
1311-
if (!init_types())
1306+
if (!init_types()) {
13121307
return -1;
1313-
astmodulestate *state = astmodulestate_global;
1308+
}
1309+
1310+
astmodulestate *state = get_global_ast_state();
13141311
return PyObject_IsInstance(obj, state->AST_type);
13151312
}
13161313
"""
@@ -1361,13 +1358,12 @@ def generate_module_def(f, mod):
13611358
f.write(' PyObject *' + s + ';\n')
13621359
f.write('} astmodulestate;\n\n')
13631360
f.write("""
1361+
static astmodulestate global_ast_state;
1362+
13641363
static astmodulestate *
1365-
get_ast_state(PyObject *module)
1364+
get_ast_state(PyObject *Py_UNUSED(module))
13661365
{
1367-
assert(module != NULL);
1368-
void *state = PyModule_GetState(module);
1369-
assert(state != NULL);
1370-
return (astmodulestate *)state;
1366+
return &global_ast_state;
13711367
}
13721368
13731369
static int astmodule_clear(PyObject *module)
@@ -1396,17 +1392,14 @@ def generate_module_def(f, mod):
13961392
13971393
static struct PyModuleDef _astmodule = {
13981394
PyModuleDef_HEAD_INIT,
1399-
"_ast",
1400-
NULL,
1401-
sizeof(astmodulestate),
1402-
NULL,
1403-
NULL,
1404-
astmodule_traverse,
1405-
astmodule_clear,
1406-
astmodule_free,
1395+
.m_name = "_ast",
1396+
.m_size = -1,
1397+
.m_traverse = astmodule_traverse,
1398+
.m_clear = astmodule_clear,
1399+
.m_free = astmodule_free,
14071400
};
14081401
1409-
#define astmodulestate_global get_ast_state(PyState_FindModule(&_astmodule))
1402+
#define get_global_ast_state() (&global_ast_state)
14101403
14111404
""")
14121405
f.write('static int init_identifiers(astmodulestate *state)\n')

Python/Python-ast.c

Lines changed: 32 additions & 38 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)