From 4b1ac7c95fc72b1fd59211f5af46cdf13f4ad478 Mon Sep 17 00:00:00 2001 From: Emanuele Torre Date: Fri, 14 Jul 2023 00:12:27 +0200 Subject: [PATCH] Parse nan in JSON as NaN instead of triggering a parse error (#2712) * Fix memory leak for has(nan) jv_array_get() used to be responsible of freeing the input array, but since b5c4c3d67decec22d34f494a200af59bbcadcc80, it is no longer called if the key is nan. We need to free it manually to avoid leaking the array. * Parse nan in JSON as NaN instead of triggering a parse error Fixes #2021 --- src/jv_aux.c | 1 + src/jv_parse.c | 6 +++++- tests/jq.test | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/jv_aux.c b/src/jv_aux.c index 3153d6e6..6a5efa94 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -215,6 +215,7 @@ jv jv_has(jv t, jv k) { } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) { if (jvp_number_is_nan(k)) { + jv_free(t); ret = jv_false(); } else { jv elem = jv_array_get(t, (int)jv_number_value(k)); diff --git a/src/jv_parse.c b/src/jv_parse.c index e91f65d0..2caf330b 100644 --- a/src/jv_parse.c +++ b/src/jv_parse.c @@ -490,7 +490,11 @@ static pfunc check_literal(struct jv_parser* p) { switch (p->tokenbuf[0]) { case 't': pattern = "true"; plen = 4; v = jv_true(); break; case 'f': pattern = "false"; plen = 5; v = jv_false(); break; - case 'n': pattern = "null"; plen = 4; v = jv_null(); break; + case 'n': + // if it starts with 'n', it could be a literal "nan" + if (p->tokenpos != 3) { + pattern = "null"; plen = 4; v = jv_null(); + } } if (pattern) { if (p->tokenpos != plen) return "Invalid literal"; diff --git a/tests/jq.test b/tests/jq.test index 3182c1f3..4a8bfeee 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -1799,6 +1799,18 @@ reduce .[] as $then (4 as $else | $else; . as $elif | . + $then * $elif) # { $__loc__ } works + { a, $__loc__, c } {"a":[1,2,3],"b":"foo","c":{"hi":"hey"}} {"a":[1,2,3],"__loc__":{"file":"","line":1},"c":{"hi":"hey"}} + + +# nan is parsed as a valid NaN value from JSON + +fromjson | isnan +"nan" +true + +tojson | fromjson +{"a":nan} +{"a":null}