]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-135608: Add a null check for attribute promotion to fix a JIT crash (GH-135613)
authorKen Jin <kenjin@python.org>
Fri, 20 Jun 2025 06:33:35 +0000 (14:33 +0800)
committerGitHub <noreply@github.com>
Fri, 20 Jun 2025 06:33:35 +0000 (14:33 +0800)
Co-authored-by: devdanzin <74280297+devdanzin@users.noreply.github.com>
Lib/test/test_capi/test_opt.py
Misc/NEWS.d/next/Core_and_Builtins/2025-06-17-12-50-48.gh-issue-135608.PnHckD.rst [new file with mode: 0644]
Python/optimizer_analysis.c
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h

index 0fea0649d75709938c94562391c7e002ce5aecef..2b6934d747ebe0cb637abe74adf81a7b0cc324c1 100644 (file)
@@ -2319,6 +2319,36 @@ class TestUopsOptimization(unittest.TestCase):
         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 (file)
index 0000000..a65a0c8
--- /dev/null
@@ -0,0 +1 @@
+Fix a crash in the JIT involving attributes of modules.
index 03ad8e1db246354bef33b4fb35a6cf44ad0d7257..8b1a63e3d2916ffa324c2e8d3f524e0ebc34db0a 100644 (file)
@@ -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;
index f01c3787e5b4c7abf6022340c02ffc8a41952701..2e240830013a466e3045c425d9fae54c40989ba3 100644 (file)
@@ -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);
+                    }
+
                 }
             }
         }
index 6bc506c6298f56a515b6390b676e787da5d8af9f..3cabf619fe81e7600ea4fcd0f6ff0983ac1bc582 100644 (file)
                         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);
+                        }
                     }
                 }
             }