round upstream patches
(cherry picked from commit c90fe1b81b387ba3f2cce777ff5c2665cc472e20)
This commit is contained in:
parent
2d9749e1c3
commit
4c3b1a5530
206
backport-Fix-build-with-clang-15.patch
Normal file
206
backport-Fix-build-with-clang-15.patch
Normal file
@ -0,0 +1,206 @@
|
||||
From 6eca65617aacd19f4928acd5766b8dd20eda0b34 Mon Sep 17 00:00:00 2001
|
||||
From: Khem Raj <raj.khem@gmail.com>
|
||||
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 <raj.khem@gmail.com>
|
||||
|
||||
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
|
||||
564
backport-json_tokener_parse_ex-handle-out-of-memory-errors.patch
Normal file
564
backport-json_tokener_parse_ex-handle-out-of-memory-errors.patch
Normal file
@ -0,0 +1,564 @@
|
||||
From 9e6acc9a4eefe9f092aa3a3890a6e5c6ca2d5ed1 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||
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 <err.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
||||
@ -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 <sunhai10@huawei.com> - 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 <zhangrui182@huawei.com> - 0.16-3
|
||||
- backport patch to fix integer overflow
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user