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:
parent
222bac51e8
commit
d6fd64cdab
@ -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 (""),
|
* Shortest valid string (the empty string) is two bytes (""),
|
||||||
* so this can't possibly be valid
|
* so this can't possibly be valid
|
||||||
*/
|
*/
|
||||||
|
*str_end = str;
|
||||||
return SPDK_JSON_PARSE_INCOMPLETE;
|
return SPDK_JSON_PARSE_INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*str++ != '"') {
|
if (*str++ != '"') {
|
||||||
|
*str_end = str;
|
||||||
return SPDK_JSON_PARSE_INVALID;
|
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);
|
flags & SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE ? out : NULL);
|
||||||
assert(rc != 0);
|
assert(rc != 0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
*str_end = str;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
out += rc;
|
out += rc;
|
||||||
} else if (str[0] <= 0x1f) {
|
} else if (str[0] <= 0x1f) {
|
||||||
/* control characters must be escaped */
|
/* control characters must be escaped */
|
||||||
|
*str_end = str;
|
||||||
return SPDK_JSON_PARSE_INVALID;
|
return SPDK_JSON_PARSE_INVALID;
|
||||||
} else {
|
} else {
|
||||||
rc = utf8_valid(str, buf_end);
|
rc = utf8_valid(str, buf_end);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
|
*str_end = str;
|
||||||
return SPDK_JSON_PARSE_INCOMPLETE;
|
return SPDK_JSON_PARSE_INCOMPLETE;
|
||||||
} else if (rc < 0) {
|
} else if (rc < 0) {
|
||||||
|
*str_end = str;
|
||||||
return SPDK_JSON_PARSE_INVALID;
|
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. */
|
/* If execution gets here, we ran out of buffer. */
|
||||||
|
*str_end = str;
|
||||||
return SPDK_JSON_PARSE_INCOMPLETE;
|
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;
|
size_t con_start_value;
|
||||||
uint8_t *data = json;
|
uint8_t *data = json;
|
||||||
uint8_t *new_data;
|
uint8_t *new_data;
|
||||||
int rc;
|
int rc = 0;
|
||||||
const struct json_literal *lit;
|
const struct json_literal *lit;
|
||||||
enum {
|
enum {
|
||||||
STATE_VALUE, /* initial state */
|
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 'f':
|
||||||
case 'n':
|
case 'n':
|
||||||
/* true, false, or null */
|
/* 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[] */
|
lit = &g_json_literals[(c >> 3) & 3]; /* See comment above g_json_literals[] */
|
||||||
assert(lit->str[0] == c);
|
assert(lit->str[0] == c);
|
||||||
rc = match_literal(data, json_end, lit->str, lit->len);
|
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);
|
ADD_VALUE(lit->type, data, data + rc);
|
||||||
data += rc;
|
data += rc;
|
||||||
state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
|
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;
|
break;
|
||||||
|
|
||||||
case '"':
|
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);
|
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.
|
* Start is data + 1 to skip initial quote.
|
||||||
* Length is data + rc - 1 to skip both quotes.
|
* 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 '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
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);
|
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);
|
ADD_VALUE(SPDK_JSON_VAL_NUMBER, data, data + rc);
|
||||||
data += rc;
|
data += rc;
|
||||||
state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
|
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 '{':
|
||||||
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) {
|
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 == '{') {
|
if (c == '{') {
|
||||||
con_type = SPDK_JSON_VAL_OBJECT_BEGIN;
|
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 '}':
|
||||||
case ']':
|
case ']':
|
||||||
if (trailing_comma) return SPDK_JSON_PARSE_INVALID;
|
if (trailing_comma) goto done_invalid;
|
||||||
if (depth == 0) return SPDK_JSON_PARSE_INVALID;
|
if (depth == 0) goto done_invalid;
|
||||||
con_type = containers[--depth];
|
con_type = containers[--depth];
|
||||||
con_start_value = con_value[depth];
|
con_start_value = con_value[depth];
|
||||||
if (values && con_start_value < num_values) {
|
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 (c == '}') {
|
||||||
if (state != STATE_NAME && state != STATE_VALUE_SEPARATOR) {
|
if (state != STATE_NAME && state != STATE_VALUE_SEPARATOR) {
|
||||||
return SPDK_JSON_PARSE_INVALID;
|
goto done_invalid;
|
||||||
}
|
}
|
||||||
if (con_type != SPDK_JSON_VAL_OBJECT_BEGIN) {
|
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);
|
ADD_VALUE(SPDK_JSON_VAL_OBJECT_END, data, data + 1);
|
||||||
} else {
|
} else {
|
||||||
if (state != STATE_VALUE && state != STATE_VALUE_SEPARATOR) {
|
if (state != STATE_VALUE && state != STATE_VALUE_SEPARATOR) {
|
||||||
return SPDK_JSON_PARSE_INVALID;
|
goto done_invalid;
|
||||||
}
|
}
|
||||||
if (con_type != SPDK_JSON_VAL_ARRAY_BEGIN) {
|
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);
|
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;
|
break;
|
||||||
|
|
||||||
case ',':
|
case ',':
|
||||||
if (state != STATE_VALUE_SEPARATOR) return SPDK_JSON_PARSE_INVALID;
|
if (state != STATE_VALUE_SEPARATOR) goto done_invalid;
|
||||||
data++;
|
data++;
|
||||||
assert(con_type == SPDK_JSON_VAL_ARRAY_BEGIN ||
|
assert(con_type == SPDK_JSON_VAL_ARRAY_BEGIN ||
|
||||||
con_type == SPDK_JSON_VAL_OBJECT_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;
|
break;
|
||||||
|
|
||||||
case ':':
|
case ':':
|
||||||
if (state != STATE_NAME_SEPARATOR) return SPDK_JSON_PARSE_INVALID;
|
if (state != STATE_NAME_SEPARATOR) goto done_invalid;
|
||||||
data++;
|
data++;
|
||||||
state = STATE_VALUE;
|
state = STATE_VALUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '/':
|
case '/':
|
||||||
if (!(flags & SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS)) {
|
if (!(flags & SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS)) {
|
||||||
return SPDK_JSON_PARSE_INVALID;
|
goto done_invalid;
|
||||||
}
|
}
|
||||||
rc = json_valid_comment(data, json_end);
|
rc = json_valid_comment(data, json_end);
|
||||||
if (rc < 0) return rc;
|
if (rc < 0) goto done_rc;
|
||||||
/* Skip over comment */
|
/* Skip over comment */
|
||||||
data += rc;
|
data += rc;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return SPDK_JSON_PARSE_INVALID;
|
goto done_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == STATE_END) {
|
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 */
|
/* Invalid end state - ran out of data */
|
||||||
|
rc = SPDK_JSON_PARSE_INCOMPLETE;
|
||||||
|
|
||||||
|
done_rc:
|
||||||
|
assert(rc < 0);
|
||||||
if (end) {
|
if (end) {
|
||||||
*end = data;
|
*end = data;
|
||||||
}
|
}
|
||||||
return SPDK_JSON_PARSE_INCOMPLETE;
|
return rc;
|
||||||
|
|
||||||
|
done_invalid:
|
||||||
|
rc = SPDK_JSON_PARSE_INVALID;
|
||||||
|
goto done_rc;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user