From 5ec101ec21d5fec71dcf693e941c90c388430a32 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 11 Nov 2011 19:17:50 +0100 Subject: [PATCH 1/3] json_load* return NULL if the first argument is NULL --- src/load.c | 33 ++++++++++++++++++++++++++++----- test/suites/api/test_load.c | 23 +++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/load.c b/src/load.c index d60a93e..3fdec8f 100644 --- a/src/load.c +++ b/src/load.c @@ -867,13 +867,19 @@ json_t *json_loads(const char *string, size_t flags, json_error_t *error) json_t *result; string_data_t stream_data; + jsonp_error_init(error, ""); + + if (string == NULL) { + error_set(error, NULL, "wrong arguments"); + return NULL; + } + stream_data.data = string; stream_data.pos = 0; if(lex_init(&lex, string_get, (void *)&stream_data)) return NULL; - jsonp_error_init(error, ""); result = parse_json(&lex, flags, error); lex_close(&lex); @@ -905,6 +911,13 @@ json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t json_t *result; buffer_data_t stream_data; + jsonp_error_init(error, ""); + + if (buffer == NULL) { + error_set(error, NULL, "wrong arguments"); + return NULL; + } + stream_data.data = buffer; stream_data.pos = 0; stream_data.len = buflen; @@ -912,7 +925,6 @@ json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t if(lex_init(&lex, buffer_get, (void *)&stream_data)) return NULL; - jsonp_error_init(error, ""); result = parse_json(&lex, flags, error); lex_close(&lex); @@ -925,15 +937,21 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) const char *source; json_t *result; - if(lex_init(&lex, (get_func)fgetc, input)) - return NULL; - if(input == stdin) source = ""; else source = ""; jsonp_error_init(error, source); + + if (input == NULL) { + error_set(error, NULL, "wrong arguments"); + return NULL; + } + + if(lex_init(&lex, (get_func)fgetc, input)) + return NULL; + result = parse_json(&lex, flags, error); lex_close(&lex); @@ -947,6 +965,11 @@ json_t *json_load_file(const char *path, size_t flags, json_error_t *error) jsonp_error_init(error, path); + if (path == NULL) { + error_set(error, NULL, "wrong arguments"); + return NULL; + } + fp = fopen(path, "rb"); if(!fp) { diff --git a/test/suites/api/test_load.c b/test/suites/api/test_load.c index d60869d..810b745 100644 --- a/test/suites/api/test_load.c +++ b/test/suites/api/test_load.c @@ -50,9 +50,32 @@ static void disable_eof_check() json_decref(json); } +static void load_wrong_args() +{ + json_t *json; + json_error_t error; + + json = json_loads(NULL, 0, &error); + if (json) + fail("json_loads should return NULL if the first argument is NULL"); + + json = json_loadb(NULL, 0, 0, &error); + if (json) + fail("json_loadb should return NULL if the first argument is NULL"); + + json = json_loadf(NULL, 0, &error); + if (json) + fail("json_loadf should return NULL if the first argument is NULL"); + + json = json_load_file(NULL, 0, &error); + if (json) + fail("json_loadf should return NULL if the first argument is NULL"); +} + static void run_tests() { file_not_found(); reject_duplicates(); disable_eof_check(); + load_wrong_args(); } From 0f2cdd70ff9c2f0dd35a2e62b5bac87305d17bf4 Mon Sep 17 00:00:00 2001 From: Petri Lehtinen Date: Mon, 14 Nov 2011 19:10:28 +0200 Subject: [PATCH 2/3] Avoid problems with object's serial number growing too big Transform serial key comparison from substraction to real comparison. Reset serial to zero in json_object_clear() to avoid it growing out of bounds when reusing objects. Closes GH-40. Closes GH-41. --- src/dump.c | 6 ++++-- src/value.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dump.c b/src/dump.c index 33112ba..089474d 100644 --- a/src/dump.c +++ b/src/dump.c @@ -159,8 +159,10 @@ static int object_key_compare_keys(const void *key1, const void *key2) static int object_key_compare_serials(const void *key1, const void *key2) { - return (*(const object_key_t **)key1)->serial - - (*(const object_key_t **)key2)->serial; + size_t a = (*(const object_key_t **)key1)->serial; + size_t b = (*(const object_key_t **)key2)->serial; + + return a < b ? -1 : a == b ? 0 : 1; } static int do_dump(const json_t *json, size_t flags, int depth, diff --git a/src/value.c b/src/value.c index d0517d5..5ef4138 100644 --- a/src/value.c +++ b/src/value.c @@ -186,7 +186,9 @@ int json_object_clear(json_t *json) return -1; object = json_to_object(json); + hashtable_clear(&object->hashtable); + object->serial = 0; return 0; } From 0931d938b049b4ab190593bd2755d03891d8bfd6 Mon Sep 17 00:00:00 2001 From: Petri Lehtinen Date: Mon, 14 Nov 2011 19:32:42 +0200 Subject: [PATCH 3/3] doc: The same JSON values must not be encoded in parallel Closes GH-42. --- doc/portability.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/portability.rst b/doc/portability.rst index 0a49e2e..dc6c5eb 100644 --- a/doc/portability.rst +++ b/doc/portability.rst @@ -20,6 +20,16 @@ such values, as containers manage the reference count of their contained values. Bugs involving concurrent incrementing or decrementing of deference counts may be hard to track. +The encoding functions (:func:`json_dumps()` and friends) track +reference loops by modifying the internal state of objects and arrays. +For this reason, encoding functions must not be run on the same JSON +values in two separate threads at the same time. As already noted +above, be especially careful if two arrays or objects share their +contained values with another array or object. + +If you want to make sure that two JSON value hierarchies do not +contain shared values, use :func:`json_deep_copy()` to make copies. + Locale ------