1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-11562 Assertion `js->state == JST_VALUE' failed in check_contains(json_engine_t*, json_engine_t*).

check_contains() fixed. When an item of an array is a complex
        structure, it can be half-read after the end of the recursive
        check_contains() call. So we just manually get to it's ending.
This commit is contained in:
Alexey Botchkov
2016-12-16 12:32:56 +04:00
parent 8938031bc7
commit e5377be211
5 changed files with 36 additions and 24 deletions

View File

@ -295,13 +295,27 @@ int json_read_value(json_engine_t *j);
int json_skip_key(json_engine_t *j); int json_skip_key(json_engine_t *j);
typedef const int *json_level_t;
/* /*
json_skip_level() makes parser quickly skip the JSON content json_skip_to_level() makes parser quickly get out of nested
to the end of the current object or array. loops and arrays. It is used when we're not interested in what is
It is used when we're not interested in the rest of an array there in the rest of these structures.
or the rest of the keys of an object. The 'level' should be remembered in advance.
json_level_t level= json_get_level(j);
.... // getting into the nested JSON structures
json_skip_to_level(j, level);
*/ */
int json_skip_level(json_engine_t *j); #define json_get_level(j) (j->stack_p)
int json_skip_to_level(json_engine_t *j, json_level_t level);
/*
json_skip_level() works as above with just current structre.
So it gets to the end of the current JSON array or object.
*/
#define json_skip_level(json_engine) \
json_skip_to_level((json_engine), (json_engine)->stack_p)
#define json_skip_array_item json_skip_key #define json_skip_array_item json_skip_key

View File

@ -143,6 +143,12 @@ json_contains('[1, {"a":1}]', '{}')
select json_contains('[1, {"a":1}]', '{"a":1}'); select json_contains('[1, {"a":1}]', '{"a":1}');
json_contains('[1, {"a":1}]', '{"a":1}') json_contains('[1, {"a":1}]', '{"a":1}')
1 1
select json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]');
json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]')
0
select json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]');
json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]')
1
select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]"); select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]");
json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]") json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]")
1 1

View File

@ -53,6 +53,8 @@ select json_contains('{"b":[1,2], "a":1}', '{"a":1, "b":2}');
select json_contains('{"a":1}', '{}'); select json_contains('{"a":1}', '{}');
select json_contains('[1, {"a":1}]', '{}'); select json_contains('[1, {"a":1}]', '{}');
select json_contains('[1, {"a":1}]', '{"a":1}'); select json_contains('[1, {"a":1}]', '{"a":1}');
select json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]');
select json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]');
select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]"); select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]");
select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[10]"); select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[10]");

View File

@ -796,17 +796,20 @@ static int check_contains(json_engine_t *js, json_engine_t *value)
{ {
while (json_scan_next(js) == 0 && js->state != JST_ARRAY_END) while (json_scan_next(js) == 0 && js->state != JST_ARRAY_END)
{ {
json_level_t c_level;
DBUG_ASSERT(js->state == JST_VALUE); DBUG_ASSERT(js->state == JST_VALUE);
if (json_read_value(js)) if (json_read_value(js))
return FALSE; return FALSE;
c_level= json_value_scalar(js) ? NULL : json_get_level(js);
if (check_contains(js, value)) if (check_contains(js, value))
{ {
if (json_skip_level(js)) if (json_skip_level(js))
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
if (value->s.error || js->s.error) if (value->s.error || js->s.error ||
(c_level && json_skip_to_level(js, c_level)))
return FALSE; return FALSE;
} }
return FALSE; return FALSE;

View File

@ -1158,25 +1158,12 @@ int json_path_setup(json_path_t *p,
} }
int json_skip_level(json_engine_t *j) int json_skip_to_level(json_engine_t *j, json_level_t level)
{ {
int ct= 0; do {
if (j->stack_p < level)
while (json_scan_next(j) == 0) return 0;
{ } while (json_scan_next(j) == 0);
switch (j->state) {
case JST_OBJ_START:
case JST_ARRAY_START:
ct++;
break;
case JST_OBJ_END:
case JST_ARRAY_END:
if (ct == 0)
return 0;
ct--;
break;
}
}
return 1; return 1;
} }