From c1c7bd4c59c25d6fe062ef5d3a95ce2e597363dc Mon Sep 17 00:00:00 2001 From: Ken Robbins Date: Fri, 29 Sep 2017 20:33:05 -0700 Subject: [PATCH] Fix loads exception handling. Don't assume exception class can accept a single string. --- CHANGES.rst | 7 +++++++ rapidjson.cpp | 11 ++++++++--- tests/test_unicode.py | 10 ++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 27f993b..60a3182 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,13 @@ Changes ------- +Unreleased +~~~~~~~~~~ + +* Fix bug where error handling code could raise an exception causing a + confusing exception to be returned. + + 0.2.4 (2017-09-17) ~~~~~~~~~~~~~~~~~~ diff --git a/rapidjson.cpp b/rapidjson.cpp index 64a8f59..057c671 100644 --- a/rapidjson.cpp +++ b/rapidjson.cpp @@ -1278,11 +1278,16 @@ do_decode(PyObject* decoder, const char* jsonStr, Py_ssize_t jsonStrLen, PyObject* etraceback; PyErr_Fetch(&etype, &evalue, &etraceback); + // Try to add the offset in the error message if the exception + // value is a string. Otherwise, use the original exception since + // we can't be sure the exception type takes a single string. const char* emsg = msg; - if (PyUnicode_Check(evalue)) + if (PyUnicode_Check(evalue)) { emsg = PyUnicode_AsUTF8(evalue); - - PyErr_Format(etype, fmt, offset, emsg); + PyErr_Format(etype, fmt, offset, emsg); + } + else + PyErr_Restore(etype, evalue, etraceback); } else PyErr_Format(PyExc_ValueError, fmt, offset, msg); diff --git a/tests/test_unicode.py b/tests/test_unicode.py index e2d006d..f2a2f25 100644 --- a/tests/test_unicode.py +++ b/tests/test_unicode.py @@ -46,3 +46,13 @@ def test_dump_surrogate(o, dumps): def test_load_surrogate(j, loads): with pytest.raises(ValueError, match="surrogate pair in string is invalid"): loads(j) + + +@pytest.mark.unit +@pytest.mark.parametrize('j', [ + '"\\udc00"', + '"\\udfff"', +]) +def test_unicode_decode_error(j, loads): + with pytest.raises(UnicodeDecodeError, match="'utf-8' codec can't decode byte"): + loads(j)