diff -up jq-1.6/src/jv_aux.c.orig jq-1.6/src/jv_aux.c --- jq-1.6/src/jv_aux.c.orig 2025-06-30 18:14:49.211823479 +0200 +++ jq-1.6/src/jv_aux.c 2025-06-30 18:15:20.270512946 +0200 @@ -162,18 +162,19 @@ jv jv_set(jv t, jv k, jv v) { if (slice_len < insert_len) { // array is growing int shift = insert_len - slice_len; - for (int i = array_len - 1; i >= end; i--) { + for (int i = array_len - 1; i >= end && jv_is_valid(t); i--) { t = jv_array_set(t, i + shift, jv_array_get(jv_copy(t), i)); } } else if (slice_len > insert_len) { // array is shrinking int shift = slice_len - insert_len; - for (int i = end; i < array_len; i++) { + for (int i = end; i < array_len && jv_is_valid(t); i++) { t = jv_array_set(t, i - shift, jv_array_get(jv_copy(t), i)); } - t = jv_array_slice(t, 0, array_len - shift); + if (jv_is_valid(t)) + t = jv_array_slice(t, 0, array_len - shift); } - for (int i=0; i < insert_len; i++) { + for (int i = 0; i < insert_len && jv_is_valid(t); i++) { t = jv_array_set(t, start + i, jv_array_get(jv_copy(v), i)); } jv_free(v); diff -up jq-1.6/src/jv.c.orig jq-1.6/src/jv.c --- jq-1.6/src/jv.c.orig 2025-06-30 18:14:49.221499541 +0200 +++ jq-1.6/src/jv.c 2025-06-30 18:17:11.071456789 +0200 @@ -326,10 +326,10 @@ static double jvp_literal_number_to_doub decNumber *p_dec_number = jvp_dec_number_ptr(j); decNumberDoublePrecision dec_double; - char literal[BIN64_DEC_PRECISION + DEC_NUMBER_STRING_GUARD + 1]; + char literal[BIN64_DEC_PRECISION + DEC_NUMBER_STRING_GUARD + 1]; // reduce the number to the shortest possible form - // while also making sure than no more than BIN64_DEC_PRECISION + // while also making sure than no more than BIN64_DEC_PRECISION // digits are used (dec_context_to_double) decNumberReduce(&dec_double.number, p_dec_number, DEC_CONTEXT_TO_DOUBLE()); @@ -368,7 +368,7 @@ static const char* jvp_literal_number_li // Preserve the actual precision as we have parsed it // don't do decNumberTrim(pdec); - + decNumberToString(pdec, plit->literal_data); } @@ -459,9 +459,9 @@ int jvp_number_cmp(jv a, jv b) { assert(JVP_HAS_KIND(b, JV_KIND_NUMBER)); if(JVP_HAS_FLAGS(a, JVP_FLAGS_NUMBER_LITERAL) && JVP_HAS_FLAGS(b, JVP_FLAGS_NUMBER_LITERAL)) { - decNumberSingle res; - decNumberCompare(&res.number, - jvp_dec_number_ptr(a), + decNumberSingle res; + decNumberCompare(&res.number, + jvp_dec_number_ptr(a), jvp_dec_number_ptr(b), DEC_CONTEXT() ); @@ -703,6 +703,11 @@ jv jv_array_set(jv j, int idx, jv val) { jv_free(val); return jv_invalid_with_msg(jv_string("Out of bounds negative array index")); } + if (idx > (INT_MAX >> 2) - jvp_array_offset(j)) { + jv_free(j); + jv_free(val); + return jv_invalid_with_msg(jv_string("Array index too large")); + } // copy/free of val,j coalesced jv* slot = jvp_array_write(&j, idx); jv_free(*slot); @@ -722,6 +727,7 @@ jv jv_array_concat(jv a, jv b) { // FIXME: could be faster jv_array_foreach(b, i, elem) { a = jv_array_append(a, elem); + if (!jv_is_valid(a)) break; } jv_free(b); return a; @@ -992,6 +998,7 @@ jv jv_string_indexes(jv j, jv k) { p = jstr; while ((p = _jq_memmem(p, (jstr + jlen) - p, idxstr, idxlen)) != NULL) { a = jv_array_append(a, jv_number(p - jstr)); + if (!jv_is_valid(a)) break; p += idxlen; } jv_free(j); @@ -1013,14 +1020,17 @@ jv jv_string_split(jv j, jv sep) { if (seplen == 0) { int c; - while ((jstr = jvp_utf8_next(jstr, jend, &c))) + while ((jstr = jvp_utf8_next(jstr, jend, &c))) { a = jv_array_append(a, jv_string_append_codepoint(jv_string(""), c)); + if (!jv_is_valid(a)) break; + } } else { for (p = jstr; p < jend; p = s + seplen) { s = _jq_memmem(p, jend - p, sepstr, seplen); if (s == NULL) s = jend; a = jv_array_append(a, jv_string_sized(p, s - p)); + if (!jv_is_valid(a)) break; // Add an empty string to denote that j ends on a sep if (s + seplen == jend && seplen != 0) a = jv_array_append(a, jv_string("")); @@ -1038,8 +1048,10 @@ jv jv_string_explode(jv j) { const char* end = i + len; jv a = jv_array_sized(len); int c; - while ((i = jvp_utf8_next(i, end, &c))) + while ((i = jvp_utf8_next(i, end, &c))) { a = jv_array_append(a, jv_number(c)); + if (!jv_is_valid(a)) break; + } jv_free(j); return a; } @@ -1312,10 +1324,13 @@ static void jvp_object_free(jv o) { } } -static jv jvp_object_rehash(jv object) { +static int jvp_object_rehash(jv *objectp) { + jv object = *objectp; assert(JVP_HAS_KIND(object, JV_KIND_OBJECT)); assert(jvp_refcnt_unshared(object.u.ptr)); int size = jvp_object_size(object); + if (size > INT_MAX >> 2) + return 0; jv new_object = jvp_object_new(size * 2); for (int i=0; ivalue; + *valpp = &slot->value; + return 1; } slot = jvp_object_add_slot(*object, key, bucket); if (slot) { slot->value = jv_invalid(); } else { - *object = jvp_object_rehash(*object); + if (!jvp_object_rehash(object)) { + *valpp = NULL; + return 0; + } bucket = jvp_object_find_bucket(*object, key); assert(!jvp_object_find_slot(*object, key, bucket)); slot = jvp_object_add_slot(*object, key, bucket); assert(slot); slot->value = jv_invalid(); } - return &slot->value; + *valpp = &slot->value; + return 1; } static int jvp_object_delete(jv* object, jv key) { @@ -1478,7 +1499,11 @@ jv jv_object_set(jv object, jv key, jv v assert(JVP_HAS_KIND(object, JV_KIND_OBJECT)); assert(JVP_HAS_KIND(key, JV_KIND_STRING)); // copy/free of object, key, value coalesced - jv* slot = jvp_object_write(&object, key); + jv* slot; + if (!jvp_object_write(&object, key, &slot)) { + jv_free(object); + return jv_invalid_with_msg(jv_string("Object too big")); + } jv_free(*slot); *slot = value; return object; @@ -1503,6 +1528,7 @@ jv jv_object_merge(jv a, jv b) { assert(JVP_HAS_KIND(a, JV_KIND_OBJECT)); jv_object_foreach(b, k, v) { a = jv_object_set(a, k, v); + if (!jv_is_valid(a)) break; } jv_free(b); return a; @@ -1522,6 +1548,7 @@ jv jv_object_merge_recursive(jv a, jv b) jv_free(elem); a = jv_object_set(a, k, v); } + if (!jv_is_valid(a)) break; } jv_free(b); return a; @@ -1671,7 +1698,7 @@ int jv_contains(jv a, jv b) { r = jvp_array_contains(a, b); } else if (JVP_HAS_KIND(a, JV_KIND_STRING)) { int b_len = jv_string_length_bytes(jv_copy(b)); - if (b_len != 0) { + if (b_len != 0) { r = _jq_memmem(jv_string_value(a), jv_string_length_bytes(jv_copy(a)), jv_string_value(b), b_len) != 0; } else { diff -up jq-1.6/tests/jq.test.orig jq-1.6/tests/jq.test --- jq-1.6/tests/jq.test.orig 2025-06-30 18:14:49.214961567 +0200 +++ jq-1.6/tests/jq.test 2025-06-30 18:15:20.271792714 +0200 @@ -186,6 +186,10 @@ null [0,1,2] [0,5,2] +try (.[999999999] = 0) catch . +null +"Array index too large" + # # Multiple outputs, iteration #