From 7e191fd939f04ccff58d9a17bdc68db3bdb8424d Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Jun 25 2015 07:11:15 +0000 Subject: json: even stricter trailing garbage detection Since older yajl ignores trailing garbage, a client can cause problems by intentionally ending the wrapper array early. Since we already track nesting, it's not too much harder to reject invalid nesting pops. * src/util/virjson. (_virJSONParser): Add field. (virJSONValueFromString): Set witness. (virJSONParserHandleEndArray): Use it to catch abuse. * tests/jsontest.c (mymain): Test it. Signed-off-by: Eric Blake --- diff --git a/src/util/virjson.c b/src/util/virjson.c index a33005a..3c6ed34 100644 --- a/src/util/virjson.c +++ b/src/util/virjson.c @@ -64,6 +64,7 @@ struct _virJSONParser { virJSONValuePtr head; virJSONParserStatePtr state; size_t nstate; + int wrap; }; @@ -1556,7 +1557,7 @@ virJSONParserHandleEndArray(void *ctx) VIR_DEBUG("parser=%p", parser); - if (!parser->nstate) + if (!(parser->nstate - parser->wrap)) return 0; state = &(parser->state[parser->nstate-1]); @@ -1591,7 +1592,7 @@ virJSONValuePtr virJSONValueFromString(const char *jsonstring) { yajl_handle hand; - virJSONParser parser = { NULL, NULL, 0 }; + virJSONParser parser = { NULL, NULL, 0, 0 }; virJSONValuePtr ret = NULL; int rc; size_t len = strlen(jsonstring); @@ -1627,8 +1628,10 @@ virJSONValueFromString(const char *jsonstring) rc = yajl_parse(hand, (const unsigned char *)jsonstring, len); # else rc = yajl_parse(hand, (const unsigned char *)"[", 1); + parser.wrap = 1; if (VIR_YAJL_STATUS_OK(rc)) rc = yajl_parse(hand, (const unsigned char *)jsonstring, len); + parser.wrap = 0; if (VIR_YAJL_STATUS_OK(rc)) rc = yajl_parse(hand, (const unsigned char *)"]", 1); # endif diff --git a/tests/jsontest.c b/tests/jsontest.c index a363dc0..97b9c0a 100644 --- a/tests/jsontest.c +++ b/tests/jsontest.c @@ -421,6 +421,7 @@ mymain(void) DO_TEST_PARSE_FAIL("comments", "[ /* nope */\n1 // not this either\n]"); DO_TEST_PARSE_FAIL("trailing garbage", "[] []"); DO_TEST_PARSE_FAIL("list without array", "1, 1"); + DO_TEST_PARSE_FAIL("parser abuse", "1] [2"); DO_TEST_PARSE_FAIL("object with numeric keys", "{ 1:1, 2:1, 3:2 }"); DO_TEST_PARSE_FAIL("unterminated object", "{ \"1\":1, \"2\":1, \"3\":2");