Skip to content

PyDict_DelItem() can crash in some circumstances #146480

@serhiy-storchaka

Description

@serhiy-storchaka

Crash report

When playing with #146173 (just disabling fast_save_leave() in save_frozenset()), I got the following error and crash:

...
KeyError: 140737086303568
when serializing dict item 'key'

The above exception was the direct cause of the following exception:

SystemError: <class 'KeyError'> returned a result with an exception set
...

The extraction from stacktrace:

...
#7  0x0000555555881414 in _Py_FatalErrorFunc (func=func@entry=0x5555559b00c0 <__func__.29> "_Py_CheckFunctionResult", msg=msg@entry=0x555555971500 "a function returned a result with an exception set") at Python/pylifecycle.c:3635
#8  0x0000555555690030 in _Py_CheckFunctionResult (tstate=tstate@entry=0x555555c32210 <_PyRuntime+360720>, callable=callable@entry=0x555555b9dc80 <_PyExc_KeyError>, result=0x7fffe7fb26d0, where=where@entry=0x0) at Objects/call.c:65
#9  0x00005555556904a5 in _PyObject_VectorcallTstate (tstate=0x555555c32210 <_PyRuntime+360720>, callable=0x555555b9dc80 <_PyExc_KeyError>, args=args@entry=0x7fffffffae18, nargsf=nargsf@entry=9223372036854775809, 
    kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:145
#10 0x00005555556905be in PyObject_CallOneArg (func=<optimized out>, arg=arg@entry=0x7fffe80d6300) at Objects/call.c:395
#11 0x000055555582fdbf in _PyErr_SetKeyError (arg=arg@entry=0x7fffe80d6300) at Python/errors.c:256
#12 0x00005555556df6ad in _PyDict_DelItem_KnownHash_LockHeld (op=op@entry=0x7fffe80d2750, key=key@entry=0x7fffe80d6300, hash=140737086563984) at Objects/dictobject.c:2942
#13 0x00005555556df6d3 in _PyDict_DelItem_KnownHash (op=op@entry=0x7fffe80d2750, key=key@entry=0x7fffe80d6300, hash=<optimized out>) at Objects/dictobject.c:2956
#14 0x00005555556df707 in PyDict_DelItem (op=0x7fffe80d2750, key=key@entry=0x7fffe80d6300) at Objects/dictobject.c:2915
...

It seems that PyDict_DelItem() was called when an error was set and failed to delete a key. It called _PyErr_SetKeyError() to set a KeyError and this crashed during calling KeyError.

There is something wrong either with PyDict_DelItem() or with PyObject_CallOneArg(). If PyDict_DelItem() supposed to never be called when an error is set, we may have many ticking bombs in cleanup code.

cc @vstinner

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions