From 60e95a663157ff2b3917b4751e23c80d404424e9 Mon Sep 17 00:00:00 2001 From: Emanuele Torre Date: Fri, 15 Mar 2024 14:56:45 +0100 Subject: [PATCH] builtin.c: fix signed integer overflow in jv2tm jv2tm now properly clamps large number values to a signed 32-bit integer and rejects nan. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65885 --- src/builtin.c | 11 +++++++++-- tests/jq.test | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/builtin.c b/src/builtin.c index 5e31795c2c..55512da9df 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -1464,13 +1464,20 @@ static jv f_strptime(jq_state *jq, jv a, jv b) { #define TO_TM_FIELD(t, j, i) \ do { \ jv n = jv_array_get(jv_copy(j), (i)); \ - if (jv_get_kind(n) != (JV_KIND_NUMBER)) { \ + if (jv_get_kind(n) != JV_KIND_NUMBER || \ + jvp_number_is_nan(n)) { \ jv_free(n); \ jv_free(j); \ return 0; \ } \ - t = jv_number_value(n); \ + double dint = jv_number_value(n); \ jv_free(n); \ + if (dint < INT_MIN) \ + (t) = INT_MIN; \ + else if (dint > INT_MAX) \ + (t) = INT_MAX; \ + else \ + (t) = (int)dint; \ } while (0) static int jv2tm(jv a, struct tm *tm) { diff --git a/tests/jq.test b/tests/jq.test index 463161c703..58c2c77d89 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -1585,6 +1585,12 @@ try mktime catch . ["a",1,2,3,4,5,6,7] "mktime requires parsed datetime inputs" +# oss-fuzz #65885: non-int32 values are accepted and cause UB overflows +.[] | try ["OK", strftime("%Y-%m-%dT%H:%M:%SZ")] catch ["KO", .] +[[1e31],[NaN]] +["KO","strftime/1 requires parsed datetime inputs"] +["KO","strftime/1 requires parsed datetime inputs"] + # oss-fuzz #67403: non-string argument with number input fails assert try ["OK", strftime([])] catch ["KO", .] 0