diff options
author | Mattias Wadman <mattias.wadman@gmail.com> | 2023-07-02 16:48:07 +0200 |
---|---|---|
committer | Nico Williams <nico@cryptonector.com> | 2023-07-25 13:38:41 -0500 |
commit | a949745059ee61366a5d880c3b18d5d4db6524eb (patch) | |
tree | 4fb0a93cf93e99d098eae5f8eff37ef6c92b049d /src | |
parent | a29ac81de117a6bad625bc4ff75bbb395a58f7d6 (diff) |
implode: Better invalid input validation and handling
Error on non-number and nan codepoint, would asserd before
Replace negative codepoint and surrogate range with unicode replacement character, would assert before
Fixes #1160
Diffstat (limited to 'src')
-rw-r--r-- | src/builtin.c | 23 | ||||
-rw-r--r-- | src/jv.c | 3 | ||||
-rw-r--r-- | src/jv.h | 1 | ||||
-rw-r--r-- | src/jv_type_private.h | 1 |
4 files changed, 25 insertions, 3 deletions
diff --git a/src/builtin.c b/src/builtin.c index 3e99c376..8e1de2b5 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -1201,7 +1201,28 @@ static jv f_string_implode(jq_state *jq, jv a) { if (jv_get_kind(a) != JV_KIND_ARRAY) { return ret_error(a, jv_string("implode input must be an array")); } - return jv_string_implode(a); + + int len = jv_array_length(jv_copy(a)); + jv s = jv_string_empty(len); + + for (int i = 0; i < len; i++) { + jv n = jv_array_get(jv_copy(a), i); + if (jv_get_kind(n) != JV_KIND_NUMBER || jvp_number_is_nan(n)) { + jv_free(a); + jv_free(s); + return type_error(n, "can't be imploded, unicode codepoint needs to be numeric"); + } + + int nv = jv_number_value(n); + jv_free(n); + // outside codepoint range or in utf16 surrogate pair range + if (nv < 0 || nv > 0x10FFFF || (nv >= 0xD800 && nv <= 0xDFFF)) + nv = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER + s = jv_string_append_codepoint(s, nv); + } + + jv_free(a); + return s; } static jv f_setpath(jq_state *jq, jv a, jv b, jv c) { return jv_setpath(a, b, c); } @@ -1368,7 +1368,8 @@ jv jv_string_implode(jv j) { assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); int nv = jv_number_value(n); jv_free(n); - if (nv > 0x10FFFF) + // outside codepoint range or in utf16 surrogate pair range + if (nv < 0 || nv > 0x10FFFF || (nv >= 0xD800 && nv <= 0xDFFF)) nv = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER s = jv_string_append_codepoint(s, nv); } @@ -63,6 +63,7 @@ jv jv_number(double); jv jv_number_with_literal(const char*); double jv_number_value(jv); int jv_is_integer(jv); +int jvp_number_is_nan(jv); int jv_number_has_literal(jv n); const char* jv_number_get_literal(jv); diff --git a/src/jv_type_private.h b/src/jv_type_private.h index 5996282b..a25254dc 100644 --- a/src/jv_type_private.h +++ b/src/jv_type_private.h @@ -2,6 +2,5 @@ #define JV_TYPE_PRIVATE int jvp_number_cmp(jv, jv); -int jvp_number_is_nan(jv); #endif //JV_TYPE_PRIVATE |