File CVE-2024-53427.patch of Package jq
This is a combined patch consisting of upstream patches:
https://github.com/jqlang/jq/commit/b86ff49f46a4a37e5a8e75a140cb5fd6e1331384
https://github.com/jqlang/jq/commit/a09a4dfd55e6c24d04b35062ccfe4509748b1dd3
which have been slightly tweaked so they apply to the jq 1.7.1 release.
The purpose of the patch is to fix CVE-2024-53427.
Index: jq-1.7.1/src/jv.c
===================================================================
--- jq-1.7.1.orig/src/jv.c
+++ jq-1.7.1/src/jv.c
@@ -206,9 +206,6 @@ enum {
JVP_NUMBER_DECIMAL = 1
};
-#define JV_NUMBER_SIZE_INIT (0)
-#define JV_NUMBER_SIZE_CONVERTED (1)
-
#define JVP_FLAGS_NUMBER_NATIVE JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 0))
#define JVP_FLAGS_NUMBER_LITERAL JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1))
@@ -589,8 +586,17 @@ static jv jvp_literal_number_new(const c
jv_mem_free(n);
return JV_INVALID;
}
+ if (decNumberIsNaN(&n->num_decimal)) {
+ // Reject NaN with payload.
+ if (n->num_decimal.digits > 1 || *n->num_decimal.lsu != 0) {
+ jv_mem_free(n);
+ return JV_INVALID;
+ }
+ jv_mem_free(n);
+ return jv_number(NAN);
+ }
- jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, JV_NUMBER_SIZE_INIT, {&n->refcnt}};
+ jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, {&n->refcnt}};
return r;
}
@@ -698,9 +704,8 @@ double jv_number_value(jv j) {
if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)) {
jvp_literal_number* n = jvp_literal_number_ptr(j);
- if (j.size != JV_NUMBER_SIZE_CONVERTED) {
+ if (isnan(n->num_double)) {
n->num_double = jvp_literal_number_to_double(j);
- j.size = JV_NUMBER_SIZE_CONVERTED;
}
return n->num_double;
@@ -731,7 +736,7 @@ int jvp_number_is_nan(jv n) {
return decNumberIsNaN(pdec);
}
#endif
- return n.u.number != n.u.number;
+ return isnan(n.u.number);
}
int jvp_number_cmp(jv a, jv b) {
Index: jq-1.7.1/tests/jq.test
===================================================================
--- jq-1.7.1.orig/tests/jq.test
+++ jq-1.7.1/tests/jq.test
@@ -1938,11 +1938,17 @@ tojson | fromjson
{"a":nan}
{"a":null}
-# also "nan with payload" #2985
-fromjson | isnan
-"nan1234"
+# NaN with payload is not parsed
+.[] | try (fromjson | isnan) catch .
+["NaN","-NaN","NaN1","NaN10","NaN100","NaN1000","NaN10000","NaN100000"]
true
-
+true
+"Invalid numeric literal at EOF at line 1, column 4 (while parsing 'NaN1')"
+"Invalid numeric literal at EOF at line 1, column 5 (while parsing 'NaN10')"
+"Invalid numeric literal at EOF at line 1, column 6 (while parsing 'NaN100')"
+"Invalid numeric literal at EOF at line 1, column 7 (while parsing 'NaN1000')"
+"Invalid numeric literal at EOF at line 1, column 8 (while parsing 'NaN10000')"
+"Invalid numeric literal at EOF at line 1, column 9 (while parsing 'NaN100000')"
# calling input/0, or debug/0 in a test doesn't crash jq
Index: jq-1.7.1/tests/shtest
===================================================================
--- jq-1.7.1.orig/tests/shtest
+++ jq-1.7.1/tests/shtest
@@ -594,11 +594,6 @@ if ! x=$($JQ -n "1 # foo$cr + 2") || [ "
exit 1
fi
-# CVE-2023-50268: No stack overflow comparing a nan with a large payload
-$VALGRIND $Q $JQ '1 != .' <<\EOF >/dev/null
-Nan4000
-EOF
-
# Allow passing the inline jq script before -- #2919
if ! r=$($JQ --args -rn -- '$ARGS.positional[0]' bar) || [ "$r" != bar ]; then
echo "passing the inline script after -- didn't work"