diff options
author | Petri Lehtinen <petri@digip.org> | 2009-10-15 21:02:27 +0300 |
---|---|---|
committer | Petri Lehtinen <petri@digip.org> | 2009-10-15 21:02:27 +0300 |
commit | 4cd777712b1e4ec17dc9efcced80a90f83ec1915 (patch) | |
tree | cca20833e8b55956be210f8cd285c387266817a2 /src | |
parent | 79009e62c10bab0869d61edfaa6c813f03f027bc (diff) | |
download | jansson-4cd777712b1e4ec17dc9efcced80a90f83ec1915.zip jansson-4cd777712b1e4ec17dc9efcced80a90f83ec1915.tar.gz jansson-4cd777712b1e4ec17dc9efcced80a90f83ec1915.tar.bz2 |
Enhance handling of circular references
It's now an error to try to add an object or array to itself. The
encoder checks for circular references and fails with an error status
if one is detected.
Diffstat (limited to 'src')
-rw-r--r-- | src/dump.c | 27 | ||||
-rw-r--r-- | src/jansson_private.h | 42 | ||||
-rw-r--r-- | src/value.c | 48 |
3 files changed, 75 insertions, 42 deletions
@@ -11,6 +11,7 @@ #include <string.h> #include <jansson.h> +#include "jansson_private.h" #include "strbuffer.h" #define MAX_INTEGER_STR_LENGTH 100 @@ -157,7 +158,16 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, case JSON_ARRAY: { int i; - int n = json_array_size(json); + int n; + json_array_t *array; + + /* detect circular references */ + array = json_to_array(json); + if(array->visited) + return -1; + array->visited = 1; + + n = json_array_size(json); if(dump("[", 1, data)) return -1; @@ -183,12 +193,23 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, return -1; } } + + array->visited = 0; return dump("]", 1, data); } case JSON_OBJECT: { - void *iter = json_object_iter((json_t *)json); + json_object_t *object; + void *iter; + + /* detect circular references */ + object = json_to_object(json); + if(object->visited) + return -1; + object->visited = 1; + + iter = json_object_iter((json_t *)json); if(dump("{", 1, data)) return -1; @@ -221,6 +242,8 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, iter = next; } + + object->visited = 0; return dump("}", 1, data); } diff --git a/src/jansson_private.h b/src/jansson_private.h index ad8419a..317f05a 100644 --- a/src/jansson_private.h +++ b/src/jansson_private.h @@ -8,8 +8,48 @@ #ifndef JANSSON_PRIVATE_H #define JANSSON_PRIVATE_H +#include "jansson.h" +#include "hashtable.h" + +#define container_of(ptr_, type_, member_) \ + ((type_ *)((char *)ptr_ - (size_t)&((type_ *)0)->member_)) + +typedef struct { + json_t json; + hashtable_t hashtable; + int visited; +} json_object_t; + +typedef struct { + json_t json; + unsigned int size; + unsigned int entries; + json_t **table; + int visited; +} json_array_t; + +typedef struct { + json_t json; + char *value; +} json_string_t; + +typedef struct { + json_t json; + double value; +} json_real_t; + +typedef struct { + json_t json; + int value; +} json_integer_t; + +#define json_to_object(json_) container_of(json_, json_object_t, json) +#define json_to_array(json_) container_of(json_, json_array_t, json) +#define json_to_string(json_) container_of(json_, json_string_t, json) +#define json_to_real(json_) container_of(json_, json_real_t, json) +#define json_to_integer(json_) container_of(json_, json_integer_t, json) + int json_object_set_nocheck(json_t *json, const char *key, json_t *value); json_t *json_string_nocheck(const char *value); - #endif diff --git a/src/value.c b/src/value.c index 076e335..1982b90 100644 --- a/src/value.c +++ b/src/value.c @@ -15,41 +15,6 @@ #include "utf.h" #include "util.h" -#define container_of(ptr_, type_, member_) \ - ((type_ *)((char *)ptr_ - (size_t)&((type_ *)0)->member_)) - -typedef struct { - json_t json; - hashtable_t hashtable; -} json_object_t; - -typedef struct { - json_t json; - unsigned int size; - unsigned int entries; - json_t **table; -} json_array_t; - -typedef struct { - json_t json; - char *value; -} json_string_t; - -typedef struct { - json_t json; - double value; -} json_real_t; - -typedef struct { - json_t json; - int value; -} json_integer_t; - -#define json_to_object(json_) container_of(json_, json_object_t, json) -#define json_to_array(json_) container_of(json_, json_array_t, json) -#define json_to_string(json_) container_of(json_, json_string_t, json) -#define json_to_real(json_) container_of(json_, json_real_t, json) -#define json_to_integer(json_) container_of(json_, json_integer_t, json) static inline void json_init(json_t *json, json_type type) { @@ -98,6 +63,9 @@ json_t *json_object(void) free(object); return NULL; } + + object->visited = 0; + return &object->json; } @@ -136,7 +104,7 @@ int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value) if(!key || !value) return -1; - if(!json_is_object(json)) + if(!json_is_object(json) || json == value) { json_decref(value); return -1; @@ -273,6 +241,8 @@ json_t *json_array(void) return NULL; } + array->visited = 0; + return &array->json; } @@ -315,7 +285,7 @@ int json_array_set_new(json_t *json, unsigned int index, json_t *value) if(!value) return -1; - if(!json_is_array(json)) + if(!json_is_array(json) || json == value) { json_decref(value); return -1; @@ -383,7 +353,7 @@ int json_array_append_new(json_t *json, json_t *value) if(!value) return -1; - if(!json_is_array(json)) + if(!json_is_array(json) || json == value) { json_decref(value); return -1; @@ -409,7 +379,7 @@ int json_array_insert_new(json_t *json, unsigned int index, json_t *value) if(!value) return -1; - if(!json_is_array(json)) { + if(!json_is_array(json) || json == value) { json_decref(value); return -1; } |