Skip to content

Error handling of RERAISE is strange #122759

@sobolevn

Description

@sobolevn

Bug report

There's a strange pattern used in RERAISE opcode:

cpython/Python/bytecodes.c

Lines 1174 to 1189 in 4767a6e

tier1 inst(RERAISE, (values[oparg], exc_st -- values[oparg])) {
PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st);
assert(oparg >= 0 && oparg <= 2);
if (oparg) {
PyObject *lasti = PyStackRef_AsPyObjectBorrow(values[0]);
if (PyLong_Check(lasti)) {
frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti);
assert(!_PyErr_Occurred(tstate));
}
else {
assert(PyLong_Check(lasti));
_PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int");
ERROR_NO_POP();
}
}

Especially these lines:

cpython/Python/bytecodes.c

Lines 1180 to 1187 in 4767a6e

if (PyLong_Check(lasti)) {
frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti);
assert(!_PyErr_Occurred(tstate));
}
else {
assert(PyLong_Check(lasti));
_PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int");
ERROR_NO_POP();

It looks like the assert call is not needed here:

  • In debug builds it will always crash, since PyLong_Check(lasti) will always be false
  • In non-debug builds it will set SystemError as it should be (at least, I think so). That's the only line that matches r'assert\(.*\);\n\s+_PyErr'

I have a PR ready.

Linked PRs

Metadata

Metadata

Assignees

Labels

interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions