From 824a42bf8c32187bab031e111ff2318ef713b41d Mon Sep 17 00:00:00 2001 From: Jonas Tarnstrom Date: Mon, 19 Sep 2011 17:30:35 +0200 Subject: [PATCH] - Added support for detecting overflow scenario when a PyLong bigger than 64-bits signed is supposed to be converted to such. Now a proper Python exception is thrown - Bumped version - Encoder now uses JT_INVALID from client implementation to abort encoder --- python/objToJSON.c | 26 ++++++++++++++++++++++++-- python/tests.py | 41 +++++++++++++++++++++++------------------ python/version.h | 2 +- ultrajson.h | 2 +- ultrajsonenc.c | 1 - 5 files changed, 49 insertions(+), 23 deletions(-) diff --git a/python/objToJSON.c b/python/objToJSON.c index fe03091..9a43284 100644 --- a/python/objToJSON.c +++ b/python/objToJSON.c @@ -30,6 +30,9 @@ typedef struct __TypeContext PyObject *itemValue; PyObject *itemName; PyObject *attrList; + + JSINT64 longValue; + } TypeContext; #define GET_TC(__ptrtc) ((TypeContext *)((__ptrtc)->prv)) @@ -97,7 +100,7 @@ static void *PyIntToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_ static void *PyLongToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { PyObject *obj = (PyObject *) _obj; - *((JSINT64 *) outValue) = PyLong_AsLongLong (obj); + *((JSINT64 *) outValue) = GET_TC(tc)->longValue; return NULL; } @@ -460,8 +463,22 @@ void Object_beginTypeContext (PyObject *obj, JSONTypeContext *tc) else if (PyLong_Check(obj)) { + PyObject *exc; + PRINTMARK(); - pc->PyTypeToJSON = PyLongToINT64; tc->type = JT_LONG; + pc->PyTypeToJSON = PyLongToINT64; + tc->type = JT_LONG; + GET_TC(tc)->longValue = PyLong_AsLongLong(obj); + + exc = PyErr_Occurred(); + + if (exc && PyErr_ExceptionMatches(PyExc_OverflowError)) + { + PRINTMARK(); + tc->type = JT_INVALID; + return; + } + return; } else @@ -611,6 +628,7 @@ JSINT64 Object_getLongValue(JSOBJ obj, JSONTypeContext *tc) { JSINT64 ret; GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL); + return ret; } @@ -710,6 +728,10 @@ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs) ret = JSON_EncodeObject (oinput, &encoder, buffer, sizeof (buffer)); PRINTMARK(); + if (PyErr_Occurred()) + { + return NULL; + } if (encoder.errorMsg) { diff --git a/python/tests.py b/python/tests.py index 2ff09ce..074589e 100644 --- a/python/tests.py +++ b/python/tests.py @@ -565,29 +565,34 @@ class UltraJSONTests(TestCase): def test_version(self): assert re.match(r'^\d+\.\d+(\.\d+)?$', ujson.__version__), \ "ujson.__version__ must be a string like '1.4.0'" - + + def test_encodeNumericOverflow(self): + try: + ujson.encode(12839128391289382193812939) + except OverflowError: + pass + else: + assert False, "expected OverflowError" + + def test_encodeNumericOverflowNested(self): + for n in xrange(0, 100): + class Nested: + x = 12839128391289382193812939 + + nested = Nested() + + try: + ujson.encode(nested) + except OverflowError: + pass + else: + assert False, "expected OverflowError" + """ def test_decodeNumericIntFrcOverflow(self): input = "X.Y" raise NotImplementedError("Implement this test!") -def test_decodeNumericIntPosOverflow(self): -input = "9223372036854775807322" -try: - ujson.decode(input) - assert False, "Expected exception!" -except(ValueError): - return -assert False, "Wrong exception" - -def test_decodeNumericIntNegOverflow(self): -input = "-9223372036854775807322" -try: - ujson.decode(input) - assert False, "Expected exception!" -except(ValueError): - return -assert False, "Wrong exception" def test_decodeStringUnicodeEscape(self): input = "\u3131" diff --git a/python/version.h b/python/version.h index 8e5ba3e..4de742d 100644 --- a/python/version.h +++ b/python/version.h @@ -1 +1 @@ -#define UJSON_VERSION "1.8" +#define UJSON_VERSION "1.9" diff --git a/ultrajson.h b/ultrajson.h index 7521bc2..1b5db9c 100644 --- a/ultrajson.h +++ b/ultrajson.h @@ -152,7 +152,7 @@ typedef void * JSITER; typedef struct __JSONTypeContext { int type; - void *prv[15]; + void *prv[32]; } JSONTypeContext; /* diff --git a/ultrajsonenc.c b/ultrajsonenc.c index 2dcbca6..c479e82 100644 --- a/ultrajsonenc.c +++ b/ultrajsonenc.c @@ -632,7 +632,6 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName) switch (tc.type) { case JT_INVALID: - SetError(obj, enc, "Could not encode object"); return; case JT_ARRAY: