diff --git a/src/dump.c b/src/dump.c index a36da03..870f30e 100644 --- a/src/dump.c +++ b/src/dump.c @@ -224,40 +224,44 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, /* detect circular references */ array = json_to_array(json); if(array->visited) - return -1; + goto array_error; array->visited = 1; n = json_array_size(json); if(dump("[", 1, data)) - return -1; + goto array_error; if(n == 0) { array->visited = 0; return dump("]", 1, data); } if(dump_indent(flags, depth + 1, 0, dump, data)) - return -1; + goto array_error; for(i = 0; i < n; ++i) { if(do_dump(json_array_get(json, i), flags, depth + 1, dump, data)) - return -1; + goto array_error; if(i < n - 1) { if(dump(",", 1, data) || dump_indent(flags, depth + 1, 1, dump, data)) - return -1; + goto array_error; } else { if(dump_indent(flags, depth, 0, dump, data)) - return -1; + goto array_error; } } array->visited = 0; return dump("]", 1, data); + + array_error: + array->visited = 0; + return -1; } case JSON_OBJECT: @@ -279,19 +283,19 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, /* detect circular references */ object = json_to_object(json); if(object->visited) - return -1; + goto object_error; object->visited = 1; iter = json_object_iter((json_t *)json); if(dump("{", 1, data)) - return -1; + goto object_error; if(!iter) { object->visited = 0; return dump("}", 1, data); } if(dump_indent(flags, depth + 1, 0, dump, data)) - return -1; + goto object_error; if(flags & JSON_SORT_KEYS) { @@ -304,7 +308,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, size = json_object_size(json); keys = malloc(size * sizeof(const char *)); if(!keys) - return -1; + goto object_error; i = 0; while(iter) @@ -331,7 +335,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, do_dump(value, flags, depth + 1, dump, data)) { free(keys); - return -1; + goto object_error; } if(i < size - 1) @@ -340,7 +344,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, dump_indent(flags, depth + 1, 1, dump, data)) { free(keys); - return -1; + goto object_error; } } else @@ -348,7 +352,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, if(dump_indent(flags, depth, 0, dump, data)) { free(keys); - return -1; + goto object_error; } } } @@ -367,18 +371,18 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, if(dump(separator, separator_length, data) || do_dump(json_object_iter_value(iter), flags, depth + 1, dump, data)) - return -1; + goto object_error; if(next) { if(dump(",", 1, data) || dump_indent(flags, depth + 1, 1, dump, data)) - return -1; + goto object_error; } else { if(dump_indent(flags, depth, 0, dump, data)) - return -1; + goto object_error; } iter = next; @@ -387,6 +391,10 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, object->visited = 0; return dump("}", 1, data); + + object_error: + object->visited = 0; + return -1; } default: diff --git a/test/suites/api/test_dump.c b/test/suites/api/test_dump.c index c471159..97eb03e 100644 --- a/test/suites/api/test_dump.c +++ b/test/suites/api/test_dump.c @@ -42,5 +42,48 @@ int main() json_decref(json); + /* Construct a JSON object/array with a circular reference: + + object: {"a": {"b": {"c": }}} + array: [[[]]] + + Encode it, remove the circular reference and encode again. + */ + json = json_object(); + json_object_set_new(json, "a", json_object()); + json_object_set_new(json_object_get(json, "a"), "b", json_object()); + json_object_set(json_object_get(json_object_get(json, "a"), "b"), "c", + json_object_get(json, "a")); + + if(json_dumps(json, 0)) + fail("json_dumps encoded a circular reference!"); + + json_object_del(json_object_get(json_object_get(json, "a"), "b"), "c"); + + result = json_dumps(json, 0); + if(!result || strcmp(result, "{\"a\": {\"b\": {}}}")) + fail("json_dumps failed!"); + free(result); + + json_decref(json); + + json = json_array(); + json_array_append_new(json, json_array()); + json_array_append_new(json_array_get(json, 0), json_array()); + json_array_append(json_array_get(json_array_get(json, 0), 0), + json_array_get(json, 0)); + + if(json_dumps(json, 0)) + fail("json_dumps encoded a circular reference!"); + + json_array_remove(json_array_get(json_array_get(json, 0), 0), 0); + + result = json_dumps(json, 0); + if(!result || strcmp(result, "[[[]]]")) + fail("json_dumps failed!"); + free(result); + + json_decref(json); + return 0; }