From cdf23ea724ba3686ab5d65dd0b6fce2317409ca9 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Mon, 30 Jan 2017 14:30:49 -0600 Subject: [PATCH] fixup parser bugs --- src/jv.c | 8 ++++++ src/jv_parse.c | 66 +++++++++++++++++++++++--------------------------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/jv.c b/src/jv.c index 64e358448f..fe0dc58ce9 100644 --- a/src/jv.c +++ b/src/jv.c @@ -191,6 +191,10 @@ int64_t jv_int64_value(jv j) return (int64_t)j.u.uint64; return INT64_MAX; } + if (j.u.number > 0 && (int64_t)j.u.number < 0) + return INT64_MAX; + if (j.u.number < 0 && (int64_t)j.u.number > 0) + return INT64_MIN; #endif return j.u.number; } @@ -207,6 +211,10 @@ uint64_t jv_uint64_value(jv j) return j.u.int64; return 0; } + if (j.u.number < 0) + return 0; + if (j.u.number > (double)UINT64_MAX) + return UINT64_MAX; #endif return j.u.number; } diff --git a/src/jv_parse.c b/src/jv_parse.c index 2343b226d9..617fb97e76 100644 --- a/src/jv_parse.c +++ b/src/jv_parse.c @@ -495,53 +495,47 @@ static pfunc check_literal(struct jv_parser* p) { } else { // FIXME: better parser p->tokenbuf[p->tokenpos] = 0; - char* end = 0; - double d = jvp_strtod(&p->dtoa, p->tokenbuf, &end); - if (end == 0 || *end != 0) - return "Invalid numeric literal"; + char *end = 0; #ifndef JQ_OMIT_INTS - if (d == (int64_t)d || d == (uint64_t)d) { - if (d >= INT64_MIN && d <= INT64_MAX) { - TRY(value(p, jv_int64(d))); - goto out; - } else if (d >= 0 && d <= UINT64_MAX) { - TRY(value(p, jv_uint64(d))); - goto out; - } - - char *q = p->tokenbuf; - int is_signed = 0; - while (isspace(*q)) - q++; - if (*q == '-') { - is_signed = 1; - q++; - } - errno = 0; - if (is_signed) { + char *q = p->tokenbuf; + int is_signed = 0; + while (isspace(*q)) + q++; + if (*q == '-') { + is_signed = 1; + q++; + } + errno = 0; + if (is_signed) { #ifdef HAVE_STRTOIMAX - int64_t i64 = strtoimax(p->tokenbuf, &q, 10); + int64_t i64 = strtoimax(p->tokenbuf, &end, 10); #else - int64_t i64 = strtoll(p->tokenbuf, &q, 10); + int64_t i64 = strtoll(p->tokenbuf, &end, 10); #endif - if (q == end && i64 < 0 && errno == 0) { - TRY(value(p, jv_int64(i64))); - goto out; - } - } else { + if (end != 0 && *end == 0 && i64 < 0 && errno == 0) { + TRY(value(p, jv_int64(i64))); + goto out; + } + } else { #ifdef HAVE_STRTOUMAX - uint64_t u64 = strtoumax(p->tokenbuf, &q, 10); + uint64_t u64 = strtoumax(p->tokenbuf, &end, 10); #else - uint64_t u64 = strtoull(p->tokenbuf, &q, 10); + uint64_t u64 = strtoull(p->tokenbuf, &end, 10); #endif - if (q == end && errno == 0) { - TRY(value(p, jv_int64(u64))); - goto out; - } + if (end != 0 && *end == 0 && errno == 0) { + TRY(value(p, jv_uint64(u64))); + goto out; } } #endif + double d = jvp_strtod(&p->dtoa, p->tokenbuf, &end); + if (end == 0 || *end != 0) + return "Invalid numeric literal"; + /* + * So there was a decimal or exponent; this might still be an + * integer, but we'll go with double. + */ TRY(value(p, jv_number(d))); } out: