From 0c3bfbd39182208e3eda96d528f5c3057c0de7e8 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Wed, 22 Nov 2023 21:36:40 -0800 Subject: [PATCH] [3.12] gh-109052: Use the base opcode when comparing code objects (gh-109107) --- Lib/test/test_code.py | 19 +++++++++++++++++++ ...-09-07-18-49-01.gh-issue-109052.TBU4nC.rst | 1 + Objects/codeobject.c | 4 ++-- 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-09-07-18-49-01.gh-issue-109052.TBU4nC.rst diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index ca06a39f5df142..de91acfa354973 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -498,6 +498,25 @@ def test_code_hash_uses_bytecode(self): 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 index 00000000000000..175046c771cdf3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-09-07-18-49-01.gh-issue-109052.TBU4nC.rst @@ -0,0 +1 @@ +Use the base opcode when comparing code objects to avoid interference from instrumentation diff --git a/Objects/codeobject.c b/Objects/codeobject.c index cda2d2f544ef60..1be662156388fd 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -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;