Compare commits
10 Commits
9caac7d6ea
...
77bb97ce3a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77bb97ce3a | ||
|
|
4c3b1a5530 | ||
|
|
2d9749e1c3 | ||
|
|
a4bc92ebbf | ||
|
|
7b6bb75baa | ||
|
|
96f547b8d7 | ||
|
|
c15a210cdd | ||
|
|
68742ceb6a | ||
|
|
304aaf6e3b | ||
|
|
ce7b82545f |
@ -0,0 +1,31 @@
|
||||
From 16208fc01afcd742fd5e6736f52849ad2ec03e8f Mon Sep 17 00:00:00 2001
|
||||
From: Eric Haszlakiewicz <erh+git@nimenees.com>
|
||||
Date: Sun, 24 Jul 2022 18:59:26 +0000
|
||||
Subject: [PATCH] Add test to check for the memory leak mentioned in issue #781
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/json-c/json-c/commit/16208fc01afcd742fd5e6736f52849ad2ec03e8f
|
||||
|
||||
---
|
||||
tests/test_set_value.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/tests/test_set_value.c b/tests/test_set_value.c
|
||||
index f51a2a5b67..a8ebbfec79 100644
|
||||
--- a/tests/test_set_value.c
|
||||
+++ b/tests/test_set_value.c
|
||||
@@ -71,6 +71,14 @@ int main(int argc, char **argv)
|
||||
json_object_set_string(tmp, SHORT);
|
||||
assert(strcmp(json_object_get_string(tmp), SHORT) == 0);
|
||||
assert(strcmp(json_object_to_json_string(tmp), "\"" SHORT "\"") == 0);
|
||||
+
|
||||
+ // Set an empty string a couple times to try to trigger
|
||||
+ // a case that used to leak memory.
|
||||
+ json_object_set_string(tmp, "");
|
||||
+ json_object_set_string(tmp, HUGE);
|
||||
+ json_object_set_string(tmp, "");
|
||||
+ json_object_set_string(tmp, HUGE);
|
||||
+
|
||||
json_object_put(tmp);
|
||||
printf("STRING PASSED\n");
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
From d6f46ae104871360f84695737864870c97adfd14 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Haszlakiewicz <erh+git@nimenees.com>
|
||||
Date: Sun, 30 Oct 2022 19:29:15 +0000
|
||||
Subject: [PATCH] Explicitly check for integer overflow/underflow when
|
||||
parsing integers with JSON_TOKENER_STRICT.
|
||||
|
||||
Reference:https://github.com/json-c/json-c/commit/d6f46ae104871360f84695737864870c97adfd14
|
||||
Conflict:Ignore changes in the ChangeLog and test because the pre-feature patch is not merged
|
||||
|
||||
---
|
||||
json_tokener.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/json_tokener.c b/json_tokener.c
|
||||
index 0c09b66..1feee65 100644
|
||||
--- a/json_tokener.c
|
||||
+++ b/json_tokener.c
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "math_compat.h"
|
||||
#include <assert.h>
|
||||
+#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
@@ -991,6 +992,11 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
|
||||
if (!tok->is_double && tok->pb->buf[0] == '-' &&
|
||||
json_parse_int64(tok->pb->buf, &num64) == 0)
|
||||
{
|
||||
+ if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
|
||||
+ {
|
||||
+ tok->err = json_tokener_error_parse_number;
|
||||
+ goto out;
|
||||
+ }
|
||||
current = json_object_new_int64(num64);
|
||||
if (current == NULL)
|
||||
goto out;
|
||||
@@ -998,6 +1004,11 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
|
||||
else if (!tok->is_double && tok->pb->buf[0] != '-' &&
|
||||
json_parse_uint64(tok->pb->buf, &numuint64) == 0)
|
||||
{
|
||||
+ if(errno==ERANGE&&(tok->flags & JSON_TOKENER_STRICT))
|
||||
+ {
|
||||
+ tok->err=json_tokener_error_parse_number;
|
||||
+ goto out;
|
||||
+ }
|
||||
if (numuint64 && tok->pb->buf[0] == '0' &&
|
||||
(tok->flags & JSON_TOKENER_STRICT))
|
||||
{
|
||||
--
|
||||
2.27.0
|
||||
|
||||
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
|
||||
@ -0,0 +1,67 @@
|
||||
From 213bb5caa11ed2182848d86c86f8e9ab4c75642a Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Danzberger <daniel@dd-wrt.com>
|
||||
Date: Sun, 24 Jul 2022 18:46:03 +0200
|
||||
Subject: [PATCH] Fix memory leak with emtpy strings in json_object_set_string
|
||||
|
||||
When a json string object is updated with a bigger string, a new
|
||||
malloc'ed buffer is used to store the new string and it's size is made
|
||||
negative to indicate that an external buffer is in use.
|
||||
|
||||
When that same json string object get's updated again with an empty
|
||||
stirng (size = 0), the new external malloc'ed buffer is still used.
|
||||
But the fact that the new size value is not negative removes the
|
||||
indicator that the externally malloc'ed buffer is used.
|
||||
|
||||
This becomes a problem when the object get's updated again with any
|
||||
other string, because a new buffer will be malloced and linked to the
|
||||
object while to old one won't be free'd.
|
||||
|
||||
This causes a memory leak when updating a json string with
|
||||
json_object_set_stirng() which has previously been updated
|
||||
with an empty string.
|
||||
|
||||
Example:
|
||||
--
|
||||
obj = json_object_new_string("data");
|
||||
json_object_set_string(obj, "more data");
|
||||
json_object_set_string(obj, "");
|
||||
json_object_set_string(obj, "other data"); /* leaks */
|
||||
--
|
||||
|
||||
This commit fixes the issue by free'ing the external buffer when an
|
||||
empty string is set and use the internal one again.
|
||||
|
||||
Signed-off-by: Daniel Danzberger <daniel@dd-wrt.com>
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/json-c/json-c/commit/213bb5caa11ed2182848d86c86f8e9ab4c75642a
|
||||
---
|
||||
json_object.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/json_object.c b/json_object.c
|
||||
index e52ca4071a..581b1e2748 100644
|
||||
--- a/json_object.c
|
||||
+++ b/json_object.c
|
||||
@@ -1323,11 +1323,18 @@ static int _json_object_set_string_len(json_object *jso, const char *s, size_t l
|
||||
// length as int, cap length at INT_MAX.
|
||||
return 0;
|
||||
|
||||
- dstbuf = get_string_component_mutable(jso);
|
||||
curlen = JC_STRING(jso)->len;
|
||||
- if (curlen < 0)
|
||||
- curlen = -curlen;
|
||||
+ if (curlen < 0) {
|
||||
+ if (len == 0) {
|
||||
+ free(JC_STRING(jso)->c_string.pdata);
|
||||
+ JC_STRING(jso)->len = curlen = 0;
|
||||
+ } else {
|
||||
+ curlen = -curlen;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
newlen = len;
|
||||
+ dstbuf = get_string_component_mutable(jso);
|
||||
|
||||
if ((ssize_t)len > curlen)
|
||||
{
|
||||
@ -1,48 +0,0 @@
|
||||
From 296db618e9d1862aea788e90e751b4999db41a2a Mon Sep 17 00:00:00 2001
|
||||
From: Even Rouault <even.rouault@spatialys.com>
|
||||
Date: Wed, 12 Jan 2022 23:43:03 +0100
|
||||
Subject: [PATCH] json_escape_str(): avoid harmless unsigned integer overflow
|
||||
|
||||
Current behaviour is perfectly valid, since wrap-over upon overflow is
|
||||
well defined behaviour for unsigned types, but it is nevertheless nice to be
|
||||
able to build with -fsanitize=undefined,unsigned-integer-overflow
|
||||
|
||||
There is no significant effect on the generated assembly as can be seen
|
||||
on the diff of objdump -d output on a optimized build (the compiler
|
||||
just decided to switch the order of a comparison):
|
||||
|
||||
@@ -135,8 +135,8 @@
|
||||
1d0: 0f 84 70 ff ff ff je 146 <json_escape_str+0x146>
|
||||
1d6: 4c 3b 24 24 cmp (%rsp),%r12
|
||||
1da: 0f 85 2d ff ff ff jne 10d <json_escape_str+0x10d>
|
||||
- 1e0: 49 39 f4 cmp %rsi,%r12
|
||||
- 1e3: 0f 87 b7 00 00 00 ja 2a0 <json_escape_str+0x2a0>
|
||||
+ 1e0: 4c 39 e6 cmp %r12,%rsi
|
||||
+ 1e3: 0f 82 b7 00 00 00 jb 2a0 <json_escape_str+0x2a0>
|
||||
1e9: 48 8b 44 24 18 mov 0x18(%rsp),%rax
|
||||
1ee: 64 48 33 04 25 28 00 xor %fs:0x28,%rax
|
||||
1f5: 00 00
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/json-c/json-c/commit/296db618e9d1862aea788e90e751b4999db41a2a
|
||||
---
|
||||
json_object.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/json_object.c b/json_object.c
|
||||
index 9198257..3216941 100644
|
||||
--- a/json_object.c
|
||||
+++ b/json_object.c
|
||||
@@ -216,8 +216,9 @@ static int json_escape_str(struct printbuf *pb, const char *str, size_t len, int
|
||||
{
|
||||
int pos = 0, start_offset = 0;
|
||||
unsigned char c;
|
||||
- while (len--)
|
||||
+ while (len)
|
||||
{
|
||||
+ --len;
|
||||
c = str[pos];
|
||||
switch (c)
|
||||
{
|
||||
--
|
||||
2.27.0
|
||||
111
backport-json_object_from_fd_ex-fail-if-file-is-too-large.patch
Normal file
111
backport-json_object_from_fd_ex-fail-if-file-is-too-large.patch
Normal file
@ -0,0 +1,111 @@
|
||||
From 5accae04bbc727fd447c2db4c1c541a4142bd4a0 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||
Date: Sun, 20 Mar 2022 13:17:37 +0100
|
||||
Subject: [PATCH] json_object_from_fd_ex: fail if file is too large
|
||||
|
||||
If the input file is too large to fit into a printbuf then return an
|
||||
error value instead of silently truncating the parsed content.
|
||||
|
||||
This introduces errno handling into printbuf to distinguish between an
|
||||
input file being too large and running out of memory.
|
||||
|
||||
Conflict:tests/test_util_file.expected,0.16 version has merge.
|
||||
Reference:https://github.com/json-c/json-c/commit/5accae04bbc727fd447c2db4c1c541a4142bd4a0
|
||||
---
|
||||
json_util.c | 13 ++++++++++---
|
||||
printbuf.c | 14 +++++++++++++-
|
||||
2 files changed, 23 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/json_util.c b/json_util.c
|
||||
index 3e6a6c681b..e1c05c5cfd 100644
|
||||
--- a/json_util.c
|
||||
+++ b/json_util.c
|
||||
@@ -101,15 +101,22 @@ struct json_object *json_object_from_fd_ex(int fd, int in_depth)
|
||||
if (!tok)
|
||||
{
|
||||
_json_c_set_last_err(
|
||||
- "json_object_from_fd_ex: unable to allocate json_tokener(depth=%d): %s\n", depth,
|
||||
- strerror(errno));
|
||||
+ "json_object_from_fd_ex: unable to allocate json_tokener(depth=%d): %s\n",
|
||||
+ depth, strerror(errno));
|
||||
printbuf_free(pb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0)
|
||||
{
|
||||
- printbuf_memappend(pb, buf, ret);
|
||||
+ if (printbuf_memappend(pb, buf, ret) < 0)
|
||||
+ {
|
||||
+ _json_c_set_last_err("json_object_from_fd_ex: error reading fd %d: %s\n",
|
||||
+ fd, strerror(errno));
|
||||
+ json_tokener_free(tok);
|
||||
+ printbuf_free(pb);
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
if (ret < 0)
|
||||
{
|
||||
diff --git a/printbuf.c b/printbuf.c
|
||||
index a08f7b1582..12d3b3319d 100644
|
||||
--- a/printbuf.c
|
||||
+++ b/printbuf.c
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
+#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -56,6 +57,8 @@ struct printbuf *printbuf_new(void)
|
||||
*
|
||||
* If the current size is large enough, nothing is changed.
|
||||
*
|
||||
+ * If extension failed, errno is set to indicate the error.
|
||||
+ *
|
||||
* Note: this does not check the available space! The caller
|
||||
* is responsible for performing those calculations.
|
||||
*/
|
||||
@@ -68,7 +71,10 @@ static int printbuf_extend(struct printbuf *p, int min_size)
|
||||
return 0;
|
||||
/* Prevent signed integer overflows with large buffers. */
|
||||
if (min_size > INT_MAX - 8)
|
||||
+ {
|
||||
+ errno = EFBIG;
|
||||
return -1;
|
||||
+ }
|
||||
if (p->size > INT_MAX / 2)
|
||||
new_size = min_size + 8;
|
||||
else {
|
||||
@@ -77,7 +83,7 @@ static int printbuf_extend(struct printbuf *p, int min_size)
|
||||
new_size = min_size + 8;
|
||||
}
|
||||
#ifdef PRINTBUF_DEBUG
|
||||
- MC_DEBUG("printbuf_memappend: realloc "
|
||||
+ MC_DEBUG("printbuf_extend: realloc "
|
||||
"bpos=%d min_size=%d old_size=%d new_size=%d\n",
|
||||
p->bpos, min_size, p->size, new_size);
|
||||
#endif /* PRINTBUF_DEBUG */
|
||||
@@ -92,7 +98,10 @@ int printbuf_memappend(struct printbuf *p, const char *buf, int size)
|
||||
{
|
||||
/* Prevent signed integer overflows with large buffers. */
|
||||
if (size < 0 || size > INT_MAX - p->bpos - 1)
|
||||
+ {
|
||||
+ errno = EFBIG;
|
||||
return -1;
|
||||
+ }
|
||||
if (p->size <= p->bpos + size + 1)
|
||||
{
|
||||
if (printbuf_extend(p, p->bpos + size + 1) < 0)
|
||||
@@ -112,7 +121,10 @@ int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
|
||||
offset = pb->bpos;
|
||||
/* Prevent signed integer overflows with large buffers. */
|
||||
if (len < 0 || offset < -1 || len > INT_MAX - offset)
|
||||
+ {
|
||||
+ errno = EFBIG;
|
||||
return -1;
|
||||
+ }
|
||||
size_needed = offset + len;
|
||||
if (pb->size < size_needed)
|
||||
{
|
||||
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
|
||||
Binary file not shown.
BIN
json-c-0.16-20220414.tar.gz
Normal file
BIN
json-c-0.16-20220414.tar.gz
Normal file
Binary file not shown.
46
json-c.spec
46
json-c.spec
@ -1,11 +1,11 @@
|
||||
%{!?_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}}
|
||||
|
||||
%global so_ver 5
|
||||
%global reldate 20200726
|
||||
%global reldate 20220414
|
||||
|
||||
|
||||
Name: json-c
|
||||
Version: 0.15
|
||||
Version: 0.16
|
||||
Release: 4
|
||||
Summary: JSON implementation in C
|
||||
|
||||
@ -15,6 +15,14 @@ Source0: %{url}/archive/%{name}-%{version}-%{reldate}.tar.gz
|
||||
|
||||
BuildRequires: cmake gcc ninja-build
|
||||
|
||||
Patch6001: backport-Add-test-to-check-for-the-memory-leak-mentioned-in-issue-781.patch
|
||||
Patch6002: backport-Fix-memory-leak-with-emtpy-strings-in-json_object_set_string.patch
|
||||
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
|
||||
@ -27,8 +35,6 @@ Summary: Development files for %{name}
|
||||
|
||||
Requires: %{name}%{?_isa} == %{version}-%{release}
|
||||
|
||||
Patch6001: backport-json-escape-str-avoid-harmless-unsigned-integer-overflow.patch
|
||||
|
||||
%description devel
|
||||
This package contains libraries and header files for
|
||||
developing applications that use %{name}.
|
||||
@ -69,19 +75,24 @@ doxygen -s -u doc/Doxyfile.in
|
||||
%{!?__cmake_in_source_build:-B "%{_vpath_builddir}"} \
|
||||
|
||||
%__cmake --build "%{_vpath_builddir}" %{?_smp_mflags} --verbose --target all doc
|
||||
#%cmake_build
|
||||
|
||||
%check
|
||||
%ninja_test -C %{_vpath_builddir}
|
||||
|
||||
%install
|
||||
#%cmake_install
|
||||
DESTDIR="%{buildroot}" %__cmake --install "%{_vpath_builddir}"
|
||||
|
||||
|
||||
mkdir -p %{buildroot}%{_pkgdocdir}
|
||||
hardlink -cfv %{buildroot}%{_pkgdocdir}
|
||||
|
||||
%pretrans devel -p <lua>
|
||||
path = "%{_includedir}/%{name}"
|
||||
st = posix.stat(path)
|
||||
if st and st.type == "link" then
|
||||
os.remove(path)
|
||||
end
|
||||
|
||||
%ldconfig_scriptlets
|
||||
|
||||
%files
|
||||
@ -89,7 +100,7 @@ hardlink -cfv %{buildroot}%{_pkgdocdir}
|
||||
%{_libdir}/lib%{name}.so.%{so_ver}*
|
||||
|
||||
%files devel
|
||||
%{_includedir}/%{name}/
|
||||
%{_includedir}/%{name}
|
||||
%{_libdir}/cmake/%{name}
|
||||
%{_libdir}/lib%{name}.so
|
||||
%{_libdir}/pkgconfig/%{name}.pc
|
||||
@ -98,6 +109,27 @@ hardlink -cfv %{buildroot}%{_pkgdocdir}
|
||||
%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
|
||||
|
||||
* Mon Nov 14 2022 mengkanglai <mengkanglai2@huawei.com> - 0.16-2
|
||||
- add backport-Add-test-to-check-for-the-memory-leak-mentioned-in-issue-781.patch
|
||||
- add backport-Fix-memory-leak-with-emtpy-strings-in-json_object_set_string.patch
|
||||
- add backport-json_object_from_fd_ex-fail-if-file-is-too-large.patch
|
||||
|
||||
* Sat Nov 5 2022 zhangrui <zhangrui182@huawei.com> - 0.16-1
|
||||
- Update to 0.16
|
||||
|
||||
* Tue May 24 2022 fengtao <fengtao40@huawei.com> - 0.15-5
|
||||
- we got upgrade error when upgrade json-c from very low version,
|
||||
for example json-c-0.11-5. because old version has a softlink:
|
||||
/usr/include/json-c --> /usr/include/json
|
||||
and now, softlink has been removed. so, we fix this in pretrans
|
||||
|
||||
* Fri May 6 2022 wuchaochao <cyanrose@yeah.net> - 0.15-4
|
||||
- add backport-json-escape-str-avoid-harmless-unsigned-integer-overflow.patch
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user