bpo-31505: Fix an assertion failure in json, in case _json.make_encod… · python/cpython@2b382dd

File tree

3 files changed

lines changed

  • Misc/NEWS.d/next/Core and Builtins

3 files changed

lines changed

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})

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.

Original file line numberDiff line numberDiff line change

@@ -1429,10 +1429,20 @@ static PyObject *

14291429

encoder_encode_string(PyEncoderObject *s, PyObject *obj)

14301430

{

14311431

/* Return the JSON representation of a string */

1432-

if (s->fast_encode)

1432+

PyObject *encoded;

1433+
1434+

if (s->fast_encode) {

14331435

return s->fast_encode(NULL, obj);

1434-

else

1435-

return PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);

1436+

}

1437+

encoded = PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);

1438+

if (encoded != NULL && !PyUnicode_Check(encoded)) {

1439+

PyErr_Format(PyExc_TypeError,

1440+

"encoder() must return a string, not %.80s",

1441+

Py_TYPE(encoded)->tp_name);

1442+

Py_DECREF(encoded);

1443+

return NULL;

1444+

}

1445+

return encoded;

14361446

}

14371447
14381448

static int