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 ------ 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/load.c b/src/load.c index ef65f0f..f5cbf68 100644 --- a/src/load.c +++ b/src/load.c @@ -869,13 +869,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); @@ -907,6 +913,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; @@ -914,7 +927,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); @@ -927,15 +939,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); @@ -949,6 +967,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/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; } diff --git a/test/suites/api/test_load.c b/test/suites/api/test_load.c index fb4c734..8143d46 100644 --- a/test/suites/api/test_load.c +++ b/test/suites/api/test_load.c @@ -76,10 +76,33 @@ static void decode_any() 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(); decode_any(); + load_wrong_args(); }