Subject: Re: [PATCH 2/3] perf tools: Make the JSON parser more conformant when in strict mode

From: Arnaldo Carvalho de Melo <[email-masked]>
Date: Fri, 8 Oct 2021 15:56:26 -0300

Em Fri, Oct 08, 2021 at 03:12:03PM +0200, Jiri Olsa escreveu:
> 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 <[email-masked]>
> > >> ---
> > >>  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 <[email-masked]>

So, is this for the whole patchset? b4 picked it just for this message.

- Arnaldo
 
> 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
> > >>
> > > 
> > 

-- 

- Arnaldo

_______________________________________________
linux-arm-kernel mailing list
[email-masked]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel