Messages in this thread | | | Date | Fri, 8 Oct 2021 15:12:03 +0200 | From | Jiri Olsa <> | Subject | Re: [PATCH 2/3] perf tools: Make the JSON parser more conformant when in strict mode |
| |
On Fri, Oct 08, 2021 at 11:08:25AM +0100, James Clark wrote: > > > On 07/10/2021 18:52, Jiri Olsa wrote: > > On Thu, Oct 07, 2021 at 12:05:41PM +0100, James Clark wrote: > >> 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 > >> > >> Signed-off-by: James Clark <james.clark@arm.com> > >> --- > >> tools/perf/pmu-events/jsmn.c | 42 ++++++++++++++++++++++++++++++++++-- > >> 1 file changed, 40 insertions(+), 2 deletions(-) > >> > >> diff --git a/tools/perf/pmu-events/jsmn.c b/tools/perf/pmu-events/jsmn.c > >> index 11d1fa18bfa5..8124d2d3ff0c 100644 > >> --- a/tools/perf/pmu-events/jsmn.c > >> +++ b/tools/perf/pmu-events/jsmn.c > >> @@ -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 > > > > I might have missed some discussion on this, but do we need the > > JSMN_STRICT define, if you enable it in the next patch? > > why can't we be more strict by default.. do you plan to disable > > it in future? > > I didn't plan on disabling it, I was just trying to keep to the existing style of the > jsmn project. > > I could have added the trailing comma detection by default and not inside any > #ifdef JSMN_STRICT blocks, but I would like to enable JSMN_STRICT anyway, because it > enables some additional built in checking that was already there. So I thought it > made sense to put my new strict stuff inside the existing strict option. > > One option would be to remove all (including the existing) #ifdef JSMN_STRICT blocks > and have everything strict by default. But it would be a further deviation from jsmn.
ok, I think it makes sense to have JSMN_STRICT then.. thanks for explanation
Acked-by: Jiri Olsa <jolsa@redhat.com>
jirka
> > Thanks > James > > > > > thanks, > > jirka > > > >> + /* > >> + * 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; > >> @@ -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; > >> @@ -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]; > >> @@ -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) > >> @@ -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. > >> @@ -253,6 +278,9 @@ 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. > >> @@ -260,6 +288,12 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, > >> /*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) > >> @@ -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 > >> } > >> > >> /* > >> -- > >> 2.28.0 > >> > > >
| |