]> git.ipfire.org Git - thirdparty/json-c.git/commitdiff
Fix memory leak with emtpy strings in json_object_set_string 781/head
authorDaniel Danzberger <daniel@dd-wrt.com>
Sun, 24 Jul 2022 16:46:03 +0000 (18:46 +0200)
committerDaniel Danzberger <daniel@dd-wrt.com>
Sun, 24 Jul 2022 17:03:49 +0000 (19:03 +0200)
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>
json_object.c

index e52ca4071a374dd6d0a97b7bc056e413e74f5fe9..581b1e274810b2de7a98711d863003d6f554643f 100644 (file)
@@ -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)
        {