diff --git a/backport-Fix-build-with-clang-15.patch b/backport-Fix-build-with-clang-15.patch new file mode 100644 index 0000000000000000000000000000000000000000..42ccfa8ba328a01ee59e0135e7328e4e4b269f80 --- /dev/null +++ b/backport-Fix-build-with-clang-15.patch @@ -0,0 +1,206 @@ +From 6eca65617aacd19f4928acd5766b8dd20eda0b34 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Sat, 13 Aug 2022 20:37:03 -0700 +Subject: [PATCH] Fix build with clang-15+ + +Fixes +json_util.c:63:35: error: a function declaration without a prototype is deprecated in all versions of C [-We +rror,-Wstrict-prototypes] +const char *json_util_get_last_err() + ^ + void + +Signed-off-by: Khem Raj + +Conflict:NA +Reference:https://github.com/json-c/json-c/commit/6eca65617aacd19f4928acd5766b8dd20eda0b34 + +--- + json_util.c | 2 +- + tests/test1.c | 6 +++--- + tests/test4.c | 2 +- + tests/test_cast.c | 2 +- + tests/test_charcase.c | 2 +- + tests/test_parse.c | 8 ++++---- + tests/test_printbuf.c | 4 ++-- + tests/test_util_file.c | 6 +++--- + 8 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/json_util.c b/json_util.c +index 952770a..83d9c68 100644 +--- a/json_util.c ++++ b/json_util.c +@@ -60,7 +60,7 @@ static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const + + static char _last_err[256] = ""; + +-const char *json_util_get_last_err() ++const char *json_util_get_last_err(void) + { + if (_last_err[0] == '\0') + return NULL; +diff --git a/tests/test1.c b/tests/test1.c +index befd246..d28811b 100644 +--- a/tests/test1.c ++++ b/tests/test1.c +@@ -61,7 +61,7 @@ static const char *to_json_string(json_object *obj, int flags) + #endif + + json_object *make_array(void); +-json_object *make_array() ++json_object *make_array(void) + { + json_object *my_array; + +@@ -77,7 +77,7 @@ json_object *make_array() + } + + void test_array_del_idx(void); +-void test_array_del_idx() ++void test_array_del_idx(void) + { + int rc; + size_t ii; +@@ -143,7 +143,7 @@ void test_array_del_idx() + } + + void test_array_list_expand_internal(void); +-void test_array_list_expand_internal() ++void test_array_list_expand_internal(void) + { + int rc; + size_t ii; +diff --git a/tests/test4.c b/tests/test4.c +index 749459d..1e136e5 100644 +--- a/tests/test4.c ++++ b/tests/test4.c +@@ -31,7 +31,7 @@ void print_hex(const char *s) + } + + static void test_lot_of_adds(void); +-static void test_lot_of_adds() ++static void test_lot_of_adds(void) + { + int ii; + char key[50]; +diff --git a/tests/test_cast.c b/tests/test_cast.c +index 276b461..02e19ea 100644 +--- a/tests/test_cast.c ++++ b/tests/test_cast.c +@@ -97,7 +97,7 @@ static void getit(struct json_object *new_obj, const char *field) + printf("new_obj.%s json_object_get_double()=%f\n", field, json_object_get_double(o)); + } + +-static void checktype_header() ++static void checktype_header(void) + { + printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s\n", json_type_to_name(json_type_null), + json_type_to_name(json_type_boolean), json_type_to_name(json_type_double), +diff --git a/tests/test_charcase.c b/tests/test_charcase.c +index c6e783e..8ffcb68 100644 +--- a/tests/test_charcase.c ++++ b/tests/test_charcase.c +@@ -22,7 +22,7 @@ int main(int argc, char **argv) + } + + /* make sure only lowercase forms are parsed in strict mode */ +-static void test_case_parse() ++static void test_case_parse(void) + { + struct json_tokener *tok; + json_object *new_obj; +diff --git a/tests/test_parse.c b/tests/test_parse.c +index cdd2d8a..4a8e3d7 100644 +--- a/tests/test_parse.c ++++ b/tests/test_parse.c +@@ -96,7 +96,7 @@ static void single_basic_parse(const char *test_string, int clear_serializer) + if (getenv("TEST_PARSE_CHUNKSIZE") != NULL) + single_incremental_parse(test_string, clear_serializer); + } +-static void test_basic_parse() ++static void test_basic_parse(void) + { + single_basic_parse("\"\003\"", 0); + single_basic_parse("/* hello */\"foo\"", 0); +@@ -199,7 +199,7 @@ static void test_basic_parse() + single_basic_parse("[18446744073709551616]", 1); + } + +-static void test_utf8_parse() ++static void test_utf8_parse(void) + { + // json_tokener_parse doesn't support checking for byte order marks. + // It's the responsibility of the caller to detect and skip a BOM. +@@ -226,7 +226,7 @@ static int clear_serializer(json_object *jso, int flags, json_object *parent_jso + return JSON_C_VISIT_RETURN_CONTINUE; + } + +-static void test_verbose_parse() ++static void test_verbose_parse(void) + { + json_object *new_obj; + enum json_tokener_error error = json_tokener_success; +@@ -566,7 +566,7 @@ struct incremental_step + {NULL, -1, -1, json_tokener_success, 0}, + }; + +-static void test_incremental_parse() ++static void test_incremental_parse(void) + { + json_object *new_obj; + enum json_tokener_error jerr; +diff --git a/tests/test_printbuf.c b/tests/test_printbuf.c +index 2a2ccc0..3b1540f 100644 +--- a/tests/test_printbuf.c ++++ b/tests/test_printbuf.c +@@ -19,7 +19,7 @@ static void test_printbuf_memset_length(void); + #define __func__ __FUNCTION__ + #endif + +-static void test_basic_printbuf_memset() ++static void test_basic_printbuf_memset(void) + { + struct printbuf *pb; + +@@ -32,7 +32,7 @@ static void test_basic_printbuf_memset() + printf("%s: end test\n", __func__); + } + +-static void test_printbuf_memset_length() ++static void test_printbuf_memset_length(void) + { + struct printbuf *pb; + +diff --git a/tests/test_util_file.c b/tests/test_util_file.c +index f3a022e..27a097e 100644 +--- a/tests/test_util_file.c ++++ b/tests/test_util_file.c +@@ -38,7 +38,7 @@ static void test_read_fd_equal(const char *testdir); + #define PATH_MAX 256 + #endif + +-static void test_write_to_file() ++static void test_write_to_file(void) + { + json_object *jso; + +@@ -234,7 +234,7 @@ static void test_read_valid_nested_with_fd(const char *testdir) + close(d); + } + +-static void test_read_nonexistant() ++static void test_read_nonexistant(void) + { + const char *filename = "./not_present.json"; + +@@ -252,7 +252,7 @@ static void test_read_nonexistant() + } + } + +-static void test_read_closed() ++static void test_read_closed(void) + { + // Test reading from a closed fd + int d = open("/dev/null", O_RDONLY, 0); +-- +2.23.0 \ No newline at end of file diff --git a/backport-json_tokener_parse_ex-handle-out-of-memory-errors.patch b/backport-json_tokener_parse_ex-handle-out-of-memory-errors.patch new file mode 100644 index 0000000000000000000000000000000000000000..01adca1c8c4ae7c4e5fbd7a09d2c5cac766b6330 --- /dev/null +++ b/backport-json_tokener_parse_ex-handle-out-of-memory-errors.patch @@ -0,0 +1,564 @@ +From 9e6acc9a4eefe9f092aa3a3890a6e5c6ca2d5ed1 Mon Sep 17 00:00:00 2001 +From: Tobias Stoeckmann +Date: Sun, 20 Mar 2022 17:22:07 +0100 +Subject: [PATCH] json_tokener_parse_ex: handle out of memory errors + +Do not silently truncate values or skip entries if out of memory errors +occur. + +Proof of Concept: + +- Create poc.c, a program which creates an eight megabyte large json + object with key "A" and a lot of "B"s as value, one of them is + UTF-formatted: + +```c + #include + #include + #include + + #include "json.h" + + #define STR_LEN (8 * 1024 * 1024) + #define STR_PREFIX "{ \"A\": \"" + #define STR_SUFFIX "\\u0042\" }" + +int main(void) { + char *str; + struct json_tokener *tok; + struct json_object *obj; + + if ((tok = json_tokener_new()) == NULL) + errx(1, "json_tokener_new"); + + if ((str = malloc(STR_LEN)) == NULL) + err(1, "malloc"); + memset(str, 'B', STR_LEN); + memcpy(str, STR_PREFIX, sizeof(STR_PREFIX) - 1); + memcpy(str + STR_LEN - sizeof(STR_SUFFIX), STR_SUFFIX, sizeof(STR_SUFFIX)); + + obj = json_tokener_parse(str); + free(str); + + printf("%p\n", obj); + if (obj != NULL) { + printf("%.*s\n", 50, json_object_to_json_string(obj)); + json_object_put(obj); + } + + json_tokener_free(tok); + return 0; +} +``` +- Compile and run poc, assuming you have enough free heap space: +``` +gcc $(pkg-config --cflags --libs) -o poc poc.c +./poc +0x559421e15de0 +{ "A": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +``` +- Reduce available heap and run again, which leads to truncation: +``` +ulimit -d 10000 +./poc +0x555a5b453de0 +{ "A": "B" } +``` +- Compile json-c with this change and run with reduced heap again: +``` +ulimit -d 10000 +./poc +(nil) +``` + +The output is limited to 70 characters, i.e. json-c parses the 8 MB +string correctly but the poc does not print all of them to the screen. + +The truncation occurs because the parser tries to add all chars up +to the UTF-8 formatted 'B' at once. Since memory is limited to 10 MB +there is not enough for this operation. The parser does not fail but +continues normally. + +Another possibility is to create a json file close to 2 GB and run a +program on a system with limited amount of RAM, i.e. around 3 GB. But +ulimit restrictions are much easier for proof of concepts. + +Treat memory errors correctly and abort operations. + +Conflict:NA +Reference:https://github.com/json-c/json-c/commit/9e6acc9a4eefe9f092aa3a3890a6e5c6ca2d5ed1 + +--- + json_tokener.c | 145 ++++++++++++++++++++++++++++++++++--------------- + json_tokener.h | 1 + + 2 files changed, 103 insertions(+), 43 deletions(-) + +diff --git a/json_tokener.c b/json_tokener.c +index 0c09b66..af03a85 100644 +--- a/json_tokener.c ++++ b/json_tokener.c +@@ -103,6 +103,7 @@ static const char *json_tokener_errors[] = { + "success", + "continue", + "nesting too deep", ++ "out of memory", + "unexpected end of data", + "unexpected character", + "null expected", +@@ -284,11 +285,24 @@ struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokene + + /* ADVANCE_CHAR() macro: + * Increments str & tok->char_offset. +- * For convenience of existing conditionals, returns the old value of c (0 on eof) ++ * For convenience of existing conditionals, returns the old value of c (0 on eof). + * Implicit inputs: c var + */ + #define ADVANCE_CHAR(str, tok) (++(str), ((tok)->char_offset)++, c) + ++/* printbuf_memappend_checked(p, s, l) macro: ++ * Add string s of length l to printbuffer p. ++ * If operation fails abort parse operation with memory error. ++ */ ++#define printbuf_memappend_checked(p, s, l) \ ++ do { \ ++ if (printbuf_memappend((p), (s), (l)) < 0) \ ++ { \ ++ tok->err = json_tokener_error_memory; \ ++ goto out; \ ++ } \ ++ } while (0) ++ + /* End optimization macro defs */ + + struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len) +@@ -336,7 +350,11 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + char *tmplocale; + tmplocale = setlocale(LC_NUMERIC, NULL); + if (tmplocale) ++ { + oldlocale = strdup(tmplocale); ++ if (oldlocale == NULL) ++ return NULL; ++ } + setlocale(LC_NUMERIC, "C"); + } + #endif +@@ -358,7 +376,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) + { + printbuf_reset(tok->pb); +- printbuf_memappend_fast(tok->pb, &c, 1); ++ printbuf_memappend_checked(tok->pb, &c, 1); + state = json_tokener_state_comment_start; + } + else +@@ -376,14 +394,20 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + saved_state = json_tokener_state_object_field_start; + current = json_object_new_object(); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + break; + case '[': + state = json_tokener_state_eatws; + saved_state = json_tokener_state_array; + current = json_object_new_array(); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + break; + case 'I': + case 'i': +@@ -486,7 +510,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + } + current = json_object_new_double(is_negative ? -INFINITY : INFINITY); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; +@@ -496,7 +523,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + int size; + int size_nan; +- printbuf_memappend_fast(tok->pb, &c, 1); ++ printbuf_memappend_checked(tok->pb, &c, 1); + size = json_min(tok->st_pos + 1, json_null_str_len); + size_nan = json_min(tok->st_pos + 1, json_nan_str_len); + if ((!(tok->flags & JSON_TOKENER_STRICT) && +@@ -519,7 +546,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + current = json_object_new_double(NAN); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; +@@ -548,7 +578,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + tok->err = json_tokener_error_parse_comment; + goto out; + } +- printbuf_memappend_fast(tok->pb, &c, 1); ++ printbuf_memappend_checked(tok->pb, &c, 1); + break; + + case json_tokener_state_comment: +@@ -559,12 +589,12 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { +- printbuf_memappend_fast(tok->pb, case_start, +- str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, ++ str - case_start); + goto out; + } + } +- printbuf_memappend_fast(tok->pb, case_start, 1 + str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start); + state = json_tokener_state_comment_end; + } + break; +@@ -577,19 +607,19 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { +- printbuf_memappend_fast(tok->pb, case_start, +- str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, ++ str - case_start); + goto out; + } + } +- printbuf_memappend_fast(tok->pb, case_start, str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, str - case_start); + MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); + state = json_tokener_state_eatws; + } + break; + + case json_tokener_state_comment_end: +- printbuf_memappend_fast(tok->pb, &c, 1); ++ printbuf_memappend_checked(tok->pb, &c, 1); + if (c == '/') + { + MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); +@@ -609,28 +639,31 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + if (c == tok->quote_char) + { +- printbuf_memappend_fast(tok->pb, case_start, +- str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, ++ str - case_start); + current = + json_object_new_string_len(tok->pb->buf, tok->pb->bpos); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + break; + } + else if (c == '\\') + { +- printbuf_memappend_fast(tok->pb, case_start, +- str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, ++ str - case_start); + saved_state = json_tokener_state_string; + state = json_tokener_state_string_escape; + break; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { +- printbuf_memappend_fast(tok->pb, case_start, +- str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, ++ str - case_start); + goto out; + } + } +@@ -643,7 +676,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + case '"': + case '\\': + case '/': +- printbuf_memappend_fast(tok->pb, &c, 1); ++ printbuf_memappend_checked(tok->pb, &c, 1); + state = saved_state; + break; + case 'b': +@@ -652,15 +685,15 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + case 't': + case 'f': + if (c == 'b') +- printbuf_memappend_fast(tok->pb, "\b", 1); ++ printbuf_memappend_checked(tok->pb, "\b", 1); + else if (c == 'n') +- printbuf_memappend_fast(tok->pb, "\n", 1); ++ printbuf_memappend_checked(tok->pb, "\n", 1); + else if (c == 'r') +- printbuf_memappend_fast(tok->pb, "\r", 1); ++ printbuf_memappend_checked(tok->pb, "\r", 1); + else if (c == 't') +- printbuf_memappend_fast(tok->pb, "\t", 1); ++ printbuf_memappend_checked(tok->pb, "\t", 1); + else if (c == 'f') +- printbuf_memappend_fast(tok->pb, "\f", 1); ++ printbuf_memappend_checked(tok->pb, "\f", 1); + state = saved_state; + break; + case 'u': +@@ -720,8 +753,8 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + /* High surrogate was not followed by a low surrogate + * Replace the high and process the rest normally + */ +- printbuf_memappend_fast(tok->pb, +- (char *)utf8_replacement_char, 3); ++ printbuf_memappend_checked(tok->pb, ++ (char *)utf8_replacement_char, 3); + } + tok->high_surrogate = 0; + } +@@ -730,14 +763,14 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + unsigned char unescaped_utf[1]; + unescaped_utf[0] = tok->ucs_char; +- printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 1); ++ printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1); + } + else if (tok->ucs_char < 0x800) + { + unsigned char unescaped_utf[2]; + unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6); + unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f); +- printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 2); ++ printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2); + } + else if (IS_HIGH_SURROGATE(tok->ucs_char)) + { +@@ -763,7 +796,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + else if (IS_LOW_SURROGATE(tok->ucs_char)) + { + /* Got a low surrogate not preceded by a high */ +- printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); ++ printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3); + } + else if (tok->ucs_char < 0x10000) + { +@@ -771,7 +804,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12); + unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); + unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f); +- printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 3); ++ printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3); + } + else if (tok->ucs_char < 0x110000) + { +@@ -780,12 +813,12 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f); + unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); + unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f); +- printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 4); ++ printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4); + } + else + { + /* Don't know what we got--insert the replacement char */ +- printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); ++ printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3); + } + state = saved_state; // i.e. _state_string or _state_object_field + } +@@ -800,7 +833,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + * it. Put a replacement char in for the high surrogate + * and pop back up to _state_string or _state_object_field. + */ +- printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); ++ printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3); + tok->high_surrogate = 0; + tok->ucs_char = 0; + tok->st_pos = 0; +@@ -819,7 +852,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + * Put a replacement char in for the high surrogate + * and handle the escape sequence normally. + */ +- printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); ++ printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3); + tok->high_surrogate = 0; + tok->ucs_char = 0; + tok->st_pos = 0; +@@ -834,7 +867,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + case json_tokener_state_boolean: + { + int size1, size2; +- printbuf_memappend_fast(tok->pb, &c, 1); ++ printbuf_memappend_checked(tok->pb, &c, 1); + size1 = json_min(tok->st_pos + 1, json_true_str_len); + size2 = json_min(tok->st_pos + 1, json_false_str_len); + if ((!(tok->flags & JSON_TOKENER_STRICT) && +@@ -845,7 +878,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + current = json_object_new_boolean(1); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; +@@ -859,7 +895,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + current = json_object_new_boolean(0); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; +@@ -939,7 +978,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { +- printbuf_memappend_fast(tok->pb, case_start, case_len); ++ printbuf_memappend_checked(tok->pb, case_start, case_len); + goto out; + } + } +@@ -948,7 +987,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + it might have been intended to be, and return a potentially + more understandable error right away. + However, if we're at the top-level, use the number as-is +- because c can be part of a new object to parse on the ++ because c can be part of a new object to parse on the + next call to json_tokener_parse(). + */ + if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' && +@@ -958,7 +997,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + goto out; + } + if (case_len > 0) +- printbuf_memappend_fast(tok->pb, case_start, case_len); ++ printbuf_memappend_checked(tok->pb, case_start, case_len); + + // Check for -Infinity + if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I')) +@@ -993,7 +1032,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + } + current = json_object_new_int64(num64); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + } + else if (!tok->is_double && tok->pb->buf[0] != '-' && + json_parse_uint64(tok->pb->buf, &numuint64) == 0) +@@ -1009,13 +1051,19 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + num64 = (uint64_t)numuint64; + current = json_object_new_int64(num64); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + } + else + { + current = json_object_new_uint64(numuint64); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + } + } + else if (tok->is_double && +@@ -1024,7 +1072,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + current = json_object_new_double_s(numd, tok->pb->buf); + if (current == NULL) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + } + else + { +@@ -1069,7 +1120,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + + case json_tokener_state_array_add: + if (json_object_array_add(current, obj) != 0) ++ { ++ tok->err = json_tokener_error_memory; + goto out; ++ } + saved_state = json_tokener_state_array_sep; + state = json_tokener_state_eatws; + goto redo_char; +@@ -1129,25 +1183,30 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * + { + if (c == tok->quote_char) + { +- printbuf_memappend_fast(tok->pb, case_start, +- str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, ++ str - case_start); + obj_field_name = strdup(tok->pb->buf); ++ if (obj_field_name == NULL) ++ { ++ tok->err = json_tokener_error_memory; ++ goto out; ++ } + saved_state = json_tokener_state_object_field_end; + state = json_tokener_state_eatws; + break; + } + else if (c == '\\') + { +- printbuf_memappend_fast(tok->pb, case_start, +- str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, ++ str - case_start); + saved_state = json_tokener_state_object_field; + state = json_tokener_state_string_escape; + break; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) + { +- printbuf_memappend_fast(tok->pb, case_start, +- str - case_start); ++ printbuf_memappend_checked(tok->pb, case_start, ++ str - case_start); + goto out; + } + } +diff --git a/json_tokener.h b/json_tokener.h +index a07e12c..c1502e8 100644 +--- a/json_tokener.h ++++ b/json_tokener.h +@@ -28,6 +28,7 @@ enum json_tokener_error + json_tokener_success, + json_tokener_continue, + json_tokener_error_depth, ++ json_tokener_error_memory, + json_tokener_error_parse_eof, + json_tokener_error_parse_unexpected, + json_tokener_error_parse_null, +-- +2.23.0 \ No newline at end of file diff --git a/json-c.spec b/json-c.spec index 0014398835735550e57078ab598bb92d493df3c0..10f6e694d5b2607f2afa2241dbacc8a1c51d20ea 100644 --- a/json-c.spec +++ b/json-c.spec @@ -6,7 +6,7 @@ Name: json-c Version: 0.16 -Release: 3 +Release: 4 Summary: JSON implementation in C License: MIT @@ -20,6 +20,9 @@ Patch6002: backport-Fix-memory-leak-with-emtpy-strings-in-json_object_set_s Patch6003: backport-json_object_from_fd_ex-fail-if-file-is-too-large.patch Patch6004: backport-Explicitly-check-for-integer-overflow-when-parsing.patch +Patch6005: backport-Fix-build-with-clang-15.patch +Patch6006: backport-json_tokener_parse_ex-handle-out-of-memory-errors.patch + %description JSON-C implements a reference counting object model that allows you to easily construct JSON objects in C, output them as JSON formatted @@ -106,6 +109,10 @@ end %doc %{_pkgdocdir} %changelog +* Mon Sep 04 2023 sunhai - 0.16-4 +- backport patch to Fix build with clang-15+ +- backport patch to Fix json_tokener_parse_ex: handle out of memory errors + * Fri Apr 21 2023 zhangrui - 0.16-3 - backport patch to fix integer overflow