diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 15da9211752a3..a5b21ad20294c 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -3022,4 +3022,68 @@ x NULL SELECT 1 FROM (SELECT JSON_REMOVE(46, DATE(NULL)) AS x EXCEPT SELECT 1) AS d WHERE NOT(NOT(x > 10)) AND (x < 1 OR x > 1); 1 +# +# MDEV-40572 SIGSEGV in JSON_OVERLAPS() on a truncated nested JSON object with different character sets/collations +# +SET @col=@@collation_connection; +SET @char=@@character_set_connection; +SET collation_connection=ucs2_general_ci; +SELECT JSON_OVERLAPS ('{"B":{}}', '{"B":{') AS exp_ucs2; +exp_ucs2 +0 +Warnings: +Warning 4037 Unexpected end of JSON text in argument 2 to function 'json_overlaps' +SET character_set_connection=utf16; +SELECT JSON_OVERLAPS ('{"B":{}}', '{"B":{') AS exp_utf16; +exp_utf16 +0 +Warnings: +Warning 4037 Unexpected end of JSON text in argument 2 to function 'json_overlaps' +SET @@collation_connection=@col; +SET @@character_set_connection=@char; +# +# MDEV-40165 JSON_EQUAL/JSON_NORMALIZE/JSON_CONTAINS error handling +# +CREATE TABLE t(c1 JSON, c2 JSON); +INSERT INTO t VALUES ('{"a":1,"b":2}', '{"b":2E0, "a":1E0}'), +(NULL, '["a", "b"]'), +('{"r": 1}', NULL), +('[{"a": 3}, {"d": [1, 2, 3]}]', '[{"d": [1E0, 2E0, 3E0]}, {"a":3E0}]'); +SELECT c1, JSON_EQUALS(c1, '{"r": 1E0}') AS je_c1_const FROM t; +c1 je_c1_const +{"a":1,"b":2} 0 +NULL NULL +{"r": 1} 1 +[{"a": 3}, {"d": [1, 2, 3]}] 0 +SELECT c1, c2, JSON_EQUALS(c1, c2) AS je_c1_c2 FROM t; +c1 c2 je_c1_c2 +{"a":1,"b":2} {"b":2E0, "a":1E0} 1 +NULL ["a", "b"] NULL +{"r": 1} NULL NULL +[{"a": 3}, {"d": [1, 2, 3]}] [{"d": [1E0, 2E0, 3E0]}, {"a":3E0}] 0 +SELECT c1, JSON_CONTAINS(c1, '{"r": 1E0}') AS jc_c1_const FROM t; +c1 jc_c1_const +{"a":1,"b":2} 0 +NULL NULL +{"r": 1} 1 +[{"a": 3}, {"d": [1, 2, 3]}] 0 +SELECT c1, c2, JSON_CONTAINS(c1, c2) AS jc_c1_c2 FROM t; +c1 c2 jc_c1_c2 +{"a":1,"b":2} {"b":2E0, "a":1E0} 1 +NULL ["a", "b"] NULL +{"r": 1} NULL NULL +[{"a": 3}, {"d": [1, 2, 3]}] [{"d": [1E0, 2E0, 3E0]}, {"a":3E0}] 1 +SELECT c1, JSON_OVERLAPS(c1, '{"r": 1E0}') AS jo_c1_const FROM t; +c1 jo_c1_const +{"a":1,"b":2} 0 +NULL NULL +{"r": 1} 1 +[{"a": 3}, {"d": [1, 2, 3]}] 0 +SELECT c1, c2, JSON_OVERLAPS(c1, c2) AS jo_c1_c2 FROM t; +c1 c2 jo_c1_c2 +{"a":1,"b":2} {"b":2E0, "a":1E0} 1 +NULL ["a", "b"] NULL +{"r": 1} NULL NULL +[{"a": 3}, {"d": [1, 2, 3]}] [{"d": [1E0, 2E0, 3E0]}, {"a":3E0}] 1 +DROP TABLE t; # End of 10.11 Test diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 58b806c78bdbc..6c181ce40f096 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -2150,4 +2150,39 @@ SELECT x FROM (SELECT 1 AS x UNION SELECT 2) AS t WHERE x IN ( SELECT JSON_REPL SELECT ( WITH RECURSIVE x ( x ) AS (WITH RECURSIVE x ( x ) AS ( SELECT 1 UNION SELECT x + 1 FROM x ) SELECT json_array_append ( '[[], [], []]' , NOT ( NULL LIKE 'ABC%' ) , 315 )) SELECT x FROM x WHERE x > 10 AND x < 1) AS x; SELECT 1 FROM (SELECT JSON_REMOVE(46, DATE(NULL)) AS x EXCEPT SELECT 1) AS d WHERE NOT(NOT(x > 10)) AND (x < 1 OR x > 1); +--echo # +--echo # MDEV-40572 SIGSEGV in JSON_OVERLAPS() on a truncated nested JSON object with different character sets/collations +--echo # + +SET @col=@@collation_connection; +SET @char=@@character_set_connection; + +SET collation_connection=ucs2_general_ci; +SELECT JSON_OVERLAPS ('{"B":{}}', '{"B":{') AS exp_ucs2; +SET character_set_connection=utf16; +SELECT JSON_OVERLAPS ('{"B":{}}', '{"B":{') AS exp_utf16; + +SET @@collation_connection=@col; +SET @@character_set_connection=@char; + +--echo # +--echo # MDEV-40165 JSON_EQUAL/JSON_NORMALIZE/JSON_CONTAINS error handling +--echo # + +CREATE TABLE t(c1 JSON, c2 JSON); +INSERT INTO t VALUES ('{"a":1,"b":2}', '{"b":2E0, "a":1E0}'), + (NULL, '["a", "b"]'), + ('{"r": 1}', NULL), + ('[{"a": 3}, {"d": [1, 2, 3]}]', '[{"d": [1E0, 2E0, 3E0]}, {"a":3E0}]'); + +SELECT c1, JSON_EQUALS(c1, '{"r": 1E0}') AS je_c1_const FROM t; +SELECT c1, c2, JSON_EQUALS(c1, c2) AS je_c1_c2 FROM t; + +SELECT c1, JSON_CONTAINS(c1, '{"r": 1E0}') AS jc_c1_const FROM t; +SELECT c1, c2, JSON_CONTAINS(c1, c2) AS jc_c1_c2 FROM t; + +SELECT c1, JSON_OVERLAPS(c1, '{"r": 1E0}') AS jo_c1_const FROM t; +SELECT c1, c2, JSON_OVERLAPS(c1, c2) AS jo_c1_c2 FROM t; +DROP TABLE t; + --echo # End of 10.11 Test diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 1681b555ca5e3..6acf31a8f6753 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -4877,24 +4877,24 @@ int compare_nested_object(json_engine_t *js, json_engine_t *value) if (json_normalize_engine(&je, &a_res, a.ptr(), a.length(), value->s.cs)) { value->s.error= je.s.error; - value->s.c_str= je.s.c_str; goto error; } if (json_normalize_engine(&je, &b_res, b.ptr(), b.length(), value->s.cs)) { js->s.error= je.s.error; - js->s.c_str= je.s.c_str; goto error; } result= strcmp(a_res.str, b_res.str) ? 0 : 1; - error: +error: dynstr_free(&a_res); dynstr_free(&b_res); return MY_TEST(result); } + + int json_find_overlap_with_object(json_engine_t *js, json_engine_t *value, bool compare_whole) {