changeset: 95860:3bdf1816f561 parent: 95857:47d1f9723a6f parent: 95859:f9027b10b3c4 user: Benjamin Peterson date: Sat May 02 22:37:13 2015 -0400 files: Misc/NEWS Modules/_json.c description: merge 3.4 (#24094) diff -r 47d1f9723a6f -r 3bdf1816f561 Lib/test/test_json/test_dump.py --- a/Lib/test/test_json/test_dump.py Sat May 02 22:34:31 2015 -0400 +++ b/Lib/test/test_json/test_dump.py Sat May 02 22:37:13 2015 -0400 @@ -28,6 +28,25 @@ 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 diff -r 47d1f9723a6f -r 3bdf1816f561 Misc/NEWS --- a/Misc/NEWS Sat May 02 22:34:31 2015 -0400 +++ b/Misc/NEWS Sat May 02 22:37:13 2015 -0400 @@ -25,6 +25,9 @@ Library ------- +- Issue #24094: Fix possible crash in json.encode with poorly behaved dict + subclasses. + - Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. Patch written by William Orr. diff -r 47d1f9723a6f -r 3bdf1816f561 Modules/_json.c --- a/Modules/_json.c Sat May 02 22:34:31 2015 -0400 +++ b/Modules/_json.c Sat May 02 22:37:13 2015 -0400 @@ -1663,36 +1663,11 @@ */ } - 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)