This commit is contained in:
Benjamin Peterson 2015-05-02 22:36:26 -04:00
commit 122f4b1bda
3 changed files with 25 additions and 28 deletions

View file

@ -28,6 +28,25 @@ def crasher(obj):
self.assertEqual(self.dumps(a, default=crasher),
'[null, null, null, null, null]')
# Issue 24094
def test_encode_evil_dict(self):
class D(dict):
def keys(self):
return L
class X:
def __hash__(self):
del L[0]
return 1337
def __lt__(self, o):
return 0
L = [X() for i in range(1122)]
d = D()
d[1337] = "true.dat"
self.assertEqual(self.dumps(d, sort_keys=True), '{"1337": "true.dat"}')
class TestPyDump(TestDump, PyTest): pass

View file

@ -39,6 +39,9 @@ Core and Builtins
Library
-------
- Issue #24094: Fix possible crash in json.encode with poorly behaved dict
subclasses.
- Asyncio issue 222 / PR 231 (Victor Stinner) -- fix @coroutine
functions without __name__.

View file

@ -1541,36 +1541,11 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
*/
}
if (PyObject_IsTrue(s->sort_keys)) {
/* First sort the keys then replace them with (key, value) tuples. */
Py_ssize_t i, nitems;
items = PyMapping_Keys(dct);
if (items == NULL)
goto bail;
if (!PyList_Check(items)) {
PyErr_SetString(PyExc_ValueError, "keys must return list");
goto bail;
}
if (PyList_Sort(items) < 0)
goto bail;
nitems = PyList_GET_SIZE(items);
for (i = 0; i < nitems; i++) {
PyObject *key, *value;
key = PyList_GET_ITEM(items, i);
value = PyDict_GetItem(dct, key);
item = PyTuple_Pack(2, key, value);
if (item == NULL)
goto bail;
PyList_SET_ITEM(items, i, item);
item = NULL;
Py_DECREF(key);
}
}
else {
items = PyMapping_Items(dct);
}
items = PyMapping_Items(dct);
if (items == NULL)
goto bail;
if (PyObject_IsTrue(s->sort_keys) && PyList_Sort(items) < 0)
goto bail;
it = PyObject_GetIter(items);
Py_DECREF(items);
if (it == NULL)