Commit e5377be2 authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-11562 Assertion `js->state == JST_VALUE' failed in...

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.
parent 8938031b
......@@ -295,13 +295,27 @@ int json_read_value(json_engine_t *j);
int json_skip_key(json_engine_t *j);
typedef const int *json_level_t;
/*
json_skip_to_level() makes parser quickly get out of nested
loops and arrays. It is used when we're not interested in what is
there in the rest of these structures.
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);
*/
#define json_get_level(j) (j->stack_p)
int json_skip_to_level(json_engine_t *j, json_level_t level);
/*
json_skip_level() makes parser quickly skip the JSON content
to the end of the current object or array.
It is used when we're not interested in the rest of an array
or the rest of the keys of an object.
json_skip_level() works as above with just current structre.
So it gets to the end of the current JSON array or object.
*/
int json_skip_level(json_engine_t *j);
#define json_skip_level(json_engine) \
json_skip_to_level((json_engine), (json_engine)->stack_p)
#define json_skip_array_item json_skip_key
......
......@@ -143,6 +143,12 @@ json_contains('[1, {"a":1}]', '{}')
select json_contains('[1, {"a":1}]', '{"a":1}');
json_contains('[1, {"a":1}]', '{"a":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]");
json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]")
1
......
......@@ -53,6 +53,8 @@ select json_contains('{"b":[1,2], "a":1}', '{"a":1, "b":2}');
select json_contains('{"a":1}', '{}');
select json_contains('[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[10]");
......
......@@ -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)
{
json_level_t c_level;
DBUG_ASSERT(js->state == JST_VALUE);
if (json_read_value(js))
return FALSE;
c_level= json_value_scalar(js) ? NULL : json_get_level(js);
if (check_contains(js, value))
{
if (json_skip_level(js))
return FALSE;
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;
......
......@@ -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;
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;
}
}
do {
if (j->stack_p < level)
return 0;
} while (json_scan_next(j) == 0);
return 1;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment