Skip to content

Commit

Permalink
perf tools: Make the JSON parser more conformant when in strict mode
Browse files Browse the repository at this point in the history
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.org

Reviewed-by: Andi Kleen <[email protected]>
Reviewed-by: Kajol Jain<[email protected]>
Signed-off-by: James Clark <[email protected]>
Acked-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: [email protected]
Cc: John Garry <[email protected]>
Cc: Leo Yan <[email protected]>
Cc: Mark Rutland <[email protected]>
Cc: Mathieu Poirier <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: [email protected]
Cc: Will Deacon <[email protected]>
Cc: [email protected]
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
James-A-Clark authored and acmel committed Oct 8, 2021
1 parent 08f3e08 commit 2181368
Showing 1 changed file with 40 additions and 2 deletions.
42 changes: 40 additions & 2 deletions tools/perf/pmu-events/jsmn.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
jsmnerr_t r;
int i;
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++) {
char c;
Expand All @@ -185,6 +193,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
switch (c) {
case '{':
case '[':
#ifdef JSMN_STRICT
if (!expecting_item)
return JSMN_ERROR_INVAL;
#endif
token = jsmn_alloc_token(parser, tokens, num_tokens);
if (token == NULL)
return JSMN_ERROR_NOMEM;
Expand All @@ -196,6 +208,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
break;
case '}':
case ']':
#ifdef JSMN_STRICT
if (expecting_item)
return JSMN_ERROR_INVAL;
#endif
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
for (i = parser->toknext - 1; i >= 0; i--) {
token = &tokens[i];
Expand All @@ -219,6 +235,11 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
}
break;
case '\"':
#ifdef JSMN_STRICT
if (!expecting_item)
return JSMN_ERROR_INVAL;
expecting_item = 0;
#endif
r = jsmn_parse_string(parser, js, len, tokens,
num_tokens);
if (r < 0)
Expand All @@ -229,11 +250,15 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
case '\t':
case '\r':
case '\n':
case ':':
case ',':
case ' ':
break;
#ifdef JSMN_STRICT
case ':':
case ',':
if (expecting_item)
return JSMN_ERROR_INVAL;
expecting_item = 1;
break;
/*
* In strict mode primitives are:
* numbers and booleans.
Expand All @@ -253,13 +278,22 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
case 'f':
case 'n':
#else
case ':':
case ',':
break;
/*
* In non-strict mode every unquoted value
* is a primitive.
*/
/*FALL THROUGH */
default:
#endif

#ifdef JSMN_STRICT
if (!expecting_item)
return JSMN_ERROR_INVAL;
expecting_item = 0;
#endif
r = jsmn_parse_primitive(parser, js, len, tokens,
num_tokens);
if (r < 0)
Expand All @@ -282,7 +316,11 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
return JSMN_ERROR_PART;
}

#ifdef JSMN_STRICT
return expecting_item ? JSMN_ERROR_INVAL : JSMN_SUCCESS;
#else
return JSMN_SUCCESS;
#endif
}

/*
Expand Down

0 comments on commit 2181368

Please sign in to comment.