From cb180ce34cd711b7a4781b17a29201444d7250aa Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Sat, 28 May 2022 16:10:15 +0200 Subject: [PATCH 1/3] add additional tests for integer overflow during parsing --- tests/test_ujson.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_ujson.py b/tests/test_ujson.py index 9c40b97b..3a6ee50a 100644 --- a/tests/test_ujson.py +++ b/tests/test_ujson.py @@ -592,7 +592,10 @@ def test_decode_range_raises(test_input, expected): ("[]]", ujson.JSONDecodeError), # array unmatched bracket fail ("18446744073709551616", ujson.JSONDecodeError), # too big value ("-90223372036854775809", ujson.JSONDecodeError), # too small value + ("-23058430092136939529", ujson.JSONDecodeError), # too small value + ("-11529215046068469760", ujson.JSONDecodeError), # too small value ("18446744073709551616", ujson.JSONDecodeError), # very too big value + ("23058430092136939529", ujson.JSONDecodeError), # 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 From 9c42263c80bb7bf00870f607c256b71c72352437 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Sat, 28 May 2022 17:01:30 +0200 Subject: [PATCH 2/3] fix integer decoding: always detect overflows --- lib/ultrajsondec.c | 55 ++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/lib/ultrajsondec.c b/lib/ultrajsondec.c index 73e8a5db..d24cfe59 100644 --- a/lib/ultrajsondec.c +++ b/lib/ultrajsondec.c @@ -92,23 +92,31 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_numeric (struct DecoderState *ds int intNeg = 1; int hasError = 0; JSUINT64 intValue; - JSUINT64 prevIntValue; + JSUINT64 addIntValue; int chr; char *offset = ds->start; - JSUINT64 overflowLimit = LLONG_MAX; + JSUINT64 maxIntValue = ULLONG_MAX; + JSUINT64 overflowLimit = maxIntValue / 10LLU; - if (*(offset) == 'I') { + if (*(offset) == 'I') + { + goto DECODE_INF; + } + else if (*(offset) == 'N') + { + goto DECODE_NAN; + } + else if (*(offset) == '-') + { + offset++; + intNeg = -1; + if (*(offset) == 'I') + { goto DECODE_INF; - } else if (*(offset) == 'N') { - goto DECODE_NAN; - } else if (*(offset) == '-') { - offset++; - intNeg = -1; - if (*(offset) == 'I') { - goto DECODE_INF; - } - overflowLimit = LLONG_MIN; + } + maxIntValue = -(JSUINT64) LONG_MIN; + overflowLimit = maxIntValue / 10LL; } // Scan integer part @@ -131,19 +139,21 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_numeric (struct DecoderState *ds case '8': case '9': { - //PERF: Don't do 64-bit arithmetic here unless we know we have to - prevIntValue = intValue; - intValue = intValue * 10ULL + (JSLONG) (chr - 48); - - if (intNeg == 1 && prevIntValue > intValue) + // check whether multiplication would be out of bounds + if (intValue > overflowLimit) { hasError = 1; } - else if (intNeg == -1 && intValue > overflowLimit) + intValue *= 10ULL; + addIntValue = (JSUINT64) (chr - 48); + + // check whether addition would be out of bounds + if (maxIntValue - intValue < addIntValue) { hasError = 1; } + intValue += addIntValue; offset ++; break; } @@ -163,14 +173,7 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_numeric (struct DecoderState *ds { if (hasError) { - if (intNeg == 1) - { - return SetError(ds, -1, "Value is too big!"); - } - else if (intNeg == -1) - { - return SetError(ds, -1, overflowLimit == LLONG_MAX ? "Value is too big!" : "Value is too small"); - } + return SetError(ds, -1, intNeg == 1 ? "Value is too big" : "Value is too small"); } goto BREAK_INT_LOOP; break; From 0a0e111701ef3ab2c1689f5de59dcf084a786a06 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Sun, 29 May 2022 19:24:07 +0200 Subject: [PATCH 3/3] fix typo: LLONG_MIN --- lib/ultrajsondec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ultrajsondec.c b/lib/ultrajsondec.c index d24cfe59..6c59bf02 100644 --- a/lib/ultrajsondec.c +++ b/lib/ultrajsondec.c @@ -115,7 +115,7 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_numeric (struct DecoderState *ds { goto DECODE_INF; } - maxIntValue = -(JSUINT64) LONG_MIN; + maxIntValue = -(JSUINT64) LLONG_MIN; overflowLimit = maxIntValue / 10LL; }