]> granicus.if.org Git - python/commitdiff
bpo-31505: Fix an assertion failure in json, in case _json.make_encoder() received...
authorOren Milman <orenmn@gmail.com>
Sun, 24 Sep 2017 09:07:12 +0000 (12:07 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Sun, 24 Sep 2017 09:07:12 +0000 (12:07 +0300)
Lib/test/test_json/test_speedups.py
Misc/NEWS.d/next/Core and Builtins/2017-09-18-12-07-39.bpo-31505.VomaFa.rst [new file with mode: 0644]
Modules/_json.c

index 56f1882001d666807998f3ebb973b40b8fb3b5ca..5dad69208704218b14539771e29aaff3a3a071e6 100644 (file)
@@ -36,6 +36,27 @@ class TestEncode(CTest):
             b"\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75",
             None)
 
+    def test_bad_str_encoder(self):
+        # Issue #31505: There shouldn't be an assertion failure in case
+        # c_make_encoder() receives a bad encoder() argument.
+        def bad_encoder1(*args):
+            return None
+        enc = self.json.encoder.c_make_encoder(None, lambda obj: str(obj),
+                                               bad_encoder1, None, ': ', ', ',
+                                               False, False, False)
+        with self.assertRaises(TypeError):
+            enc('spam', 4)
+        with self.assertRaises(TypeError):
+            enc({'spam': 42}, 4)
+
+        def bad_encoder2(*args):
+            1/0
+        enc = self.json.encoder.c_make_encoder(None, lambda obj: str(obj),
+                                               bad_encoder2, None, ': ', ', ',
+                                               False, False, False)
+        with self.assertRaises(ZeroDivisionError):
+            enc('spam', 4)
+
     def test_bad_bool_args(self):
         def test(name):
             self.json.encoder.JSONEncoder(**{name: BadBool()}).encode({'a': 1})
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-18-12-07-39.bpo-31505.VomaFa.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-18-12-07-39.bpo-31505.VomaFa.rst
new file mode 100644 (file)
index 0000000..bad9e51
--- /dev/null
@@ -0,0 +1,2 @@
+Fix an assertion failure in `json`, in case `_json.make_encoder()` received
+a bad `encoder()` argument. Patch by Oren Milman.
index 769696d9d6855869f545665483a9a991de4014b5..13218a6ecce587bc5de63911b2ba973aeb8c99c4 100644 (file)
@@ -1429,10 +1429,20 @@ static PyObject *
 encoder_encode_string(PyEncoderObject *s, PyObject *obj)
 {
     /* Return the JSON representation of a string */
-    if (s->fast_encode)
+    PyObject *encoded;
+
+    if (s->fast_encode) {
         return s->fast_encode(NULL, obj);
-    else
-        return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
+    }
+    encoded = PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
+    if (encoded != NULL && !PyUnicode_Check(encoded)) {
+        PyErr_Format(PyExc_TypeError,
+                     "encoder() must return a string, not %.80s",
+                     Py_TYPE(encoded)->tp_name);
+        Py_DECREF(encoded);
+        return NULL;
+    }
+    return encoded;
 }
 
 static int