Browse Source

Add a json_object_from_fd_ex() function, to allow the max nesting depth to be specified.

tags/json-c-0.14-20200419
Eric Haszlakiewicz 5 years ago
parent
commit
baed9983b3
6 changed files with 94 additions and 7 deletions
  1. +25
    -3
      json_util.c
  2. +12
    -0
      json_util.h
  3. +1
    -0
      tests/Makefile.am
  4. +51
    -3
      tests/test_util_file.c
  5. +4
    -1
      tests/test_util_file.expected
  6. +1
    -0
      tests/valid_nested.json

+ 25
- 3
json_util.c View File

@@ -82,6 +82,10 @@ void _json_c_set_last_err(const char *err_fmt, ...)
}

struct json_object* json_object_from_fd(int fd)
{
return json_object_from_fd_ex(fd, -1);
}
struct json_object* json_object_from_fd_ex(int fd, int in_depth)
{
struct printbuf *pb;
struct json_object *obj;
@@ -92,17 +96,35 @@ struct json_object* json_object_from_fd(int fd)
_json_c_set_last_err("json_object_from_file: printbuf_new failed\n");
return NULL;
}

int depth = JSON_TOKENER_DEFAULT_DEPTH;
if (in_depth != -1)
depth = in_depth;
json_tokener *tok = json_tokener_new_ex(depth);
if (!tok)
{
_json_c_set_last_err("json_object_from_fd: 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(ret < 0) {
_json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, strerror(errno));
json_tokener_free(tok);
printbuf_free(pb);
return NULL;
}
obj = json_tokener_parse(pb->buf);
printbuf_free(pb);
return obj;

obj = json_tokener_parse_ex(tok, pb->buf, printbuf_length(pb));
if (obj == NULL)
_json_c_set_last_err("json_tokener_parse_ex failed: %s\n", json_tokener_error_desc(json_tokener_get_error(tok)));

json_tokener_free(tok);
printbuf_free(pb);
return obj;
}

struct json_object* json_object_from_file(const char *filename)


+ 12
- 0
json_util.h View File

@@ -50,8 +50,20 @@ JSON_EXPORT struct json_object* json_object_from_file(const char *filename);
* Note, that the fd must be readable at the actual position, i.e.
* use lseek(fd, 0, SEEK_SET) before.
*
* The depth argument specifies the maximum object depth to pass to
* json_tokener_new_ex(). When depth == -1, JSON_TOKENER_DEFAULT_DEPTH
* is used instead.
*
* Returns NULL on failure. See json_util_get_last_err() for details.
*/
JSON_EXPORT struct json_object* json_object_from_fd_ex(int fd, int depth);

/**
* Create a JSON object from an already opened file descriptor, using
* the default maximum object depth. (JSON_TOKENER_DEFAULT_DEPTH)
*
* See json_object_from_fd_ex() for details.
*/
JSON_EXPORT struct json_object* json_object_from_fd(int fd);

/**


+ 1
- 0
tests/Makefile.am View File

@@ -36,6 +36,7 @@ EXTRA_DIST += $(TESTS)
EXTRA_DIST += $(TESTS:.test=.expected)
EXTRA_DIST += test-defs.sh
EXTRA_DIST += valid.json
EXTRA_DIST += valid_nested.json


# Note: handled by test1.test


+ 51
- 3
tests/test_util_file.c View File

@@ -5,6 +5,7 @@
#include <stddef.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -13,6 +14,7 @@
#include "json_util.h"

static void test_read_valid_with_fd(const char *testdir);
static void test_read_valid_nested_with_fd(const char *testdir);
static void test_read_nonexistant();
static void test_read_closed(void);

@@ -129,6 +131,7 @@ int main(int argc, char **argv)
testdir = argv[1];

test_read_valid_with_fd(testdir);
test_read_valid_nested_with_fd(testdir);
test_read_nonexistant();
test_read_closed();
test_write_to_file();
@@ -137,7 +140,8 @@ int main(int argc, char **argv)

static void test_read_valid_with_fd(const char *testdir)
{
const char *filename = "./valid.json";
char filename[PATH_MAX];
(void)snprintf(filename, sizeof(filename), "%s/valid.json", testdir);

int d = open(filename, O_RDONLY, 0);
if (d < 0)
@@ -150,8 +154,37 @@ static void test_read_valid_with_fd(const char *testdir)
json_object *jso = json_object_from_fd(d);
if (jso != NULL)
{
printf("OK: json_object_from_fd(%s)=%s\n",
filename, json_object_to_json_string(jso));
printf("OK: json_object_from_fd(valid.json)=%s\n",
json_object_to_json_string(jso));
json_object_put(jso);
}
else
{
fprintf(stderr,
"FAIL: unable to parse contents of %s: %s\n",
filename, json_util_get_last_err());
}
close(d);
}

static void test_read_valid_nested_with_fd(const char *testdir)
{
char filename[PATH_MAX];
(void)snprintf(filename, sizeof(filename), "%s/valid_nested.json", testdir);

int d = open(filename, O_RDONLY, 0);
if (d < 0)
{
fprintf(stderr,
"FAIL: unable to open %s: %s\n",
filename, strerror(errno));
exit(EXIT_FAILURE);
}
json_object *jso = json_object_from_fd_ex(d, 20);
if (jso != NULL)
{
printf("OK: json_object_from_fd_ex(valid_nested.json, 20)=%s\n",
json_object_to_json_string(jso));
json_object_put(jso);
}
else
@@ -160,6 +193,21 @@ static void test_read_valid_with_fd(const char *testdir)
"FAIL: unable to parse contents of %s: %s\n",
filename, json_util_get_last_err());
}

(void)lseek(d, SEEK_SET, 0);

jso = json_object_from_fd_ex(d, 3);
if (jso != NULL)
{
printf("FAIL: json_object_from_fd_ex(%s, 3)=%s\n",
filename, json_object_to_json_string(jso));
json_object_put(jso);
}
else
{
printf("OK: correctly unable to parse contents of valid_nested.json with low max depth: %s\n",
json_util_get_last_err());
}
close(d);
}



+ 4
- 1
tests/test_util_file.expected View File

@@ -1,4 +1,7 @@
OK: json_object_from_fd(./valid.json)={ "foo": 123 }
OK: json_object_from_fd(valid.json)={ "foo": 123 }
OK: json_object_from_fd_ex(valid_nested.json, 20)={ "foo": 123, "obj2": { "obj3": { "obj4": { "foo": 999 } } } }
OK: correctly unable to parse contents of valid_nested.json with low max depth: json_tokener_parse_ex failed: nesting too deep

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


+ 1
- 0
tests/valid_nested.json View File

@@ -0,0 +1 @@
{"foo":123, "obj2": { "obj3": { "obj4": { "foo": 999 } } } }

Loading…
Cancel
Save