Commit ceb496e5 fails on RHEL 6, with yajl 1.0.7, because that version of yajl returns yajl_status_insufficient_data when the parser is waiting for the rest of a token (this enum value was dropped in yajl 2, so we have to wrap it). It also exposes a problem where older yajl silently ignores trailing garbage after a successful parse, so this patch works around that by changing the testsuite. Another more invasive patch can add tighter semantics to json parsing, but this is sufficient for a minimal clean backport. While touching this, fix up our error message cleanup. Yajl documents that error messages produced by yajl_get_error() MUST be cleaned with yajl_free_error(); this is certainly true if we were to pass non-NULL allocator callbacks during yajl_alloc(), but probably harmless in our usage of passing NULL. But better safe than sorry. * src/util/virjson.c (virJSONValueFromString): Allow different error code. Use canonical cleanup of error message. (VIR_YAJL_STATUS_OK): New helper macro. * tests/jsontest.c (mymain): Wrap text to avoid difference in trailing garbage handling Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- src/util/virjson.c | 12 ++++++++---- tests/jsontest.c | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/util/virjson.c b/src/util/virjson.c index 29e2c39..4257b30 100644 --- a/src/util/virjson.c +++ b/src/util/virjson.c @@ -36,9 +36,12 @@ # ifdef WITH_YAJL2 # define yajl_size_t size_t +# define VIR_YAJL_STATUS_OK(status) ((status) == yajl_status_ok) # else # define yajl_size_t unsigned int # define yajl_complete_parse yajl_parse_complete +# define VIR_YAJL_STATUS_OK(status) \ + ((status) == yajl_status_ok || (status) == yajl_status_insufficient_data) # endif #endif @@ -1590,6 +1593,8 @@ virJSONValueFromString(const char *jsonstring) yajl_handle hand; virJSONParser parser = { NULL, NULL, 0 }; virJSONValuePtr ret = NULL; + int rc; + size_t len = strlen(jsonstring); # ifndef WITH_YAJL2 yajl_parser_config cfg = { 1, 1 }; # endif @@ -1611,9 +1616,8 @@ virJSONValueFromString(const char *jsonstring) goto cleanup; } - if (yajl_parse(hand, - (const unsigned char *)jsonstring, - strlen(jsonstring)) != yajl_status_ok || + rc = yajl_parse(hand, (const unsigned char *)jsonstring, len); + if (!VIR_YAJL_STATUS_OK(rc) || yajl_complete_parse(hand) != yajl_status_ok) { unsigned char *errstr = yajl_get_error(hand, 1, (const unsigned char*)jsonstring, @@ -1622,7 +1626,7 @@ virJSONValueFromString(const char *jsonstring) virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot parse json %s: %s"), jsonstring, (const char*) errstr); - VIR_FREE(errstr); + yajl_free_error(hand, errstr); virJSONValueFree(parser.head); goto cleanup; } diff --git a/tests/jsontest.c b/tests/jsontest.c index 34a07ee..8ac0970 100644 --- a/tests/jsontest.c +++ b/tests/jsontest.c @@ -416,7 +416,7 @@ mymain(void) DO_TEST_PARSE("boolean", "true"); DO_TEST_PARSE("null", "null"); DO_TEST_PARSE_FAIL("incomplete keyword", "tr"); - DO_TEST_PARSE_FAIL("overdone keyword", "truest"); + DO_TEST_PARSE_FAIL("overdone keyword", "[ truest ]"); DO_TEST_PARSE_FAIL("unknown keyword", "huh"); DO_TEST_PARSE_FAIL("object with numeric keys", "{ 1:1, 2:1, 3:2 }"); -- 2.4.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list