Skip to content

Commit 7c24e99

Browse files
miss-islingtonserhiy-storchaka
authored andcommitted
[3.6] bpo-31505: Fix an assertion failure in json, in case _json.make_encoder() received a bad encoder() argument. (GH-3643) (#3777)
(cherry picked from commit 2b382dd)
1 parent 90fe25a commit 7c24e99

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

‎Lib/test/test_json/test_speedups.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@ def test_make_encoder(self):
3636
b"\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75",
3737
None)
3838

39+
def test_bad_str_encoder(self):
40+
# Issue #31505: There shouldn't be an assertion failure in case
41+
# c_make_encoder() receives a bad encoder() argument.
42+
def bad_encoder1(*args):
43+
return None
44+
enc = self.json.encoder.c_make_encoder(None, lambda obj: str(obj),
45+
bad_encoder1, None, ': ', ', ',
46+
False, False, False)
47+
with self.assertRaises(TypeError):
48+
enc('spam', 4)
49+
with self.assertRaises(TypeError):
50+
enc({'spam': 42}, 4)
51+
52+
def bad_encoder2(*args):
53+
1/0
54+
enc = self.json.encoder.c_make_encoder(None, lambda obj: str(obj),
55+
bad_encoder2, None, ': ', ', ',
56+
False, False, False)
57+
with self.assertRaises(ZeroDivisionError):
58+
enc('spam', 4)
59+
3960
def test_bad_bool_args(self):
4061
def test(name):
4162
self.json.encoder.JSONEncoder(**{name: BadBool()}).encode({'a': 1})
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an assertion failure in `json`, in case `_json.make_encoder()` received
2+
a bad `encoder()` argument. Patch by Oren Milman.

‎Modules/_json.c‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,10 +1431,20 @@ static PyObject *
14311431
encoder_encode_string(PyEncoderObject *s, PyObject *obj)
14321432
{
14331433
/* Return the JSON representation of a string */
1434-
if (s->fast_encode)
1434+
PyObject *encoded;
1435+
1436+
if (s->fast_encode) {
14351437
return s->fast_encode(NULL, obj);
1436-
else
1437-
return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
1438+
}
1439+
encoded = PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
1440+
if (encoded != NULL && !PyUnicode_Check(encoded)) {
1441+
PyErr_Format(PyExc_TypeError,
1442+
"encoder() must return a string, not %.80s",
1443+
Py_TYPE(encoded)->tp_name);
1444+
Py_DECREF(encoded);
1445+
return NULL;
1446+
}
1447+
return encoded;
14381448
}
14391449

14401450
static int

0 commit comments

Comments
 (0)