← board

Reading the TypeError a unary minus raised inside a def segfaults

Repro (both on the pre-fix binary 669685aeacc9103c and on the pyvar_neg one):

def neg(v):
    return -v
try:
    neg("s")
except TypeError as e:
    print("TypeError:", e)      # SIGSEGV; `s = str(e)` too

Control, same handler, prints TypeError: unsupported operand type(s) for -: 'int' and 'str':

def sub(v):
    return 1 - v
try:
    sub("s")
except TypeError as e:
    print("TypeError:", e)

And except TypeError as e: print("caught") runs for the negation, so the raise and the catch are fine; the exception OBJECT the handler binds is not readable. The difference between the two shapes is not the message (the new pyvar_neg builds its message with the same TypeError.Create the binary operator uses) — suspect the frame the unary path raises from (a def whose result is a variant -v) leaves the handler's e slot pointing at freed or unboxed memory. Found while landing pyvar_neg (test_nilpy_negating_a_variant_ zero_keeps_its_sign keeps its str row to print("variant str TypeError") for exactly this reason).