https://github.com/python/cpython/commit/b53b0c14da58b73955b8989e4a9ce19ea67db7a3
commit: b53b0c14da58b73955b8989e4a9ce19ea67db7a3
branch: main
author: Ken Jin <ken...@python.org>
committer: Fidget-Spinner <kenjin4...@gmail.com>
date: 2025-06-20T14:33:35+08:00
summary:

gh-135608: Add a null check for attribute promotion to fix a JIT crash 
(GH-135613)

Co-authored-by: devdanzin <74280297+devdan...@users.noreply.github.com>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-06-17-12-50-48.gh-issue-135608.PnHckD.rst
M Lib/test/test_capi/test_opt.py
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 0fea0649d75709..2b6934d747ebe0 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -2319,6 +2319,36 @@ def testfunc(n):
         self.assertNotIn("_GUARD_TOS_INT", uops)
         self.assertNotIn("_GUARD_NOS_INT", uops)
 
+    def test_attr_promotion_failure(self):
+        # We're not testing for any specific uops here, just
+        # testing it doesn't crash.
+        script_helper.assert_python_ok('-c', textwrap.dedent("""
+        import _testinternalcapi
+        import _opcode
+        import email
+
+        def get_first_executor(func):
+            code = func.__code__
+            co_code = code.co_code
+            for i in range(0, len(co_code), 2):
+                try:
+                    return _opcode.get_executor(code, i)
+                except ValueError:
+                    pass
+            return None
+
+        def testfunc(n):
+            for _ in range(n):
+                email.jit_testing = None
+                prompt = email.jit_testing
+                del email.jit_testing
+
+
+        testfunc(_testinternalcapi.TIER2_THRESHOLD)
+        ex = get_first_executor(testfunc)
+        assert ex is not None
+        """))
+
 
 def global_identity(x):
     return x
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-17-12-50-48.gh-issue-135608.PnHckD.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-17-12-50-48.gh-issue-135608.PnHckD.rst
new file mode 100644
index 00000000000000..a65a0c85fa64fa
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-17-12-50-48.gh-issue-135608.PnHckD.rst
@@ -0,0 +1 @@
+Fix a crash in the JIT involving attributes of modules.
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 03ad8e1db24635..8b1a63e3d2916f 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -103,6 +103,10 @@ convert_global_to_const(_PyUOpInstruction *inst, PyObject 
*obj, bool pop)
     if ((int)index >= dict->ma_keys->dk_nentries) {
         return NULL;
     }
+    PyDictKeysObject *keys = dict->ma_keys;
+    if (keys->dk_version != inst->operand0) {
+        return NULL;
+    }
     PyObject *res = entries[index].me_value;
     if (res == NULL) {
         return NULL;
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index f01c3787e5b4c7..2e240830013a46 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -591,7 +591,13 @@ dummy_func(void) {
                     PyDict_Watch(GLOBALS_WATCHER_ID, dict);
                     _Py_BloomFilter_Add(dependencies, dict);
                     PyObject *res = convert_global_to_const(this_instr, dict, 
true);
-                    attr = sym_new_const(ctx, res);
+                    if (res == NULL) {
+                        attr = sym_new_not_null(ctx);
+                    }
+                    else {
+                        attr = sym_new_const(ctx, res);
+                    }
+
                 }
             }
         }
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 6bc506c6298f56..3cabf619fe81e7 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1266,7 +1266,12 @@
                         PyDict_Watch(GLOBALS_WATCHER_ID, dict);
                         _Py_BloomFilter_Add(dependencies, dict);
                         PyObject *res = convert_global_to_const(this_instr, 
dict, true);
-                        attr = sym_new_const(ctx, res);
+                        if (res == NULL) {
+                            attr = sym_new_not_null(ctx);
+                        }
+                        else {
+                            attr = sym_new_const(ctx, res);
+                        }
                     }
                 }
             }

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to