mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
[3.12] gh-109118: Fix runtime crash when NameError happens in PEP 695 function (GH-109123) (#109173)
* gh-109118: Fix runtime crash when NameError happens in PEP 695 function (#109123) (cherry picked from commit17f994174d
) * [3.12] gh-109118: Fix runtime crash when NameError happens in PEP 695 function (GH-109123). (cherry picked from commit17f994174d
) Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
parent
c76f4b97dc
commit
acde502e8a
5 changed files with 522 additions and 451 deletions
|
@ -956,3 +956,43 @@ class TypeParamsWeakRefTest(unittest.TestCase):
|
||||||
for case in cases:
|
for case in cases:
|
||||||
with self.subTest(case=case):
|
with self.subTest(case=case):
|
||||||
weakref.ref(case)
|
weakref.ref(case)
|
||||||
|
|
||||||
|
|
||||||
|
class TypeParamsRuntimeTest(unittest.TestCase):
|
||||||
|
def test_name_error(self):
|
||||||
|
# gh-109118: This crashed the interpreter due to a refcounting bug
|
||||||
|
code = """
|
||||||
|
class name_2[name_5]:
|
||||||
|
class name_4[name_5](name_0):
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
with self.assertRaises(NameError):
|
||||||
|
run_code(code)
|
||||||
|
|
||||||
|
# Crashed with a slightly different stack trace
|
||||||
|
code = """
|
||||||
|
class name_2[name_5]:
|
||||||
|
class name_4[name_5: name_5](name_0):
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
with self.assertRaises(NameError):
|
||||||
|
run_code(code)
|
||||||
|
|
||||||
|
def test_broken_class_namespace(self):
|
||||||
|
code = """
|
||||||
|
class WeirdMapping(dict):
|
||||||
|
def __missing__(self, key):
|
||||||
|
if key == "T":
|
||||||
|
raise RuntimeError
|
||||||
|
raise KeyError(key)
|
||||||
|
|
||||||
|
class Meta(type):
|
||||||
|
def __prepare__(name, bases):
|
||||||
|
return WeirdMapping()
|
||||||
|
|
||||||
|
class MyClass[V](metaclass=Meta):
|
||||||
|
class Inner[U](T):
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
run_code(code)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix interpreter crash when a NameError is raised inside the type parameters
|
||||||
|
of a generic class.
|
|
@ -1165,7 +1165,7 @@ dummy_func(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_LOAD_LOCALS, ( -- locals)) {
|
inst(LOAD_LOCALS, ( -- locals)) {
|
||||||
locals = LOCALS();
|
locals = LOCALS();
|
||||||
if (locals == NULL) {
|
if (locals == NULL) {
|
||||||
_PyErr_SetString(tstate, PyExc_SystemError,
|
_PyErr_SetString(tstate, PyExc_SystemError,
|
||||||
|
@ -1175,9 +1175,70 @@ dummy_func(
|
||||||
Py_INCREF(locals);
|
Py_INCREF(locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro(LOAD_LOCALS) = _LOAD_LOCALS;
|
inst(LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) {
|
||||||
|
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
|
||||||
op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) {
|
if (PyDict_CheckExact(mod_or_class_dict)) {
|
||||||
|
v = PyDict_GetItemWithError(mod_or_class_dict, name);
|
||||||
|
if (v != NULL) {
|
||||||
|
Py_INCREF(v);
|
||||||
|
}
|
||||||
|
else if (_PyErr_Occurred(tstate)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v = PyObject_GetItem(mod_or_class_dict, name);
|
||||||
|
if (v == NULL) {
|
||||||
|
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
_PyErr_Clear(tstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (v == NULL) {
|
||||||
|
v = PyDict_GetItemWithError(GLOBALS(), name);
|
||||||
|
if (v != NULL) {
|
||||||
|
Py_INCREF(v);
|
||||||
|
}
|
||||||
|
else if (_PyErr_Occurred(tstate)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (PyDict_CheckExact(BUILTINS())) {
|
||||||
|
v = PyDict_GetItemWithError(BUILTINS(), name);
|
||||||
|
if (v == NULL) {
|
||||||
|
if (!_PyErr_Occurred(tstate)) {
|
||||||
|
format_exc_check_arg(
|
||||||
|
tstate, PyExc_NameError,
|
||||||
|
NAME_ERROR_MSG, name);
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
Py_INCREF(v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v = PyObject_GetItem(BUILTINS(), name);
|
||||||
|
if (v == NULL) {
|
||||||
|
if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
|
||||||
|
format_exc_check_arg(
|
||||||
|
tstate, PyExc_NameError,
|
||||||
|
NAME_ERROR_MSG, name);
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DECREF_INPUTS();
|
||||||
|
}
|
||||||
|
|
||||||
|
inst(LOAD_NAME, (-- v)) {
|
||||||
|
PyObject *mod_or_class_dict = LOCALS();
|
||||||
|
if (mod_or_class_dict == NULL) {
|
||||||
|
_PyErr_SetString(tstate, PyExc_SystemError,
|
||||||
|
"no locals found");
|
||||||
|
ERROR_IF(true, error);
|
||||||
|
}
|
||||||
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
|
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
|
||||||
if (PyDict_CheckExact(mod_or_class_dict)) {
|
if (PyDict_CheckExact(mod_or_class_dict)) {
|
||||||
v = PyDict_GetItemWithError(mod_or_class_dict, name);
|
v = PyDict_GetItemWithError(mod_or_class_dict, name);
|
||||||
|
@ -1185,7 +1246,6 @@ dummy_func(
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
}
|
}
|
||||||
else if (_PyErr_Occurred(tstate)) {
|
else if (_PyErr_Occurred(tstate)) {
|
||||||
Py_DECREF(mod_or_class_dict);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1193,13 +1253,11 @@ dummy_func(
|
||||||
v = PyObject_GetItem(mod_or_class_dict, name);
|
v = PyObject_GetItem(mod_or_class_dict, name);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
|
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
|
||||||
Py_DECREF(mod_or_class_dict);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
_PyErr_Clear(tstate);
|
_PyErr_Clear(tstate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Py_DECREF(mod_or_class_dict);
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
v = PyDict_GetItemWithError(GLOBALS(), name);
|
v = PyDict_GetItemWithError(GLOBALS(), name);
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
|
@ -1236,10 +1294,6 @@ dummy_func(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro(LOAD_NAME) = _LOAD_LOCALS + _LOAD_FROM_DICT_OR_GLOBALS;
|
|
||||||
|
|
||||||
macro(LOAD_FROM_DICT_OR_GLOBALS) = _LOAD_FROM_DICT_OR_GLOBALS;
|
|
||||||
|
|
||||||
family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
|
family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
|
||||||
LOAD_GLOBAL,
|
LOAD_GLOBAL,
|
||||||
LOAD_GLOBAL_MODULE,
|
LOAD_GLOBAL_MODULE,
|
||||||
|
|
843
Python/generated_cases.c.h
generated
843
Python/generated_cases.c.h
generated
File diff suppressed because it is too large
Load diff
|
@ -163,10 +163,10 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||||
return 0;
|
return 0;
|
||||||
case LOAD_LOCALS:
|
case LOAD_LOCALS:
|
||||||
return 0;
|
return 0;
|
||||||
case LOAD_NAME:
|
|
||||||
return 0+1;
|
|
||||||
case LOAD_FROM_DICT_OR_GLOBALS:
|
case LOAD_FROM_DICT_OR_GLOBALS:
|
||||||
return 1;
|
return 1;
|
||||||
|
case LOAD_NAME:
|
||||||
|
return 0;
|
||||||
case LOAD_GLOBAL:
|
case LOAD_GLOBAL:
|
||||||
return 0;
|
return 0;
|
||||||
case LOAD_GLOBAL_MODULE:
|
case LOAD_GLOBAL_MODULE:
|
||||||
|
@ -559,10 +559,10 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
||||||
return 0;
|
return 0;
|
||||||
case LOAD_LOCALS:
|
case LOAD_LOCALS:
|
||||||
return 1;
|
return 1;
|
||||||
case LOAD_NAME:
|
|
||||||
return 1+1;
|
|
||||||
case LOAD_FROM_DICT_OR_GLOBALS:
|
case LOAD_FROM_DICT_OR_GLOBALS:
|
||||||
return 1;
|
return 1;
|
||||||
|
case LOAD_NAME:
|
||||||
|
return 1;
|
||||||
case LOAD_GLOBAL:
|
case LOAD_GLOBAL:
|
||||||
return ((oparg & 1) ? 1 : 0) + 1;
|
return ((oparg & 1) ? 1 : 0) + 1;
|
||||||
case LOAD_GLOBAL_MODULE:
|
case LOAD_GLOBAL_MODULE:
|
||||||
|
@ -881,9 +881,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
|
||||||
[DELETE_ATTR] = { true, INSTR_FMT_IB },
|
[DELETE_ATTR] = { true, INSTR_FMT_IB },
|
||||||
[STORE_GLOBAL] = { true, INSTR_FMT_IB },
|
[STORE_GLOBAL] = { true, INSTR_FMT_IB },
|
||||||
[DELETE_GLOBAL] = { true, INSTR_FMT_IB },
|
[DELETE_GLOBAL] = { true, INSTR_FMT_IB },
|
||||||
[LOAD_LOCALS] = { true, INSTR_FMT_IB },
|
[LOAD_LOCALS] = { true, INSTR_FMT_IX },
|
||||||
[LOAD_NAME] = { true, INSTR_FMT_IB },
|
|
||||||
[LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB },
|
[LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB },
|
||||||
|
[LOAD_NAME] = { true, INSTR_FMT_IB },
|
||||||
[LOAD_GLOBAL] = { true, INSTR_FMT_IBC000 },
|
[LOAD_GLOBAL] = { true, INSTR_FMT_IBC000 },
|
||||||
[LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000 },
|
[LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000 },
|
||||||
[LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000 },
|
[LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000 },
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue