summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@stoeckmann.org>2020-05-16 13:01:10 +0200
committerTobias Stoeckmann <tobias@stoeckmann.org>2020-05-16 15:26:16 +0200
commit5385a566db80428c39c80abbf48f35f59760e975 (patch)
treeab8c4e72d390a0518e200fd4d3ed2bdf1a6a389f
parent0a3d22b9bb58dfbba8b0ab25b9fb14fdf6136f49 (diff)
downloadjson-c-5385a566db80428c39c80abbf48f35f59760e975.tar.gz
Prevent truncation on custom double formatters.
A custom double formatter can lead to truncation of the rest of the JSON document. If a custom formatter completely fills the buffer used by snprintf with a trailing dot or comma and the formatting option JSON_C_TO_STRING_NOZERO has been specified, then an iterator moves past the ending '\0' (off-by-one buffer overflow) to set an additional '\0' and adds the first '\0' into the printbuf. Since '\0' will eventually be considered the terminating character of the complete printbuf result, all trailing characters are lost. This leads to an incomplete JSON string as can be seen with the test case. The off-by-one can be noticed if compiled with address sanitizer. Since this is a very special case and a malformed formatter could do way more harm and is the responsibility of the user of this library, this is just a protective measure to keep json-c code as robust as possible.
-rw-r--r--json_object.c3
-rw-r--r--tests/test_set_serializer.c14
-rw-r--r--tests/test_set_serializer.expected2
3 files changed, 17 insertions, 2 deletions
diff --git a/json_object.c b/json_object.c
index 04164d0..c2463c1 100644
--- a/json_object.c
+++ b/json_object.c
@@ -969,7 +969,8 @@ static int json_object_double_to_json_string_format(struct json_object *jso, str
p = q;
}
/* drop trailing zeroes */
- *(++p) = 0;
+ if (*p != 0)
+ *(++p) = 0;
size = p - buf;
}
}
diff --git a/tests/test_set_serializer.c b/tests/test_set_serializer.c
index db1c187..b5c1979 100644
--- a/tests/test_set_serializer.c
+++ b/tests/test_set_serializer.c
@@ -26,7 +26,7 @@ static int custom_serializer(struct json_object *o, struct printbuf *pb, int lev
int main(int argc, char **argv)
{
- json_object *my_object;
+ json_object *my_object, *my_sub_object;
MC_SET_DEBUG(1);
@@ -67,5 +67,17 @@ int main(int argc, char **argv)
json_object_put(my_object);
assert(freeit_was_called);
+ // ============================================
+
+ my_object = json_object_new_object();
+ my_sub_object = json_object_new_double(1.0);
+ json_object_object_add(my_object, "double", my_sub_object);
+ printf("Check that the custom serializer does not include nul byte:\n");
+ json_object_set_serializer(my_sub_object, json_object_double_to_json_string, "%125.0f,", NULL);
+ printf("my_object.to_string(custom serializer)=%s\n",
+ json_object_to_json_string_ext(my_object, JSON_C_TO_STRING_NOZERO));
+
+ json_object_put(my_object);
+
return 0;
}
diff --git a/tests/test_set_serializer.expected b/tests/test_set_serializer.expected
index ad44a90..9629dd6 100644
--- a/tests/test_set_serializer.expected
+++ b/tests/test_set_serializer.expected
@@ -8,3 +8,5 @@ Check that the custom serializer isn't free'd until the last json_object_put:
my_object.to_string(custom serializer)=Custom Output
Next line of output should be from the custom freeit function:
freeit, value=123
+Check that the custom serializer does not include nul byte:
+my_object.to_string(custom serializer)={"double": 1.}