Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add JSONDecodeError #498

Merged
merged 3 commits into from Feb 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion python/JSONtoObj.c
Expand Up @@ -38,6 +38,7 @@ Numeric decoder derived from from TCL library

#include <Python.h>
#include <ultrajson.h>
#include "ujson.h"


//#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__)
Expand Down Expand Up @@ -187,7 +188,7 @@ PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs)
/*
FIXME: It's possible to give a much nicer error message here with actual failing element in input etc*/

PyErr_Format (PyExc_ValueError, "%s", decoder.errorStr);
PyErr_Format (JSONDecodeError, "%s", decoder.errorStr);

if (ret)
{
Expand Down
13 changes: 13 additions & 0 deletions python/ujson.c
Expand Up @@ -38,6 +38,7 @@ Numeric decoder derived from from TCL library

#include <Python.h>
#include "version.h"
#include "ujson.h"

/* objToJSON */
PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs);
Expand All @@ -51,6 +52,8 @@ PyObject* objToJSONFile(PyObject* self, PyObject *args, PyObject *kwargs);
/* JSONFileToObj */
PyObject* JSONFileToObj(PyObject* self, PyObject *args, PyObject *kwargs);

PyObject* JSONDecodeError;


#define ENCODER_HELP_TEXT "Use ensure_ascii=false to output UTF-8. " \
"Set encode_html_chars=True to encode < > & as unicode escape sequences. "\
Expand Down Expand Up @@ -188,5 +191,15 @@ PyMODINIT_FUNC PyInit_ujson(void)
PyErr_Clear();
#endif

JSONDecodeError = PyErr_NewException("ujson.JSONDecodeError", PyExc_ValueError, NULL);
Py_XINCREF(JSONDecodeError);
if (PyModule_AddObject(module, "JSONDecodeError", JSONDecodeError) < 0)
{
Py_XDECREF(JSONDecodeError);
Py_CLEAR(JSONDecodeError);
Py_DECREF(module);
return NULL;
}

return module;
}
1 change: 1 addition & 0 deletions python/ujson.h
@@ -0,0 +1 @@
extern PyObject* JSONDecodeError;
68 changes: 36 additions & 32 deletions tests/test_ujson.py
Expand Up @@ -555,46 +555,46 @@ def test_decode_numeric_int_exp(test_input):
@pytest.mark.parametrize(
"test_input, expected",
[
('{{1337:""}}', ValueError), # broken dict key type leak test
('{{"key":"}', ValueError), # broken dict leak test
('{{"key":"}', ValueError), # broken dict leak test
("[[[true", ValueError), # broken list leak test
('{{1337:""}}', ujson.JSONDecodeError), # broken dict key type leak test
('{{"key":"}', ujson.JSONDecodeError), # broken dict leak test
('{{"key":"}', ujson.JSONDecodeError), # broken dict leak test
("[[[true", ujson.JSONDecodeError), # broken list leak test
],
)
def test_decode_range_raises(test_input, expected):
for x in range(1000):
with pytest.raises(ValueError):
with pytest.raises(expected):
ujson.decode(test_input)


@pytest.mark.parametrize(
"test_input, expected",
[
("fdsa sda v9sa fdsa", ValueError), # jibberish
("[", ValueError), # broken array start
("{", ValueError), # broken object start
("]", ValueError), # broken array end
("}", ValueError), # broken object end
('{"one":1,}', ValueError), # object trailing comma fail
('"TESTING', ValueError), # string unterminated
('"TESTING\\"', ValueError), # string bad escape
("tru", ValueError), # true broken
("fa", ValueError), # false broken
("n", ValueError), # null broken
("{{{{31337}}}}", ValueError), # dict with no key
('{{{{"key"}}}}', ValueError), # dict with no colon or value
('{{{{"key":}}}}', ValueError), # dict with no value
("[31337,]", ValueError), # array trailing comma fail
("[,31337]", ValueError), # array leading comma fail
("[,]", ValueError), # array only comma fail
("[]]", ValueError), # array unmatched bracket fail
("18446744073709551616", ValueError), # too big value
("-90223372036854775809", ValueError), # too small value
("18446744073709551616", ValueError), # very too big value
("-90223372036854775809", ValueError), # very too small value
("{}\n\t a", ValueError), # with trailing non whitespaces
("[18446744073709551616]", ValueError), # array with big int
('{"age", 44}', ValueError), # read bad object syntax
("fdsa sda v9sa fdsa", ujson.JSONDecodeError), # jibberish
("[", ujson.JSONDecodeError), # broken array start
("{", ujson.JSONDecodeError), # broken object start
("]", ujson.JSONDecodeError), # broken array end
("}", ujson.JSONDecodeError), # broken object end
('{"one":1,}', ujson.JSONDecodeError), # object trailing comma fail
('"TESTING', ujson.JSONDecodeError), # string unterminated
('"TESTING\\"', ujson.JSONDecodeError), # string bad escape
("tru", ujson.JSONDecodeError), # true broken
("fa", ujson.JSONDecodeError), # false broken
("n", ujson.JSONDecodeError), # null broken
("{{{{31337}}}}", ujson.JSONDecodeError), # dict with no key
('{{{{"key"}}}}', ujson.JSONDecodeError), # dict with no colon or value
('{{{{"key":}}}}', ujson.JSONDecodeError), # dict with no value
("[31337,]", ujson.JSONDecodeError), # array trailing comma fail
("[,31337]", ujson.JSONDecodeError), # array leading comma fail
("[,]", ujson.JSONDecodeError), # array only comma fail
("[]]", ujson.JSONDecodeError), # array unmatched bracket fail
("18446744073709551616", ujson.JSONDecodeError), # too big value
("-90223372036854775809", ujson.JSONDecodeError), # too small value
("18446744073709551616", ujson.JSONDecodeError), # very too big value
("-90223372036854775809", ujson.JSONDecodeError), # very too small value
("{}\n\t a", ujson.JSONDecodeError), # with trailing non whitespaces
("[18446744073709551616]", ujson.JSONDecodeError), # array with big int
('{"age", 44}', ujson.JSONDecodeError), # read bad object syntax
],
)
def test_decode_raises(test_input, expected):
Expand All @@ -605,15 +605,19 @@ def test_decode_raises(test_input, expected):
@pytest.mark.parametrize(
"test_input, expected",
[
("[", ValueError), # array depth too big
("{", ValueError), # object depth too big
("[", ujson.JSONDecodeError), # array depth too big
("{", ujson.JSONDecodeError), # object depth too big
],
)
def test_decode_raises_for_long_input(test_input, expected):
with pytest.raises(expected):
ujson.decode(test_input * (1024 * 1024))


def test_decode_exception_is_value_error():
assert issubclass(ujson.JSONDecodeError, ValueError)


@pytest.mark.parametrize(
"test_input, expected",
[
Expand Down