From 07a62d49b03ba01f85457c438721cd4a89225c62 Mon Sep 17 00:00:00 2001 From: YASUOKA Masahiko Date: Sat, 13 Oct 2018 14:15:03 +0900 Subject: [PATCH] Disallow using an object or an array as a name for an object member. --- jsmn.c | 9 ++++++++- test/tests.c | 27 +++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/jsmn.c b/jsmn.c index 853c3f17..1768b2a2 100644 --- a/jsmn.c +++ b/jsmn.c @@ -170,7 +170,14 @@ int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, if (token == NULL) return JSMN_ERROR_NOMEM; if (parser->toksuper != -1) { - tokens[parser->toksuper].size++; + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; #ifdef JSMN_PARENT_LINKS token->parent = parser->toksuper; #endif diff --git a/test/tests.c b/test/tests.c index 31761cd3..df4ee02d 100644 --- a/test/tests.c +++ b/test/tests.c @@ -380,8 +380,30 @@ int test_unmatched_brackets(void) { JSMN_OBJECT, 0, 16, 1, JSMN_STRING, "key {1", 1, JSMN_PRIMITIVE, "1234")); - js = "{{\"key 1\": 1234}"; - check(parse(js, JSMN_ERROR_PART, 4)); + js = "{\"key 1\":{\"key 2\": 1234}"; + check(parse(js, JSMN_ERROR_PART, 5)); + return 0; +} + +int test_object_key(void) { + const char *js; + + js = "{\"key\": 1}"; + check(parse(js, 3, 3, + JSMN_OBJECT, 0, 10, 1, + JSMN_STRING, "key", 1, + JSMN_PRIMITIVE, "1")); +#ifdef JSMN_STRICT + js = "{true: 1}"; + check(parse(js, JSMN_ERROR_INVAL, 3)); + js = "{1: 1}"; + check(parse(js, JSMN_ERROR_INVAL, 3)); + js = "{{\"key\": 1}: 2}"; + check(parse(js, JSMN_ERROR_INVAL, 5)); + js = "{[1,2]: 2}"; + check(parse(js, JSMN_ERROR_INVAL, 5)); +#endif + return 0; } @@ -402,6 +424,7 @@ int main(void) { test(test_count, "test tokens count estimation"); test(test_nonstrict, "test for non-strict mode"); test(test_unmatched_brackets, "test for unmatched brackets"); + test(test_object_key, "test for key type"); printf("\nPASSED: %d\nFAILED: %d\n", test_passed, test_failed); return (test_failed > 0); }