json: make sure parse always sets *end

Funnel all of the return paths in the main parsing routine through the
code that sets the *end pointer so that all error cases set it.

Change-Id: I0565913f7b9488470ede79dc1af84eb4b9a03225
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Daniel Verkamp 2017-01-03 16:52:06 -07:00
parent 222bac51e8
commit d6fd64cdab

View File

@ -202,10 +202,12 @@ json_decode_string(uint8_t *str_start, uint8_t *buf_end, uint8_t **str_end, uint
* Shortest valid string (the empty string) is two bytes (""),
* so this can't possibly be valid
*/
*str_end = str;
return SPDK_JSON_PARSE_INCOMPLETE;
}
if (*str++ != '"') {
*str_end = str;
return SPDK_JSON_PARSE_INVALID;
}
@ -222,17 +224,21 @@ json_decode_string(uint8_t *str_start, uint8_t *buf_end, uint8_t **str_end, uint
flags & SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE ? out : NULL);
assert(rc != 0);
if (rc < 0) {
*str_end = str;
return rc;
}
out += rc;
} else if (str[0] <= 0x1f) {
/* control characters must be escaped */
*str_end = str;
return SPDK_JSON_PARSE_INVALID;
} else {
rc = utf8_valid(str, buf_end);
if (rc == 0) {
*str_end = str;
return SPDK_JSON_PARSE_INCOMPLETE;
} else if (rc < 0) {
*str_end = str;
return SPDK_JSON_PARSE_INVALID;
}
@ -245,6 +251,7 @@ json_decode_string(uint8_t *str_start, uint8_t *buf_end, uint8_t **str_end, uint
}
/* If execution gets here, we ran out of buffer. */
*str_end = str;
return SPDK_JSON_PARSE_INCOMPLETE;
}
@ -442,7 +449,7 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
size_t con_start_value;
uint8_t *data = json;
uint8_t *new_data;
int rc;
int rc = 0;
const struct json_literal *lit;
enum {
STATE_VALUE, /* initial state */
@ -476,11 +483,11 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
case 'f':
case 'n':
/* true, false, or null */
if (state != STATE_VALUE) return SPDK_JSON_PARSE_INVALID;
if (state != STATE_VALUE) goto done_invalid;
lit = &g_json_literals[(c >> 3) & 3]; /* See comment above g_json_literals[] */
assert(lit->str[0] == c);
rc = match_literal(data, json_end, lit->str, lit->len);
if (rc < 0) return rc;
if (rc < 0) goto done_rc;
ADD_VALUE(lit->type, data, data + rc);
data += rc;
state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
@ -488,9 +495,12 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
break;
case '"':
if (state != STATE_VALUE && state != STATE_NAME) return SPDK_JSON_PARSE_INVALID;
if (state != STATE_VALUE && state != STATE_NAME) goto done_invalid;
rc = json_decode_string(data, json_end, &new_data, flags);
if (rc < 0) return rc;
if (rc < 0) {
data = new_data;
goto done_rc;
}
/*
* Start is data + 1 to skip initial quote.
* Length is data + rc - 1 to skip both quotes.
@ -517,9 +527,9 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
case '7':
case '8':
case '9':
if (state != STATE_VALUE) return SPDK_JSON_PARSE_INVALID;
if (state != STATE_VALUE) goto done_invalid;
rc = json_valid_number(data, json_end);
if (rc < 0) return rc;
if (rc < 0) goto done_rc;
ADD_VALUE(SPDK_JSON_VAL_NUMBER, data, data + rc);
data += rc;
state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
@ -528,9 +538,10 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
case '{':
case '[':
if (state != STATE_VALUE) return SPDK_JSON_PARSE_INVALID;
if (state != STATE_VALUE) goto done_invalid;
if (depth == SPDK_JSON_MAX_NESTING_DEPTH) {
return SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED;
rc = SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED;
goto done_rc;
}
if (c == '{') {
con_type = SPDK_JSON_VAL_OBJECT_BEGIN;
@ -548,8 +559,8 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
case '}':
case ']':
if (trailing_comma) return SPDK_JSON_PARSE_INVALID;
if (depth == 0) return SPDK_JSON_PARSE_INVALID;
if (trailing_comma) goto done_invalid;
if (depth == 0) goto done_invalid;
con_type = containers[--depth];
con_start_value = con_value[depth];
if (values && con_start_value < num_values) {
@ -557,18 +568,18 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
}
if (c == '}') {
if (state != STATE_NAME && state != STATE_VALUE_SEPARATOR) {
return SPDK_JSON_PARSE_INVALID;
goto done_invalid;
}
if (con_type != SPDK_JSON_VAL_OBJECT_BEGIN) {
return SPDK_JSON_PARSE_INVALID;
goto done_invalid;
}
ADD_VALUE(SPDK_JSON_VAL_OBJECT_END, data, data + 1);
} else {
if (state != STATE_VALUE && state != STATE_VALUE_SEPARATOR) {
return SPDK_JSON_PARSE_INVALID;
goto done_invalid;
}
if (con_type != SPDK_JSON_VAL_ARRAY_BEGIN) {
return SPDK_JSON_PARSE_INVALID;
goto done_invalid;
}
ADD_VALUE(SPDK_JSON_VAL_ARRAY_END, data, data + 1);
}
@ -579,7 +590,7 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
break;
case ',':
if (state != STATE_VALUE_SEPARATOR) return SPDK_JSON_PARSE_INVALID;
if (state != STATE_VALUE_SEPARATOR) goto done_invalid;
data++;
assert(con_type == SPDK_JSON_VAL_ARRAY_BEGIN ||
con_type == SPDK_JSON_VAL_OBJECT_BEGIN);
@ -588,23 +599,23 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
break;
case ':':
if (state != STATE_NAME_SEPARATOR) return SPDK_JSON_PARSE_INVALID;
if (state != STATE_NAME_SEPARATOR) goto done_invalid;
data++;
state = STATE_VALUE;
break;
case '/':
if (!(flags & SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS)) {
return SPDK_JSON_PARSE_INVALID;
goto done_invalid;
}
rc = json_valid_comment(data, json_end);
if (rc < 0) return rc;
if (rc < 0) goto done_rc;
/* Skip over comment */
data += rc;
break;
default:
return SPDK_JSON_PARSE_INVALID;
goto done_invalid;
}
if (state == STATE_END) {
@ -638,8 +649,16 @@ spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t nu
}
/* Invalid end state - ran out of data */
rc = SPDK_JSON_PARSE_INCOMPLETE;
done_rc:
assert(rc < 0);
if (end) {
*end = data;
}
return SPDK_JSON_PARSE_INCOMPLETE;
return rc;
done_invalid:
rc = SPDK_JSON_PARSE_INVALID;
goto done_rc;
}