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

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.org



Reviewed-by: default avatarAndi Kleen <ak@linux.intel.com>
Reviewed-by: default avatarKajol <Jain&lt;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.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 08f3e087
Loading
Loading
Loading
Loading
+40 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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
}

/*