+import dis
import math
import os
import unittest
self.check_constant(f1, frozenset({0}))
self.assertTrue(f1(0))
+ # This is a regression test for a CPython specific peephole optimizer
+ # implementation bug present in a few releases. It's assertion verifies
+ # that peephole optimization was actually done though that isn't an
+ # indication of the bugs presence or not (crashing is).
+ @support.cpython_only
+ def test_peephole_opt_unreachable_code_array_access_in_bounds(self):
+ """Regression test for issue35193 when run under clang msan."""
+ def unused_code_at_end():
+ return 3
+ raise RuntimeError("unreachable")
+ # The above function definition will trigger the out of bounds
+ # bug in the peephole optimizer as it scans opcodes past the
+ # RETURN_VALUE opcode. This does not always crash an interpreter.
+ # When you build with the clang memory sanitizer it reliably aborts.
+ self.assertEqual(
+ 'RETURN_VALUE',
+ list(dis.get_instructions(unused_code_at_end))[-1].opname)
+
def test_dont_merge_constants(self):
# Issue #25843: compile() must not merge constants which are equal
# but have a different type.
/* Scans through EXTENDED ARGs, seeking the index of the effective opcode */
static Py_ssize_t
-find_op(const _Py_CODEUNIT *codestr, Py_ssize_t i)
+find_op(const _Py_CODEUNIT *codestr, Py_ssize_t codelen, Py_ssize_t i)
{
- while (_Py_OPCODE(codestr[i]) == EXTENDED_ARG) {
+ while (i < codelen && _Py_OPCODE(codestr[i]) == EXTENDED_ARG) {
i++;
}
return i;
CONST_STACK_CREATE();
- for (i=find_op(codestr, 0) ; i<codelen ; i=nexti) {
+ for (i=find_op(codestr, codelen, 0) ; i<codelen ; i=nexti) {
opcode = _Py_OPCODE(codestr[i]);
op_start = i;
while (op_start >= 1 && _Py_OPCODE(codestr[op_start-1]) == EXTENDED_ARG) {
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
h = get_arg(codestr, i) / sizeof(_Py_CODEUNIT);
- tgt = find_op(codestr, h);
+ tgt = find_op(codestr, codelen, h);
j = _Py_OPCODE(codestr[tgt]);
if (CONDITIONAL_JUMP(j)) {
case SETUP_WITH:
case SETUP_ASYNC_WITH:
h = GETJUMPTGT(codestr, i);
- tgt = find_op(codestr, h);
+ tgt = find_op(codestr, codelen, h);
/* Replace JUMP_* to a RETURN into just a RETURN */
if (UNCONDITIONAL_JUMP(opcode) &&
_Py_OPCODE(codestr[tgt]) == RETURN_VALUE) {
}
if (h > i + 1) {
fill_nops(codestr, i + 1, h);
- nexti = find_op(codestr, h);
+ nexti = find_op(codestr, codelen, h);
}
break;
}