]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] GH-109052: Use the base opcode when comparing code objects (GH-112329)
authorTian Gao <gaogaotiantian@hotmail.com>
Thu, 23 Nov 2023 18:18:17 +0000 (10:18 -0800)
committerGitHub <noreply@github.com>
Thu, 23 Nov 2023 18:18:17 +0000 (10:18 -0800)
Lib/test/test_code.py
Misc/NEWS.d/next/Core and Builtins/2023-09-07-18-49-01.gh-issue-109052.TBU4nC.rst [new file with mode: 0644]
Objects/codeobject.c

index ca06a39f5df142f44caa63321e157d9a94318f71..de91acfa3549733131a53d936a13bb62586a9180 100644 (file)
@@ -498,6 +498,25 @@ class CodeTest(unittest.TestCase):
         self.assertNotEqual(c, c1)
         self.assertNotEqual(hash(c), hash(c1))
 
+    @cpython_only
+    def test_code_equal_with_instrumentation(self):
+        """ GH-109052
+
+        Make sure the instrumentation doesn't affect the code equality
+        The validity of this test relies on the fact that "x is x" and
+        "x in x" have only one different instruction and the instructions
+        have the same argument.
+
+        """
+        code1 = compile("x is x", "example.py", "eval")
+        code2 = compile("x in x", "example.py", "eval")
+        sys._getframe().f_trace_opcodes = True
+        sys.settrace(lambda *args: None)
+        exec(code1, {'x': []})
+        exec(code2, {'x': []})
+        self.assertNotEqual(code1, code2)
+        sys.settrace(None)
+
 
 def isinterned(s):
     return s is sys.intern(('_' + s + '_')[1:-1])
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-09-07-18-49-01.gh-issue-109052.TBU4nC.rst b/Misc/NEWS.d/next/Core and Builtins/2023-09-07-18-49-01.gh-issue-109052.TBU4nC.rst
new file mode 100644 (file)
index 0000000..175046c
--- /dev/null
@@ -0,0 +1 @@
+Use the base opcode when comparing code objects to avoid interference from instrumentation
index cda2d2f544ef60e17500861bc9704181bb3c8388..1be662156388fd8d8c4cbc9caf6870c3c2b9e39b 100644 (file)
@@ -1800,8 +1800,8 @@ code_richcompare(PyObject *self, PyObject *other, int op)
     for (int i = 0; i < Py_SIZE(co); i++) {
         _Py_CODEUNIT co_instr = _PyCode_CODE(co)[i];
         _Py_CODEUNIT cp_instr = _PyCode_CODE(cp)[i];
-        co_instr.op.code = _PyOpcode_Deopt[co_instr.op.code];
-        cp_instr.op.code = _PyOpcode_Deopt[cp_instr.op.code];
+        co_instr.op.code = _Py_GetBaseOpcode(co, i);
+        cp_instr.op.code = _Py_GetBaseOpcode(cp, i);
         eq = co_instr.cache == cp_instr.cache;
         if (!eq) {
             goto unequal;