mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-05 05:45:46 +00:00
json: cope with older yajl semantics
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@redhat.com>
This commit is contained in:
parent
39618d4088
commit
f2acaebd40
@ -36,9 +36,12 @@
|
|||||||
|
|
||||||
# ifdef WITH_YAJL2
|
# ifdef WITH_YAJL2
|
||||||
# define yajl_size_t size_t
|
# define yajl_size_t size_t
|
||||||
|
# define VIR_YAJL_STATUS_OK(status) ((status) == yajl_status_ok)
|
||||||
# else
|
# else
|
||||||
# define yajl_size_t unsigned int
|
# define yajl_size_t unsigned int
|
||||||
# define yajl_complete_parse yajl_parse_complete
|
# define yajl_complete_parse yajl_parse_complete
|
||||||
|
# define VIR_YAJL_STATUS_OK(status) \
|
||||||
|
((status) == yajl_status_ok || (status) == yajl_status_insufficient_data)
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1590,6 +1593,8 @@ virJSONValueFromString(const char *jsonstring)
|
|||||||
yajl_handle hand;
|
yajl_handle hand;
|
||||||
virJSONParser parser = { NULL, NULL, 0 };
|
virJSONParser parser = { NULL, NULL, 0 };
|
||||||
virJSONValuePtr ret = NULL;
|
virJSONValuePtr ret = NULL;
|
||||||
|
int rc;
|
||||||
|
size_t len = strlen(jsonstring);
|
||||||
# ifndef WITH_YAJL2
|
# ifndef WITH_YAJL2
|
||||||
yajl_parser_config cfg = { 1, 1 };
|
yajl_parser_config cfg = { 1, 1 };
|
||||||
# endif
|
# endif
|
||||||
@ -1611,9 +1616,8 @@ virJSONValueFromString(const char *jsonstring)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yajl_parse(hand,
|
rc = yajl_parse(hand, (const unsigned char *)jsonstring, len);
|
||||||
(const unsigned char *)jsonstring,
|
if (!VIR_YAJL_STATUS_OK(rc) ||
|
||||||
strlen(jsonstring)) != yajl_status_ok ||
|
|
||||||
yajl_complete_parse(hand) != yajl_status_ok) {
|
yajl_complete_parse(hand) != yajl_status_ok) {
|
||||||
unsigned char *errstr = yajl_get_error(hand, 1,
|
unsigned char *errstr = yajl_get_error(hand, 1,
|
||||||
(const unsigned char*)jsonstring,
|
(const unsigned char*)jsonstring,
|
||||||
@ -1622,7 +1626,7 @@ virJSONValueFromString(const char *jsonstring)
|
|||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot parse json %s: %s"),
|
_("cannot parse json %s: %s"),
|
||||||
jsonstring, (const char*) errstr);
|
jsonstring, (const char*) errstr);
|
||||||
VIR_FREE(errstr);
|
yajl_free_error(hand, errstr);
|
||||||
virJSONValueFree(parser.head);
|
virJSONValueFree(parser.head);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -416,7 +416,7 @@ mymain(void)
|
|||||||
DO_TEST_PARSE("boolean", "true");
|
DO_TEST_PARSE("boolean", "true");
|
||||||
DO_TEST_PARSE("null", "null");
|
DO_TEST_PARSE("null", "null");
|
||||||
DO_TEST_PARSE_FAIL("incomplete keyword", "tr");
|
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("unknown keyword", "huh");
|
||||||
|
|
||||||
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 }");
|
||||||
|
Loading…
Reference in New Issue
Block a user