diff --git a/lua_cjson.c b/lua_cjson.c index f1aa4ad..39a7164 100644 --- a/lua_cjson.c +++ b/lua_cjson.c @@ -37,6 +37,7 @@ */ #include +#include #include #include #include @@ -1585,9 +1586,14 @@ static int json_is_invalid_number(json_parse_t *json) static void json_next_number_token(json_parse_t *json, json_token_t *token) { char *endptr; - long long tmpval = strtoll(json->ptr, &endptr, 10); - if (json->ptr == endptr || *endptr == '.' || *endptr == 'e' || - *endptr == 'E' || *endptr == 'x') { + long long tmpval; + + errno = 0; + tmpval = strtoll(json->ptr, &endptr, 10); + /* Reparse overflowing integers as doubles instead of using the + * saturated value returned by strtoll(). */ + if (errno == ERANGE || json->ptr == endptr || *endptr == '.' || + *endptr == 'e' || *endptr == 'E' || *endptr == 'x') { token->type = T_NUMBER; token->value.number = fpconv_strtod(json->ptr, &endptr); if (json->ptr == endptr) { diff --git a/tests/test.lua b/tests/test.lua index 984c583..42bc0e2 100755 --- a/tests/test.lua +++ b/tests/test.lua @@ -101,6 +101,15 @@ local cjson_tests = { { "Decode numbers", json.decode, { '[ 0.0, -5e3, -1, 0.3e-3, 1023.2, 0e10 ]' }, true, { { 0.0, -5000, -1, 0.0003, 1023.2, 0 } } }, + { "Decode positive integer overflow as a number", + json.decode, { '100000000000000000000' }, + true, { 1e20 } }, + { "Decode negative integer overflow as a number", + json.decode, { '-100000000000000000000' }, + true, { -1e20 } }, + { "Decode integers following overflowing numbers", + json.decode, { '[ 100000000000000000000, 42, -100000000000000000000, -42 ]' }, + true, { { 1e20, 42, -1e20, -42 } } }, { "Decode null", json.decode, { 'null' }, true, { json.null } }, { "Decode true",