On Mon, Jun 22, 2015 at 15:01:15 -0600, Eric Blake wrote:
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(a)redhat.com>
---
Could be squashed with 3/3, if desired.
src/util/virjson.c | 7 +++++--
tests/jsontest.c | 1 +
2 files changed, 6 insertions(+), 2 deletions(-)
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;
Boolean?
};
@@ -1556,7 +1557,7 @@ virJSONParserHandleEndArray(void *ctx)
VIR_DEBUG("parser=%p", parser);
- if (!parser->nstate)
+ if (!(parser->nstate - parser->wrap))
Yuck! This really covers up what's happening here.
if ((parser->nstate == 1 && parser->wrap) ||
(parser->nstate == 0 && !parser->wrap))
It takes two lines but you at least don't cover up the logic.
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;
True?
if (VIR_YAJL_STATUS_OK(rc))
rc = yajl_parse(hand, (const unsigned char *)jsonstring, len);
+ parser.wrap = 0;
False?
if (VIR_YAJL_STATUS_OK(rc))
rc = yajl_parse(hand, (const unsigned char *)"]", 1);
# endif
Peter