mirror of https://gitee.com/openkylin/libvirt.git
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 <eblake@redhat.com>
This commit is contained in:
parent
7cd991b74c
commit
7e191fd939
|
@ -64,6 +64,7 @@ struct _virJSONParser {
|
||||||
virJSONValuePtr head;
|
virJSONValuePtr head;
|
||||||
virJSONParserStatePtr state;
|
virJSONParserStatePtr state;
|
||||||
size_t nstate;
|
size_t nstate;
|
||||||
|
int wrap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1556,7 +1557,7 @@ virJSONParserHandleEndArray(void *ctx)
|
||||||
|
|
||||||
VIR_DEBUG("parser=%p", parser);
|
VIR_DEBUG("parser=%p", parser);
|
||||||
|
|
||||||
if (!parser->nstate)
|
if (!(parser->nstate - parser->wrap))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
state = &(parser->state[parser->nstate-1]);
|
state = &(parser->state[parser->nstate-1]);
|
||||||
|
@ -1591,7 +1592,7 @@ virJSONValuePtr
|
||||||
virJSONValueFromString(const char *jsonstring)
|
virJSONValueFromString(const char *jsonstring)
|
||||||
{
|
{
|
||||||
yajl_handle hand;
|
yajl_handle hand;
|
||||||
virJSONParser parser = { NULL, NULL, 0 };
|
virJSONParser parser = { NULL, NULL, 0, 0 };
|
||||||
virJSONValuePtr ret = NULL;
|
virJSONValuePtr ret = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
size_t len = strlen(jsonstring);
|
size_t len = strlen(jsonstring);
|
||||||
|
@ -1627,8 +1628,10 @@ virJSONValueFromString(const char *jsonstring)
|
||||||
rc = yajl_parse(hand, (const unsigned char *)jsonstring, len);
|
rc = yajl_parse(hand, (const unsigned char *)jsonstring, len);
|
||||||
# else
|
# else
|
||||||
rc = yajl_parse(hand, (const unsigned char *)"[", 1);
|
rc = yajl_parse(hand, (const unsigned char *)"[", 1);
|
||||||
|
parser.wrap = 1;
|
||||||
if (VIR_YAJL_STATUS_OK(rc))
|
if (VIR_YAJL_STATUS_OK(rc))
|
||||||
rc = yajl_parse(hand, (const unsigned char *)jsonstring, len);
|
rc = yajl_parse(hand, (const unsigned char *)jsonstring, len);
|
||||||
|
parser.wrap = 0;
|
||||||
if (VIR_YAJL_STATUS_OK(rc))
|
if (VIR_YAJL_STATUS_OK(rc))
|
||||||
rc = yajl_parse(hand, (const unsigned char *)"]", 1);
|
rc = yajl_parse(hand, (const unsigned char *)"]", 1);
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -421,6 +421,7 @@ mymain(void)
|
||||||
DO_TEST_PARSE_FAIL("comments", "[ /* nope */\n1 // not this either\n]");
|
DO_TEST_PARSE_FAIL("comments", "[ /* nope */\n1 // not this either\n]");
|
||||||
DO_TEST_PARSE_FAIL("trailing garbage", "[] []");
|
DO_TEST_PARSE_FAIL("trailing garbage", "[] []");
|
||||||
DO_TEST_PARSE_FAIL("list without array", "1, 1");
|
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("object with numeric keys", "{ 1:1, 2:1, 3:2 }");
|
||||||
DO_TEST_PARSE_FAIL("unterminated object", "{ \"1\":1, \"2\":1, \"3\":2");
|
DO_TEST_PARSE_FAIL("unterminated object", "{ \"1\":1, \"2\":1, \"3\":2");
|
||||||
|
|
Loading…
Reference in New Issue