From a8e6d5f8714ad470ae1dbbf6198dec03092d954c Mon Sep 17 00:00:00 2001 From: omkar bhor Date: Fri, 9 Oct 2026 05:52:59 +0530 Subject: [PATCH] Fix undefined behavior on out-of-range array index in has() and del() (#3560) Converting a double outside the int range to int is undefined behavior, and has() and del() did it on array indices like infinite or 1e10, which UBSan reports as "inf is outside the range of representable values of type 'int'". Only NaN was guarded against. Clamp the index to the int range in has(), as getting and setting array elements already do, and drop out-of-range indices in del() before they are converted. Such indices can never refer to an element, so has() returns false and del() leaves the array unchanged, the same as for indices past the end of the array. Valid indices deleted together with out-of-range ones, as in del(.[0, 1e10]), are still deleted. --- src/jv_aux.c | 12 ++++++++---- tests/jq.test | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/jv_aux.c b/src/jv_aux.c index 4f5be0ab..72a3816a 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -260,11 +260,14 @@ jv jv_has(jv t, jv k) { jv_free(elem); } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) { - if (jvp_number_is_nan(k)) { + double nv = jv_number_value(k); + if (isnan(nv)) { jv_free(t); ret = jv_false(); } else { - jv elem = jv_array_get(t, (int)jv_number_value(k)); + if (nv < INT_MIN) nv = INT_MIN; + if (nv > INT_MAX) nv = INT_MAX; + jv elem = jv_array_get(t, (int)nv); ret = jv_bool(jv_is_valid(elem)); jv_free(elem); } @@ -294,9 +297,10 @@ static jv jv_dels(jv t, jv keys) { jv starts = jv_array(), ends = jv_array(); jv_array_foreach(keys, i, key) { if (jv_get_kind(key) == JV_KIND_NUMBER) { - if (jvp_number_is_nan(key)) { + double nv = jv_number_value(key); + if (isnan(nv) || nv < INT_MIN || nv > INT_MAX) { jv_free(key); - } else if (jv_number_value(key) < 0) { + } else if (nv < 0) { neg_keys = jv_array_append(neg_keys, key); } else { nonneg_keys = jv_array_append(nonneg_keys, key); diff --git a/tests/jq.test b/tests/jq.test index ca73c999..9f2ab525 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -1752,6 +1752,38 @@ has(nan) [0,1,2] false +has(infinite) +[0,1,2] +false + +has(-infinite) +[0,1,2] +false + +del(.[infinite]) +[1,2,3] +[1,2,3] + +del(.[-infinite]) +[1,2,3] +[1,2,3] + +has(1e10) +[0,1,2] +false + +has(-1e10) +[0,1,2] +false + +del(.[1e10]) +[1,2,3] +[1,2,3] + +del(.[-1e10]) +[1,2,3] +[1,2,3] + keys [42,3,35] [0,1,2]