Compare commits

...

No commits in common. "c8s" and "imports/c9-beta/jq-1.6-14.el9" have entirely different histories.

25 changed files with 20419 additions and 25894 deletions

View File

@ -1 +0,0 @@
1

1
.gitignore vendored
View File

@ -1,2 +1 @@
SOURCES/jq-1.6.tar.gz SOURCES/jq-1.6.tar.gz
/jq-1.6.tar.gz

1
.jq.metadata Normal file
View File

@ -0,0 +1 @@
02959bca30672e0dfe678e7b36464c8fb08ec389 SOURCES/jq-1.6.tar.gz

View File

@ -1,244 +0,0 @@
commit fead9669cb67badb22789d3ed1888779ed85c679
Author: Tomas Halman <thalman@redhat.com>
Date: Thu Mar 9 11:34:44 2023 +0100
Test that jq works in threads
This patch implements test that searches a key in simple
json in pthread.
diff -up jq-1.6/src/jq_test.c.orig jq-1.6/src/jq_test.c
--- jq-1.6/src/jq_test.c.orig 2023-03-09 14:02:16.980062057 +0100
+++ jq-1.6/src/jq_test.c 2023-03-09 14:03:38.347017032 +0100
@@ -2,12 +2,17 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
#include "jv.h"
#include "jq.h"
static void jv_test();
static void run_jq_tests(jv, int, FILE *, int, int);
-
+#ifdef HAVE_PTHREAD
+static void run_jq_pthread_tests();
+#endif
int jq_testsuite(jv libdirs, int verbose, int argc, char* argv[]) {
FILE *testdata = stdin;
@@ -32,6 +37,9 @@ int jq_testsuite(jv libdirs, int verbose
}
}
run_jq_tests(libdirs, verbose, testdata, skip, take);
+#ifdef HAVE_PTHREAD
+ run_jq_pthread_tests();
+#endif
return 0;
}
@@ -105,7 +113,7 @@ static void run_jq_tests(jv lib_dirs, in
if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n'))
break;
}
-
+
must_fail = 0;
check_msg = 0;
@@ -229,7 +237,7 @@ static void run_jq_tests(jv lib_dirs, in
total_skipped = tests_to_skip - skip;
}
- printf("%d of %d tests passed (%d malformed, %d skipped)\n",
+ printf("%d of %d tests passed (%d malformed, %d skipped)\n",
passed, tests, invalid, total_skipped);
if (skip > 0) {
@@ -241,6 +249,88 @@ static void run_jq_tests(jv lib_dirs, in
}
+/// pthread regression test
+#ifdef HAVE_PTHREAD
+#define NUMBER_OF_THREADS 3
+struct test_pthread_data {
+ int result;
+};
+
+static int test_pthread_jq_parse(jq_state *jq, struct jv_parser *parser)
+{
+ int rv = 0;
+ jv value;
+
+ value = jv_parser_next(parser);
+ while (jv_is_valid(value)) {
+ jq_start(jq, value, 0);
+ jv result = jq_next(jq);
+
+ while (jv_is_valid(result)) {
+ jv_free(result);
+ result = jq_next(jq);
+ }
+ jv_free(result);
+ value = jv_parser_next(parser);
+ }
+ jv_free(value);
+ return rv;
+}
+
+static void *test_pthread_run(void *ptr) {
+ int rv;
+ jq_state *jq;
+ const char *prg = ".data";
+ const char *buf = "{ \"data\": 1 }";
+ struct test_pthread_data *data = ptr;
+
+ jq = jq_init();
+ if (jq_compile(jq, prg) == 0) {
+ jq_teardown(&jq);
+ return NULL;
+ }
+
+ struct jv_parser *parser = jv_parser_new(0);
+ jv_parser_set_buf(parser, buf, strlen(buf), 0);
+ rv = test_pthread_jq_parse(jq, parser);
+
+ data->result = rv;
+
+ jv_parser_free(parser);
+ jq_teardown(&jq);
+ return NULL;
+}
+
+static void run_jq_pthread_tests() {
+ pthread_t threads[NUMBER_OF_THREADS];
+ struct test_pthread_data data[NUMBER_OF_THREADS];
+ int createerror;
+ int a;
+
+ memset(&threads, 0, sizeof(threads));
+ memset(&data, 0, sizeof(data));
+
+ // Create all threads
+ for (a = 0; a < NUMBER_OF_THREADS; ++a) {
+ createerror = pthread_create(&threads[a], NULL, test_pthread_run, &data[a]);
+ assert(createerror == 0);
+ }
+
+ // wait for all threads
+ for(a = 0; a < NUMBER_OF_THREADS; ++a) {
+ if (threads[a] != 0) {
+ pthread_join(threads[a], NULL);
+ }
+ }
+
+ // check results
+ for(a = 0; a < NUMBER_OF_THREADS; ++a) {
+ assert(data[a].result == 0);
+ }
+}
+#endif // HAVE_PTHREAD
+
+
static void jv_test() {
/// JSON parser regression tests
{
commit f05c5bb521f404592b137e02a1b8abd50da87ca3
Author: Tomas Halman <thalman@redhat.com>
Date: Wed Mar 1 20:07:28 2023 +0100
Fix segmentation fault when using jq in threads
In previous code nomem_handler in jv_alloc.c is called only once
and therefore the structure is not initialized for second and
following threads.
This leads to segmentation fault in multi-threading environment.
This patch moves initialization of nomem_handler out of the
pthread_once call.
diff -up jq-1.6/src/jv_alloc.c.orig jq-1.6/src/jv_alloc.c
--- jq-1.6/src/jv_alloc.c.orig 2018-11-02 02:49:29.000000000 +0100
+++ jq-1.6/src/jv_alloc.c 2023-03-09 14:13:47.810177037 +0100
@@ -45,9 +45,11 @@ static void memory_exhausted() {
#ifdef HAVE_PTHREAD_KEY_CREATE
#include <pthread.h>
-pthread_key_t nomem_handler_key;
-pthread_once_t mem_once = PTHREAD_ONCE_INIT;
+static pthread_key_t nomem_handler_key;
+static pthread_once_t mem_once = PTHREAD_ONCE_INIT;
+/* tsd_fini is called on application exit */
+/* it clears the nomem_handler allocated in the main thread */
static void tsd_fini(void) {
struct nomem_handler *nomem_handler;
nomem_handler = pthread_getspecific(nomem_handler_key);
@@ -57,30 +59,45 @@ static void tsd_fini(void) {
}
}
+/* The tsd_fini_thread is a destructor set by calling */
+/* pthread_key_create(&nomem_handler_key, tsd_fini_thread) */
+/* It is called when thread ends */
+static void tsd_fini_thread(void *nomem_handler) {
+ free(nomem_handler);
+}
+
static void tsd_init(void) {
- if (pthread_key_create(&nomem_handler_key, NULL) != 0) {
- fprintf(stderr, "error: cannot create thread specific key");
+ if (pthread_key_create(&nomem_handler_key, tsd_fini_thread) != 0) {
+ fprintf(stderr, "jq: error: cannot create thread specific key");
abort();
}
if (atexit(tsd_fini) != 0) {
- fprintf(stderr, "error: cannot set an exit handler");
+ fprintf(stderr, "jq: error: cannot set an exit handler");
abort();
}
- struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler));
- if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {
- fprintf(stderr, "error: cannot set thread specific data");
- abort();
+}
+
+static void tsd_init_nomem_handler(void)
+{
+ if (pthread_getspecific(nomem_handler_key) == NULL) {
+ struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler));
+ if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {
+ fprintf(stderr, "jq: error: cannot set thread specific data");
+ abort();
+ }
}
}
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
pthread_once(&mem_once, tsd_init); // cannot fail
+ tsd_init_nomem_handler();
+
struct nomem_handler *nomem_handler;
nomem_handler = pthread_getspecific(nomem_handler_key);
if (nomem_handler == NULL) {
handler(data);
- fprintf(stderr, "error: cannot allocate memory\n");
+ fprintf(stderr, "jq: error: cannot allocate memory\n");
abort();
}
nomem_handler->handler = handler;
@@ -91,6 +108,8 @@ static void memory_exhausted() {
struct nomem_handler *nomem_handler;
pthread_once(&mem_once, tsd_init);
+ tsd_init_nomem_handler();
+
nomem_handler = pthread_getspecific(nomem_handler_key);
if (nomem_handler)
nomem_handler->handler(nomem_handler->data); // Maybe handler() will longjmp() to safety

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +0,0 @@
diff -up jq-1.6/src/jq_test.c.orig jq-1.6/src/jq_test.c
--- jq-1.6/src/jq_test.c.orig 2024-05-03 11:47:47.403617188 +0200
+++ jq-1.6/src/jq_test.c 2024-05-03 11:48:46.569675199 +0200
@@ -16,6 +16,7 @@ static void run_jq_pthread_tests();
int jq_testsuite(jv libdirs, int verbose, int argc, char* argv[]) {
FILE *testdata = stdin;
+ const char *testdata_filename = NULL;
int skip = -1;
int take = -1;
jv_test();
@@ -28,18 +29,24 @@ int jq_testsuite(jv libdirs, int verbose
take = atoi(argv[i+1]);
i++;
} else {
- testdata = fopen(argv[i], "r");
- if (!testdata) {
- perror("fopen");
- exit(1);
- }
+ testdata_filename = argv[i];
}
}
}
+ if (testdata_filename) {
+ testdata = fopen(testdata_filename, "r");
+ if (!testdata) {
+ perror("fopen");
+ exit(1);
+ }
+ }
run_jq_tests(libdirs, verbose, testdata, skip, take);
#ifdef HAVE_PTHREAD
run_jq_pthread_tests();
#endif
+ if (testdata_filename) {
+ fclose(testdata);
+ }
return 0;
}
diff -up jq-1.6/src/locfile.c.orig jq-1.6/src/locfile.c
--- jq-1.6/src/locfile.c.orig 2018-11-02 02:49:29.000000000 +0100
+++ jq-1.6/src/locfile.c 2024-05-03 11:15:46.562476303 +0200
@@ -72,6 +72,7 @@ void locfile_locate(struct locfile* l, l
}
jv m1 = jv_string_vfmt(fmt, fmtargs);
+ va_end(fmtargs);
if (!jv_is_valid(m1)) {
jq_report_error(l->jq, m1);
return;

View File

@ -1,238 +0,0 @@
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; i<size; i++) {
struct object_slot* slot = jvp_object_get_slot(object, i);
@@ -1328,7 +1343,8 @@ static jv jvp_object_rehash(jv object) {
}
// references are transported, just drop the old table
jv_mem_free(jvp_object_ptr(object));
- return new_object;
+ *objectp = new_object;
+ return 1;
}
static jv jvp_object_unshare(jv object) {
@@ -1357,27 +1373,32 @@ static jv jvp_object_unshare(jv object)
return new_object;
}
-static jv* jvp_object_write(jv* object, jv key) {
+static int jvp_object_write(jv* object, jv key, jv **valpp) {
*object = jvp_object_unshare(*object);
int* bucket = jvp_object_find_bucket(*object, key);
struct object_slot* slot = jvp_object_find_slot(*object, key, bucket);
if (slot) {
// already has the key
jvp_string_free(key);
- return &slot->value;
+ *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
#

View File

@ -1,111 +0,0 @@
diff -up jq-1.6/src/builtin.c.orig jq-1.6/src/builtin.c
--- jq-1.6/src/builtin.c.orig 2025-06-30 19:07:06.250825334 +0200
+++ jq-1.6/src/builtin.c 2025-06-30 19:08:51.635668449 +0200
@@ -317,19 +317,10 @@ static jv f_multiply(jq_state *jq, jv in
str = b;
num = a;
}
- int n;
- size_t alen = jv_string_length_bytes(jv_copy(str));
- jv res = str;
-
- for (n = jv_number_value(num) - 1; n > 0; n--)
- res = jv_string_append_buf(res, jv_string_value(str), alen);
-
+ double d = jv_number_value(num);
jv_free(num);
- if (n < 0) {
- jv_free(str);
- return jv_null();
- }
- return res;
+ return jv_string_repeat(str,
+ d < 0 || isnan(d) ? -1 : d > INT_MAX ? INT_MAX : (int)d);
} else if (ak == JV_KIND_OBJECT && bk == JV_KIND_OBJECT) {
return jv_object_merge_recursive(a, b);
} else {
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 19:06:08.660648842 +0200
+++ jq-1.6/src/jv.c 2025-06-30 19:07:06.251424952 +0200
@@ -828,6 +828,7 @@ static jv jvp_string_empty_new(uint32_t
jvp_string* s = jvp_string_alloc(length);
s->length_hashed = 0;
memset(s->data, 0, length);
+ s->data[length] = 0;
jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}};
return r;
}
@@ -1006,6 +1007,32 @@ jv jv_string_indexes(jv j, jv k) {
return a;
}
+jv jv_string_repeat(jv j, int n) {
+ assert(JVP_HAS_KIND(j, JV_KIND_STRING));
+ if (n < 0) {
+ jv_free(j);
+ return jv_null();
+ }
+ int len = jv_string_length_bytes(jv_copy(j));
+ int64_t res_len = (int64_t)len * n;
+ if (res_len >= INT_MAX) {
+ jv_free(j);
+ return jv_invalid_with_msg(jv_string("Repeat string result too long"));
+ }
+ if (res_len == 0) {
+ jv_free(j);
+ return jv_string("");
+ }
+ jv res = jv_string_empty(res_len);
+ res = jvp_string_append(res, jv_string_value(j), len);
+ for (int curr = len, grow; curr < res_len; curr += grow) {
+ grow = MIN(res_len - curr, curr);
+ res = jvp_string_append(res, jv_string_value(res), grow);
+ }
+ jv_free(j);
+ return res;
+}
+
jv jv_string_split(jv j, jv sep) {
assert(JVP_HAS_KIND(j, JV_KIND_STRING));
assert(JVP_HAS_KIND(sep, JV_KIND_STRING));
diff -up jq-1.6/src/jv.h.orig jq-1.6/src/jv.h
--- jq-1.6/src/jv.h.orig 2025-06-30 19:06:08.614632776 +0200
+++ jq-1.6/src/jv.h 2025-06-30 19:07:06.251840524 +0200
@@ -120,6 +120,7 @@ jv jv_string_fmt(const char*, ...) JV_PR
jv jv_string_append_codepoint(jv a, uint32_t c);
jv jv_string_append_buf(jv a, const char* buf, int len);
jv jv_string_append_str(jv a, const char* str);
+jv jv_string_repeat(jv j, int n);
jv jv_string_split(jv j, jv sep);
jv jv_string_explode(jv j);
jv jv_string_implode(jv j);
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 19:06:08.661007480 +0200
+++ jq-1.6/tests/jq.test 2025-06-30 19:09:33.221816670 +0200
@@ -1169,6 +1169,18 @@ indices(", ")
["a", "ab", "abc"]
["aaa", "ababab", "abcabcabc"]
+. * 100000 | [.[:10],.[-10:]]
+"abc"
+["abcabcabca","cabcabcabc"]
+
+. * 1000000000
+""
+""
+
+try (. * 1000000000) catch .
+"abc"
+"Repeat string result too long"
+
[.[] / ","]
["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]
[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]
@@ -1560,3 +1572,7 @@ false
.x - 10
{"x":13911860366432393}
13911860366432382
+
+try 0[implode] catch .
+[]
+"Cannot index number with string \"\""

View File

@ -1,48 +1,46 @@
Name: jq Name: jq
Version: 1.6 Version: 1.6
Release: 11%{?dist} Release: 14%{?dist}
Summary: Command-line JSON processor Summary: Command-line JSON processor
License: MIT and ASL 2.0 and CC-BY and GPLv3 License: MIT and ASL 2.0 and CC-BY and GPLv3
URL: http://stedolan.github.io/jq/ URL: http://stedolan.github.io/jq/
Source0: https://github.com/stedolan/jq/releases/download/%{name}-%{version}/%{name}-%{version}.tar.gz Source0: https://github.com/stedolan/jq/releases/download/%{name}-%{version}/%{name}-%{version}.tar.gz
Patch0: 0000-jq-decimal-literal-number.patch # Backport of PR#1752 for RHBZ#2008979
Patch0: jq-decimal-literal-number.patch
Patch1: 0001-iterration-problem-for-non-decimal-string.patch Patch1: 0001-iterration-problem-for-non-decimal-string.patch
Patch2: 0002-add-mantest.patch Patch2: 0002-add-mantest.patch
Patch3: 0003-fix-pthread-segfault.patch
Patch4: 0004-make-jq-fast.patch
Patch5: 0005-sast.patch
Patch6: 0006-CVE-2024-23337.patch
Patch7: 0007-CVE-2025-48060.patch
BuildRequires: gcc
BuildRequires: flex BuildRequires: flex
BuildRequires: bison BuildRequires: bison
BuildRequires: oniguruma-devel BuildRequires: oniguruma-devel
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libtool
BuildRequires: chrpath BuildRequires: chrpath
%ifnarch s390x %ifarch %{valgrind_arches}
BuildRequires: valgrind BuildRequires: valgrind
%endif %endif
BuildRequires: make
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libtool
%description %description
lightweight and flexible command-line JSON processor lightweight and flexible command-line JSON processor
jq is like sed for JSON data you can use it to slice jq is like sed for JSON data you can use it to slice
and filter and map and transform structured data with and filter and map and transform structured data with
the same ease that sed, awk, grep and friends let you the same ease that sed, awk, grep and friends let you
play with text. play with text.
It is written in portable C, and it has zero runtime It is written in portable C, and it has zero runtime
dependencies. dependencies.
jq can mangle the data format that you have into the jq can mangle the data format that you have into the
one that you want with very little effort, and the one that you want with very little effort, and the
program to do so is often shorter and simpler than program to do so is often shorter and simpler than
you'd expect. you'd expect.
%package devel %package devel
Summary: Development files for %{name} Summary: Development files for %{name}
@ -56,7 +54,7 @@ Development files for %{name}
%autosetup -n %{name}-%{version} -p1 %autosetup -n %{name}-%{version} -p1
%build %build
autoreconf -fi autoreconf -if
%configure --disable-static %configure --disable-static
make %{?_smp_mflags} make %{?_smp_mflags}
# Docs already shipped in jq's tarball. # Docs already shipped in jq's tarball.
@ -102,53 +100,52 @@ make check
%changelog %changelog
* Mon Jun 30 2025 Tomas Halman <thalman@redhat.com> - 1.6-11
- Fix CVE-2025-48060 AddressSanitizer: stack-buffer-overflow in jq_fuzz_execute (jv_string_vfmt)
- Resolves: RHEL-92987
* Mon Jun 30 2025 Tomas Halman <thalman@redhat.com> - 1.6-10
- Fix CVE-2024-23337 jq has signed integer overflow in jv.c:jvp_array_write
- Resolves: RHEL-92968
* Fri May 3 2024 Tomas Halman <thalman@redhat.com> - 1.6-9
- Fix SAST findings in jq 1.6
- Resolves: RHEL-37827
* Fri Oct 13 2023 Tomas Halman <thalman@redhat.com> - 1.6-8
- Make jq 1.6 fast
- Resolves: RHEL-5052
* Tue Mar 14 2023 Tomas Halman <thalman@redhat.com> - 1.6-7
- Fix jq segfault when used in threads
- Resolves: rhbz#2092160
* Fri Nov 4 2022 Tomas Halman <thalman@redhat.com> - 1.6-6 * Fri Nov 4 2022 Tomas Halman <thalman@redhat.com> - 1.6-6
- Add mantest to the gating - Add mantest to the gating
- Related: rhbz#2049601 - Related: rhbz#2049594
* Tue Oct 11 2022 Tomas Halman <thalman@redhat.com> - 1.6-5 * Fri Oct 21 2022 Tomas Halman <thalman@redhat.com> - 1.6-13
- Remove rpath from jq binary - jq try/catch stops iteration over items
- Related: rhbz#2049601 Resolves: rhbz#2049594
* Tue Oct 11 2022 Tomas Halman <thalman@redhat.com> - 1.6-4 * Mon Nov 15 2021 Tomas Halman <thalman@redhat.com>
- Fix iterration problem for non decimal string - Strip rpath from jq binary
- Resolves: rhbz#2049601 Related: rhbz#2008983
* Mon Oct 4 2021 Tomas Halman <thalman@redhat.com> * Wed Sep 29 2021 Davide Cavalca <dcavalca@centosproject.org> - 1.6-10
- Fix big integers issue - Backport PR#1752 to fix an integer logic issue
- Resolves: bug#2008717 Resolves: rhbz#2008983
* Mon Oct 4 2021 Tomas Halman <thalman@redhat.com> * Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 1.6-9
- Releasing v1.6 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
- Resolves: bug#1852514 Related: rhbz#1991688
* Wed Aug 11 2021 Tomas Halman <thalman@redhat.com> * Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 1.6-8
- Publishing devel package - Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
- Resolves: bug#1908928
* Sat Aug 11 2018 Troy Dawson <tdawson@redhat.com> * Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-7
- Fix typo: s390 -> s390x - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
- Related: bug#1614611
* Sat Dec 05 2020 Richard W.M. Jones <rjones@redhat.com> - 1.6-6
- Use correct valgrind_arches macro to check for valgrind.
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Thu Nov 08 2018 David Fetter <david@fetter.org> - 1.6-1
- Upstream 1.6.0
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.5-13
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Sun Apr 01 2018 Mamoru TASAKA <mtasaka@fedoraproject.org> - 1.5-12 * Sun Apr 01 2018 Mamoru TASAKA <mtasaka@fedoraproject.org> - 1.5-12
- Rebuild against oniguruma 6.8.1 - Rebuild against oniguruma 6.8.1

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-8
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

View File

@ -1,23 +0,0 @@
summary: Run gating tests
discover:
how: fmf
dist-git-source: true
dist-git-type: centos
prepare:
- how: install
package:
- dnf-plugins-core
- https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
- how: shell
script: /usr/bin/crb enable
- how: install
package:
- jq
- jq-devel
- gcc
- wget
- how: shell
script: dnf config-manager --disable epel*
execute:
how: tmt

View File

@ -1 +0,0 @@
SHA512 (jq-1.6.tar.gz) = f5ae8be558ca2ff15324c378d623106b74bd0823be50835e23548584aa1eb24eb81f8f054693d5d3fe44f157d0735c5f0f40b9f21899ba068f2a11d1345ace19

View File

@ -1,20 +0,0 @@
#!/bin/bash
export LC_ALL=C
stress_jq() {
`which time` -p -f '%e\n' bash -c 'for i in `seq 1 1000` ; do echo '"'"'{"foo":"bar"}'"'"' | jq '"'"'has("bar")'"'"' > /dev/null ; done' 2>&1 | cut -d. -f1
}
FAIL=0
TIME=`stress_jq`
echo -n "Test jqspeed ... "
if [ $TIME -gt 8 ] ; then
echo "failed"
FAIL=1
else
echo "ok"
fi
echo "Runtime: ${TIME}s "
exit $FAIL

View File

@ -1,6 +0,0 @@
summary: Run jq performance/speed test
require:
- jq
- which
- time
test: ./jqspeed.sh

View File

View File

@ -1,5 +0,0 @@
---
standard-inventory-qcow2:
qemu:
m: 2G

View File

@ -1,19 +0,0 @@
#!/bin/sh
FAIL=0
# Test for segfault in multithreaded environment
gcc -o test_segfault test_segfault_with_multithreaded_env.c -lpthread -ljq && \
./test_segfault
RET=$?
echo -n "Test jqsegfault ... "
if [ $RET != 0 ]; then
echo "failed"
FAIL=1
else
echo "ok"
fi
exit $FAIL

View File

@ -1,8 +0,0 @@
summary: Run segfault threads test
require:
- wget
- dnf-utils
- gcc
- jq
- jq-devel
test: ./jqsegfault.sh

View File

@ -1,90 +0,0 @@
#include <stdlib.h>
#include <jq.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int my_jq_parse(jq_state *jq, struct jv_parser *parser)
{
int rv = 0;
jv value;
value = jv_parser_next(parser);
while (jv_is_valid(value)) {
jq_start(jq, value, 0);
jv result;
while (jv_is_valid(result = jq_next(jq))) {
jv dumped = jv_dump_string(result, 0);
const char *str = jv_string_value(dumped);
printf("dumped: %s\n", str);
}
jv_free(result);
value = jv_parser_next(parser);
}
if (jv_invalid_has_msg(jv_copy(value))) {
jv msg = jv_invalid_get_msg(value);
printf("invalid: %s\n", jv_string_value(msg));
jv_free(msg);
rv = 1;
} else {
jv_free(value);
}
return rv;
}
void *run(void *not_used) {
int rv;
jq_state *jq;
const char *prg = ".data";
jq = jq_init();
printf("jq_init jq: %p prg: %s\n", jq, prg);
if (jq_compile(jq, prg) == 0) {
jq_teardown(&jq);
return NULL;
}
printf("compiled\n");
struct jv_parser *parser = jv_parser_new(0);
const char *buf = "{ \"data\": 1 }";
jv_parser_set_buf(parser, buf, strlen(buf), 0);
rv = my_jq_parse(jq, parser);
if (rv != 0) {
printf("my_jq_parse failed!\n");
}
jv_parser_free(parser);
jq_teardown(&jq);
return NULL;
}
#define THREADS 2
/* calling run() twice works fine */
/* calling them in threads causes core-dump */
int main (int argc, char *argv[])
{
pthread_t threads[THREADS];
int createerror;
int a;
memset(&threads, 0, sizeof(threads));
for (a = 0; a < THREADS; ++a) {
// sleep(1); // < if you want to run threads sequentionally
createerror = pthread_create(&threads[a], NULL, run, NULL);
if (createerror) {
printf("create thread error %d\n", a);
}
}
for(a = 0; a < THREADS; ++a) {
if (threads[a] != 0) {
pthread_join(threads[a], NULL);
}
}
return 0;
}

View File

@ -1,27 +0,0 @@
---
- hosts: localhost
roles:
- role: standard-test-source
tags:
- always
- role: standard-test-basic
tags:
- classic
required_packages:
- jq
- gcc
- wget
- jq-devel
- valgrind
- rubygem-rake
tests:
- upstream:
dir: upstream
run: ./jqtests.sh
- segfault:
dir: segfault
run: ./jqsegfault.sh
- performance:
dir: performance
run: ./jqspeed.sh

View File

@ -1,48 +0,0 @@
#!/bin/sh
die () {
echo "$1" >&2
exit 1
}
# If source not found, download it with dnf
if [ ! -d ./source ]; then
# Extract source from srpm
dnf download --source jq && \
rpm2cpio jq*.rpm|cpio -id && \
mkdir source && \
tar -zxf jq-*.tar.gz -C source --strip-components=1
if [ $? != 0 ]; then
echo "Failed to download upstream tests"
exit 1
fi
fi
pushd ./source || die "missing source directory"
rm -f jq tests/*.log 2>/dev/null
ln -s /usr/bin/jq || die "failed to link jq binary"
FAIL=0
# run the tests
# List of tests is taken from Makefile
TESTS="tests/optionaltest tests/mantest tests/jqtest tests/onigtest tests/shtest tests/utf8test tests/base64test"
for t in $TESTS; do
echo -n "Test $t ... "
./${t} >"${t}.log" 2>&1
RET=$?
if [ $RET = 0 ]; then
echo "ok"
else
echo "failed"
echo "-------------------- ${t}.log start -----------------------------"
cat "${t}.log"
echo "-------------------- ${t}.log end -----------------------------"
FAIL=1
fi
done
popd # exit SOURCE_DIR
exit $FAIL

View File

@ -1,11 +0,0 @@
summary: Run jq gating tests
require:
- wget
- dnf-utils
- gcc
- jq
- jq-devel
- valgrind
- diffutils
test: ./jqtests.sh
duration: 30m