Commit 21813684 authored by James Clark's avatar James Clark Committed by Arnaldo Carvalho de Melo

perf tools: Make the JSON parser more conformant when in strict mode

Return an error when a trailing comma is found or a new item is
encountered before a comma or an opening brace. This ensures that the
perf JSON files conform more closely to the spec at https://www.json.orgReviewed-by: default avatarAndi Kleen <ak@linux.intel.com>
Reviewed-by: Kajol Jain<kjain@linux.ibm.com>
Signed-off-by: default avatarJames Clark <james.clark@arm.com>
Acked-by: default avatarJiri Olsa <jolsa@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andrew.Kilroy@arm.com
Cc: John Garry <john.garry@huawei.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nick.Forrington@arm.com
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20211007110543.564963-3-james.clark@arm.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 08f3e087
...@@ -176,6 +176,14 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, ...@@ -176,6 +176,14 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
jsmnerr_t r; jsmnerr_t r;
int i; int i;
jsmntok_t *token; jsmntok_t *token;
#ifdef JSMN_STRICT
/*
* Keeps track of whether a new object/list/primitive is expected. New items are only
* allowed after an opening brace, comma or colon. A closing brace after a comma is not
* valid JSON.
*/
int expecting_item = 1;
#endif
for (; parser->pos < len; parser->pos++) { for (; parser->pos < len; parser->pos++) {
char c; char c;
...@@ -185,6 +193,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, ...@@ -185,6 +193,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
switch (c) { switch (c) {
case '{': case '{':
case '[': case '[':
#ifdef JSMN_STRICT
if (!expecting_item)
return JSMN_ERROR_INVAL;
#endif
token = jsmn_alloc_token(parser, tokens, num_tokens); token = jsmn_alloc_token(parser, tokens, num_tokens);
if (token == NULL) if (token == NULL)
return JSMN_ERROR_NOMEM; return JSMN_ERROR_NOMEM;
...@@ -196,6 +208,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, ...@@ -196,6 +208,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
break; break;
case '}': case '}':
case ']': case ']':
#ifdef JSMN_STRICT
if (expecting_item)
return JSMN_ERROR_INVAL;
#endif
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
for (i = parser->toknext - 1; i >= 0; i--) { for (i = parser->toknext - 1; i >= 0; i--) {
token = &tokens[i]; token = &tokens[i];
...@@ -219,6 +235,11 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, ...@@ -219,6 +235,11 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
} }
break; break;
case '\"': case '\"':
#ifdef JSMN_STRICT
if (!expecting_item)
return JSMN_ERROR_INVAL;
expecting_item = 0;
#endif
r = jsmn_parse_string(parser, js, len, tokens, r = jsmn_parse_string(parser, js, len, tokens,
num_tokens); num_tokens);
if (r < 0) if (r < 0)
...@@ -229,11 +250,15 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, ...@@ -229,11 +250,15 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
case '\t': case '\t':
case '\r': case '\r':
case '\n': case '\n':
case ':':
case ',':
case ' ': case ' ':
break; break;
#ifdef JSMN_STRICT #ifdef JSMN_STRICT
case ':':
case ',':
if (expecting_item)
return JSMN_ERROR_INVAL;
expecting_item = 1;
break;
/* /*
* In strict mode primitives are: * In strict mode primitives are:
* numbers and booleans. * numbers and booleans.
...@@ -253,6 +278,9 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, ...@@ -253,6 +278,9 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
case 'f': case 'f':
case 'n': case 'n':
#else #else
case ':':
case ',':
break;
/* /*
* In non-strict mode every unquoted value * In non-strict mode every unquoted value
* is a primitive. * is a primitive.
...@@ -260,6 +288,12 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, ...@@ -260,6 +288,12 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
/*FALL THROUGH */ /*FALL THROUGH */
default: default:
#endif #endif
#ifdef JSMN_STRICT
if (!expecting_item)
return JSMN_ERROR_INVAL;
expecting_item = 0;
#endif
r = jsmn_parse_primitive(parser, js, len, tokens, r = jsmn_parse_primitive(parser, js, len, tokens,
num_tokens); num_tokens);
if (r < 0) if (r < 0)
...@@ -282,7 +316,11 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, ...@@ -282,7 +316,11 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
return JSMN_ERROR_PART; return JSMN_ERROR_PART;
} }
#ifdef JSMN_STRICT
return expecting_item ? JSMN_ERROR_INVAL : JSMN_SUCCESS;
#else
return JSMN_SUCCESS; return JSMN_SUCCESS;
#endif
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment