Skip to content

Commit 60fc42c

Browse files
[3.14] gh-135608: Add a null check for attribute promotion to fix a JIT crash (GH-135613) (#135739)
gh-135608: Add a null check for attribute promotion to fix a JIT crash (GH-135613) Co-authored-by: devdanzin <74280297+devdanzin@users.noreply.github.com>
1 parent 203753b commit 60fc42c

File tree

5 files changed

+48
-2
lines changed

5 files changed

+48
-2
lines changed

Lib/test/test_capi/test_opt.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,36 @@ def testfunc(n):
19421942
self.assertNotIn("_COMPARE_OP_INT", uops)
19431943
self.assertNotIn("_GUARD_IS_TRUE_POP", uops)
19441944

1945+
def test_attr_promotion_failure(self):
1946+
# We're not testing for any specific uops here, just
1947+
# testing it doesn't crash.
1948+
script_helper.assert_python_ok('-c', textwrap.dedent("""
1949+
import _testinternalcapi
1950+
import _opcode
1951+
import email
1952+
1953+
def get_first_executor(func):
1954+
code = func.__code__
1955+
co_code = code.co_code
1956+
for i in range(0, len(co_code), 2):
1957+
try:
1958+
return _opcode.get_executor(code, i)
1959+
except ValueError:
1960+
pass
1961+
return None
1962+
1963+
def testfunc(n):
1964+
for _ in range(n):
1965+
email.jit_testing = None
1966+
prompt = email.jit_testing
1967+
del email.jit_testing
1968+
1969+
1970+
testfunc(_testinternalcapi.TIER2_THRESHOLD)
1971+
ex = get_first_executor(testfunc)
1972+
assert ex is not None
1973+
"""))
1974+
19451975

19461976
def global_identity(x):
19471977
return x
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a crash in the JIT involving attributes of modules.

Python/optimizer_analysis.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj, bool pop)
103103
if ((int)index >= dict->ma_keys->dk_nentries) {
104104
return NULL;
105105
}
106+
PyDictKeysObject *keys = dict->ma_keys;
107+
if (keys->dk_version != inst->operand0) {
108+
return NULL;
109+
}
106110
PyObject *res = entries[index].me_value;
107111
if (res == NULL) {
108112
return NULL;

Python/optimizer_bytecodes.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,13 @@ dummy_func(void) {
580580
PyDict_Watch(GLOBALS_WATCHER_ID, dict);
581581
_Py_BloomFilter_Add(dependencies, dict);
582582
PyObject *res = convert_global_to_const(this_instr, dict, true);
583-
attr = sym_new_const(ctx, res);
583+
if (res == NULL) {
584+
attr = sym_new_not_null(ctx);
585+
}
586+
else {
587+
attr = sym_new_const(ctx, res);
588+
}
589+
584590
}
585591
}
586592
}

Python/optimizer_cases.c.h

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)