From 0cac724924ae8aadf9e12dd2aedc3eb0bf8de901 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Tue, 25 Aug 2009 03:05:10 +0000 Subject: Change the way JSON parse templates are declared... so that string lengths won't step on offsets. --- json.c | 37 ++++++++++++++++++++++++++----------- json.h | 7 +++---- test_json.c | 2 +- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/json.c b/json.c index 8b204776..c5e5b4b2 100644 --- a/json.c +++ b/json.c @@ -31,13 +31,21 @@ elements of an array must be of the same type. JSON object or a JSON array. JSON "float" quantities are actually stored as doubles. - The only really opaque part of the interface is structobjects. -This is a way to parse a list of objects to a set of modifications to -a corresponding array of C structs. The trick is that the array -object initialization has to specify both the C struct array's base -address and the stride length (the size of the C struct. If you -initialize the offset fields with the correct offsetof() calls, -everything will work. + This paraer processes object arrays in one of two different ways, +defending on whether the array subtype is declared as object or structobject. + + Object arrays take one base address per object subfield, and are +mapped into parallel C arrays (one per subfield). Strings are not +supported in this kind of array, as the don't have a "natural" size +to use as an offset multiplier. + + Structobjects arrays are a way to parse a list of objects to a set +of modifications to a corresponding array of C structs. The trick is +that the array object initialization has to specify both the C struct +array's base address and the stride length (the size of the C struct. +If you initialize the offset fields with the correct offsetof() calls, +everything will work. Strings are suppported but all string storage +has to be inline in the struct. ***************************************************************************/ #include @@ -69,7 +77,10 @@ static int json_internal_read_object(const char *cp, const struct json_attr_t *a cursor->addr.real[offset] = cursor->dflt.real; break; case string: - cursor->addr.string.ptr[offset] = '\0'; + if (offset > 0) + return JSON_ERR_NOPARSTR; + else + cursor->addr.string[0] = '\0'; break; case boolean: /* nullbool default says not to set the value at all */ @@ -202,7 +213,7 @@ static int json_internal_read_object(const char *cp, const struct json_attr_t *a break; case in_val_string: if (cursor->type == string) - maxlen = cursor->addr.string.len - 1; + maxlen = cursor->len - 1; else if (cursor->type == check) maxlen = strlen(cursor->dflt.check); if (*cp == '"') { @@ -248,7 +259,10 @@ static int json_internal_read_object(const char *cp, const struct json_attr_t *a cursor->addr.real[offset] = atof(valbuf); break; case string: - (void)strncpy(cursor->addr.string.ptr+offset, valbuf, cursor->addr.string.len); + if (offset > 0) + return JSON_ERR_NOPARSTR; + else + (void)strncpy(cursor->addr.string, valbuf, cursor->len); break; case boolean: cursor->addr.boolean[offset] = (bool)!strcmp(valbuf, "true"); @@ -278,7 +292,7 @@ static int json_internal_read_object(const char *cp, const struct json_attr_t *a *((double *)lptr) = atof(valbuf); break; case string: - (void)strncpy(lptr, valbuf, cursor->addr.string.len); + (void)strncpy(lptr, valbuf, cursor->len); break; case boolean: *((bool *)lptr) = (bool)!strcmp(valbuf, "true"); @@ -450,6 +464,7 @@ const char *json_error_string(int err) "error while string parsing", "check attribute not matched", "invalid flag token", + "can't support strings in aparalle. arrays", }; if (err <= 0 || err >= (int)(sizeof(errors)/sizeof(errors[0]))) diff --git a/json.h b/json.h index 0e830dce..e6505d69 100644 --- a/json.h +++ b/json.h @@ -32,10 +32,7 @@ struct json_attr_t { union { int *integer; double *real; - struct { - char *ptr; - int len; - } string; + char *string; bool *boolean; struct json_array_t array; size_t offset; @@ -46,6 +43,7 @@ struct json_attr_t { bool boolean; char *check; } dflt; + size_t len; }; #define JSON_ATTR_MAX 31 /* max chars in JSON attribute name */ @@ -72,5 +70,6 @@ const char *json_error_string(int); #define JSON_ERR_BADSTRING 15 /* error while string parsing */ #define JSON_ERR_CHECKFAIL 16 /* check attribute not matched */ #define JSON_ERR_BADENUM 17 /* invalid flag token */ +#define JSON_ERR_NOPARSTR 18 /* can't support strings in aparalle. arrays */ /* json.h ends here */ diff --git a/test_json.c b/test_json.c index ef92dca0..a71625e1 100644 --- a/test_json.c +++ b/test_json.c @@ -144,7 +144,7 @@ static int dumbcount; static const struct json_attr_t json_attrs_6_subtype[] = { {"name", string, .addr.offset = offsetof(struct dumbstruct_t, name), - .addr.string.len = 64}, + .len = 64}, {"flag", boolean, .addr.offset = offsetof(struct dumbstruct_t, flag),}, {"count", integer, .addr.offset = offsetof(struct dumbstruct_t, count),}, {NULL}, -- cgit v1.2.1