From: Eric S. Raymond Date: Fri, 26 Sep 2014 21:01:31 +0000 (-0400) Subject: Set the end pointer when erroring out. X-Git-Tag: 1.2~1 X-Git-Url: http://thyrsus.com/gitweb/?a=commitdiff_plain;h=cd8f3b96266c5c5cd9ee2484b8db8acceebd9443;p=microjson.git Set the end pointer when erroring out. --- diff --git a/mjson.asc b/mjson.asc index 0479000..0826f22 100644 --- a/mjson.asc +++ b/mjson.asc @@ -47,6 +47,9 @@ The two main functions return 0 for success, a nonzero error code for failure. The function +json_error_string()+ maps error codes to explanatory messages. +When an error is returned and the end pointer argument +is non-null, it is filled with the value of the buffer +pointer at the time the error was thrown. == BUGS == A backslash escape of "\0000" in a string value will drop a NUL in the string that is likely to confuse C code looking at the storage. In diff --git a/mjson.c b/mjson.c index 799fa34..25fd00b 100644 --- a/mjson.c +++ b/mjson.c @@ -237,6 +237,8 @@ static int json_internal_read_object(const char *cp, else { json_debug_trace((1, "Non-WS when expecting object start.\n")); + if (end) + *end = cp; return JSON_ERR_OBSTART; } break; @@ -250,12 +252,17 @@ static int json_internal_read_object(const char *cp, break; else { json_debug_trace((1, "Non-WS when expecting attribute.\n")); + if (end) + *end = cp; return JSON_ERR_ATTRSTART; } break; case in_attr: - if (pattr == NULL) + if (pattr == NULL) { + if (end) + *end = cp; return JSON_ERR_NULLPTR; + } if (*cp == '"') { *pattr++ = '\0'; json_debug_trace((1, "Collected attribute name %s\n", @@ -284,6 +291,8 @@ static int json_internal_read_object(const char *cp, pval = valbuf; } else if (pattr >= attrbuf + JSON_ATTR_MAX - 1) { json_debug_trace((1, "Attribute name too long.\n")); + if (end) + *end = cp; return JSON_ERR_ATTRLEN; } else *pattr++ = *cp; @@ -295,6 +304,8 @@ static int json_internal_read_object(const char *cp, if (cursor->type != t_array) { json_debug_trace((1, "Saw [ when not expecting array.\n")); + if (end) + *end = cp; return JSON_ERR_NOARRAY; } substatus = json_read_array(cp, &cursor->addr.array, &cp); @@ -304,6 +315,8 @@ static int json_internal_read_object(const char *cp, } else if (cursor->type == t_array) { json_debug_trace((1, "Array element was specified, but no [.\n")); + if (end) + *end = cp; return JSON_ERR_NOBRAK; } else if (*cp == '"') { value_quoted = true; @@ -317,8 +330,11 @@ static int json_internal_read_object(const char *cp, } break; case in_val_string: - if (pval == NULL) + if (pval == NULL) { + if (end) + *end = cp; return JSON_ERR_NULLPTR; + } if (*cp == '\\') state = in_escape; else if (*cp == '"') { @@ -328,13 +344,18 @@ static int json_internal_read_object(const char *cp, } else if (pval > valbuf + JSON_VAL_MAX - 1 || pval > valbuf + maxlen) { json_debug_trace((1, "String value too long.\n")); + if (end) + *end = cp; return JSON_ERR_STRLONG; /* */ } else *pval++ = *cp; break; case in_escape: - if (pval == NULL) + if (pval == NULL) { + if (end) + *end = cp; return JSON_ERR_NULLPTR; + } switch (*cp) { case 'b': *pval++ = '\b'; @@ -365,8 +386,11 @@ static int json_internal_read_object(const char *cp, state = in_val_string; break; case in_val_token: - if (pval == NULL) + if (pval == NULL) { + if (end) + *end = cp; return JSON_ERR_NULLPTR; + } if (isspace((unsigned char) *cp) || *cp == ',' || *cp == '}') { *pval = '\0'; json_debug_trace((1, "Collected token value %s.\n", valbuf)); @@ -375,6 +399,8 @@ static int json_internal_read_object(const char *cp, --cp; } else if (pval > valbuf + JSON_VAL_MAX - 1) { json_debug_trace((1, "Token value too long.\n")); + if (end) + *end = cp; return JSON_ERR_TOKLONG; } else *pval++ = *cp; @@ -414,6 +440,8 @@ static int json_internal_read_object(const char *cp, && cursor->type != t_ignore && cursor->map == 0)) { json_debug_trace((1, "Saw quoted value when expecting non-string.\n")); + if (end) + *end = cp; return JSON_ERR_QNONSTRING; } if (!value_quoted @@ -421,6 +449,8 @@ static int json_internal_read_object(const char *cp, || cursor->map != 0)) { json_debug_trace((1, "Didn't see quoted value when expecting string.\n")); + if (end) + *end = cp; return JSON_ERR_NONQSTRING; } if (cursor->map != 0) { @@ -430,6 +460,8 @@ static int json_internal_read_object(const char *cp, } json_debug_trace((1, "Invalid enumerated value string %s.\n", valbuf)); + if (end) + *end = cp; return JSON_ERR_BADENUM; foundit: (void)snprintf(valbuf, sizeof(valbuf), "%d", mp->value); @@ -470,8 +502,11 @@ static int json_internal_read_object(const char *cp, } break; case t_character: - if (strlen(valbuf) > 1) + if (strlen(valbuf) > 1) { + if (end) + *end = cp; return JSON_ERR_STRLONG; + } else lptr[0] = valbuf[0]; break; @@ -485,6 +520,8 @@ static int json_internal_read_object(const char *cp, json_debug_trace((1, "Required attribute value %s not present.\n", cursor->dflt.check)); + if (end) + *end = cp; return JSON_ERR_CHECKFAIL; } break; @@ -500,6 +537,8 @@ static int json_internal_read_object(const char *cp, goto good_parse; } else { json_debug_trace((1, "Garbage while expecting comma or }\n")); + if (end) + *end = cp; return JSON_ERR_BADTRAIL; } break;