From 5decd38112c02dbd646c2d13b9563460ee15eb4b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 Nov 2017 22:01:29 +0200 Subject: bpo-31505: Fix an assertion failure in json, in case _json.make_encoder() received a bad encoder() argument. Original patch by Oren Milman. --- simplejson/_speedups.c | 21 ++++++++++++++++++--- simplejson/tests/test_speedups.py | 26 ++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c index 7b46d8a..60f15e1 100644 --- a/simplejson/_speedups.c +++ b/simplejson/_speedups.c @@ -2807,10 +2807,25 @@ 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 py_encode_basestring_ascii(NULL, obj); - else - return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL); + } + encoded = PyObject_CallFunctionObjArgs(s->encoder, obj, NULL); + if (encoded != NULL && +#if PY_MAJOR_VERSION < 3 + !JSON_ASCII_Check(unicode) && +#endif /* PY_MAJOR_VERSION < 3 */ + !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 diff --git a/simplejson/tests/test_speedups.py b/simplejson/tests/test_speedups.py index b59eeca..75242fd 100644 --- a/simplejson/tests/test_speedups.py +++ b/simplejson/tests/test_speedups.py @@ -59,6 +59,32 @@ class TestEncode(TestCase): None ) + @skip_if_speedups_missing + 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 = encoder.c_make_encoder( + None, lambda obj: str(obj), + bad_encoder1, None, ': ', ', ', + False, False, False, {}, False, False, False, + None, None, 'utf-8', False, False, decimal.Decimal, False) + self.assertRaises(TypeError, enc, 'spam', 4) + self.assertRaises(TypeError, enc, {'spam': 42}, 4) + + def bad_encoder2(*args): + 1/0 + enc = encoder.c_make_encoder( + None, lambda obj: str(obj), + bad_encoder2, None, ': ', ', ', + False, False, False, {}, False, False, False, + None, None, 'utf-8', False, False, decimal.Decimal, False) + enc = self.json.encoder.c_make_encoder(None, lambda obj: str(obj), + bad_encoder2, None, ': ', ', ', + False, False, False) + self.assertRaises(ZeroDivisionError, enc, 'spam', 4) + @skip_if_speedups_missing def test_bad_bool_args(self): def test(name): -- cgit v1.2.1 From eb9665a751e8aea21aeedea02ae6617ff53eeaad Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 Nov 2017 22:42:58 +0200 Subject: Fix a test. --- simplejson/tests/test_speedups.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/simplejson/tests/test_speedups.py b/simplejson/tests/test_speedups.py index 75242fd..8b146df 100644 --- a/simplejson/tests/test_speedups.py +++ b/simplejson/tests/test_speedups.py @@ -63,6 +63,7 @@ class TestEncode(TestCase): 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. + import decimal def bad_encoder1(*args): return None enc = encoder.c_make_encoder( @@ -80,9 +81,6 @@ class TestEncode(TestCase): bad_encoder2, None, ': ', ', ', False, False, False, {}, False, False, False, None, None, 'utf-8', False, False, decimal.Decimal, False) - enc = self.json.encoder.c_make_encoder(None, lambda obj: str(obj), - bad_encoder2, None, ': ', ', ', - False, False, False) self.assertRaises(ZeroDivisionError, enc, 'spam', 4) @skip_if_speedups_missing -- cgit v1.2.1