revision-id: e554cd1f31b8fecc0ec9ab7845a82a852e739b99 (mariadb-10.2.31-657-ge554cd1f31b) parent(s): cd1e5d65c6d3aab7f77860803d2d0f29bf307b4a author: Varun Gupta committer: Varun Gupta timestamp: 2021-01-08 13:01:38 +0530 message: MDEV-24519: Server crashes in Charset::set_charset upon SELECT The query causing the issue here has implicit grouping for we have to produce one row with special values for the aggregates (depending on each aggregate function), and NULL values for all non-aggregate fields. The subselect item where implicit grouping was being done, null_value for the subselect item was not being set for the case when the implcit grouping prodcues NULL values for the items in the select list for the subquery. This which was leading to the crash. The fix would be to set the null_value correctly in the val_* functions for Item_singlerow_subselect. --- mysql-test/r/subselect4.result | 27 +++++++++++++++++++++++++++ mysql-test/t/subselect4.test | 24 ++++++++++++++++++++++++ sql/item_subselect.cc | 27 +++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index c0df4f626b1..a9b89577462 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2686,4 +2686,31 @@ SELECT * FROM t2; f bar DROP TABLE t1, t2; +# +# MDEV-24519: Server crashes in Charset::set_charset upon SELECT +# +CREATE TABLE t1 (a VARBINARY(8)); +INSERT INTO t1 VALUES ('foo'),('bar'); +CREATE TABLE t2 (b VARBINARY(8)); +EXPLAIN +SELECT a FROM t1 WHERE (a, a) IN (SELECT 'qux', 'qux') AND a = (SELECT MIN(b) FROM t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +SELECT a FROM t1 WHERE (a, a) IN (SELECT 'qux', 'qux') AND a = (SELECT MIN(b) FROM t2); +a +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b VARBINARY(8)); +EXPLAIN +SELECT a FROM t1 WHERE (a, a) IN (SELECT 1, 2) AND a = (SELECT MIN(b) FROM t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +SELECT a FROM t1 WHERE (a, a) IN (SELECT 1, 2) AND a = (SELECT MIN(b) FROM t2); +a +DROP TABLE t1,t2; # End of 10.2 tests diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index 6eada9b27d9..7c6f294c25e 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -2201,4 +2201,28 @@ SELECT * FROM t2; DROP TABLE t1, t2; +--echo # +--echo # MDEV-24519: Server crashes in Charset::set_charset upon SELECT +--echo # + +CREATE TABLE t1 (a VARBINARY(8)); +INSERT INTO t1 VALUES ('foo'),('bar'); +CREATE TABLE t2 (b VARBINARY(8)); + +EXPLAIN +SELECT a FROM t1 WHERE (a, a) IN (SELECT 'qux', 'qux') AND a = (SELECT MIN(b) FROM t2); +SELECT a FROM t1 WHERE (a, a) IN (SELECT 'qux', 'qux') AND a = (SELECT MIN(b) FROM t2); + +DROP TABLE t1,t2; + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b VARBINARY(8)); + +EXPLAIN +SELECT a FROM t1 WHERE (a, a) IN (SELECT 1, 2) AND a = (SELECT MIN(b) FROM t2); +SELECT a FROM t1 WHERE (a, a) IN (SELECT 1, 2) AND a = (SELECT MIN(b) FROM t2); + +DROP TABLE t1,t2; + --echo # End of 10.2 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 802bfca64b7..f63bc944d6c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1308,7 +1308,11 @@ double Item_singlerow_subselect::val_real() { DBUG_ASSERT(fixed == 1); if (forced_const) + { + if ((null_value= value->null_value)) + return 0; return value->val_real(); + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1325,7 +1329,11 @@ longlong Item_singlerow_subselect::val_int() { DBUG_ASSERT(fixed == 1); if (forced_const) + { + if ((null_value= value->null_value)) + return 0; return value->val_int(); + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1342,7 +1350,14 @@ String *Item_singlerow_subselect::val_str(String *str) { DBUG_ASSERT(fixed == 1); if (forced_const) + { + if (value->null_value) + { + if ((null_value= value->null_value)) + return 0; + } return value->val_str(str); + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1360,7 +1375,11 @@ my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); if (forced_const) + { + if ((null_value= value->null_value)) + return 0; return value->val_decimal(decimal_value); + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1378,7 +1397,11 @@ bool Item_singlerow_subselect::val_bool() { DBUG_ASSERT(fixed == 1); if (forced_const) + { + if ((null_value= value->null_value)) + return 0; return value->val_bool(); + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1396,7 +1419,11 @@ bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) { DBUG_ASSERT(fixed == 1); if (forced_const) + { + if ((null_value= value->null_value)) + return 1; return value->get_date(ltime, fuzzydate); + } if (!exec() && !value->null_value) { null_value= FALSE;