]> git.ipfire.org Git - thirdparty/json-c.git/commitdiff
json_object_from_fd_ex: fail if file is too large 757/head
authorTobias Stoeckmann <tobias@stoeckmann.org>
Sun, 20 Mar 2022 12:17:37 +0000 (13:17 +0100)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Sun, 20 Mar 2022 12:17:37 +0000 (13:17 +0100)
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.

json_util.c
printbuf.c
tests/test_util_file.expected

index 3e6a6c681beb00d578a6129bd30f0ec50ae9a901..e1c05c5cfd311fc57d78d758528f5b8fe4c6e356 100644 (file)
@@ -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)
        {
index a08f7b15829e5037fbbff653e9fc0b4aafa1a8f9..12d3b3319da89e88264cf578105a29b4cc36e478 100644 (file)
@@ -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)
        {
index f149f8543a81c52463222cfa412dee26081e9ee7..4a8aea55fa0aadce5292cafcf05733775ef24a83 100644 (file)
@@ -4,7 +4,7 @@ OK: correctly unable to parse contents of valid_nested.json with low max depth:
 
 OK: json_object_from_file(./not_present.json) correctly returned NULL: json_object_from_file: error opening file ./not_present.json: ERRNO=ENOENT
 
-OK: json_object_from_fd(closed_fd), expecting NULL, EBADF, got:NULL, json_object_from_fd: error reading fd 10: ERRNO=EBADF
+OK: json_object_from_fd(closed_fd), expecting NULL, EBADF, got:NULL, json_object_from_fd_ex: error reading fd 10: ERRNO=EBADF
 
 OK: json_object_to_file(json.out, jso)=0
 file[json.out], size=336, contents={"foo":1234,"foo1":"abcdefghijklmnopqrstuvwxyz","foo2":"abcdefghijklmnopqrstuvwxyz","foo3":"abcdefghijklmnopqrstuvwxyz","foo4":"abcdefghijklmnopqrstuvwxyz","foo5":"abcdefghijklmnopqrstuvwxyz","foo6":"abcdefghijklmnopqrstuvwxyz","foo7":"abcdefghijklmnopqrstuvwxyz","foo8":"abcdefghijklmnopqrstuvwxyz","foo9":"abcdefghijklmnopqrstuvwxyz"}