Commit f0a57acb authored by Alexander Barkov's avatar Alexander Barkov

MDEV-23535 SIGSEGV, SIGABRT and SIGILL in typeinfo for Item_func_set_collation...

MDEV-23535 SIGSEGV, SIGABRT and SIGILL in typeinfo for Item_func_set_collation (on optimized builds)

This piece of the code in Item_func_or_sum::agg_item_set_converter:

 if (!conv && ((*arg)->collation.repertoire == MY_REPERTOIRE_ASCII))
   conv= new (thd->mem_root) Item_func_conv_charset(thd, *arg, coll.collation, 1);

was wrong because:

1. It could change Item_cache to Item_func_conv_charset
  (with the old Item_cache in args[0]).
  Such Item type change is not always supported, e.g.
  the code in Item_singlerow_subselect::reset() expects only Item_cache,
  to be able to call Item_cache::set_null(). So it erroneously
  reinterpreted Item_func_conv_charset to Item_cache and called
  a non-existing method set_null(), which crashed the server.

2. The 1 in the last parameter to Item_func_conv_charset() was also
  a problem. In MariaDB versions where the reported query did not crash,
  it erroneously returned "empty set" instead of one row, because
  the 1 made subselects execute too earlier and return NULL.

Fix:

1. Removing the above two lines from Item_func_or_sum::agg_item_set_converter()

2. Adding the repertoire test inside the constructor of Item_func_conv_charset,
   so it now detects itself as "safe" in more cases than before.
   This is needed to avoid new "Illegal mix of collations" after
   removing the wrong code in various scenarios when character set
   conversion from pure ASCII happens, including the reported scenario.

So now this sequence:

   Item_cache -> Item_func_concat

is replaced to this compatible sequence (the top Item is still Item_cache):

   new Item_cache -> Item_func_conv_charset -> Item_func_concat

Before the fix it was replaced to this incompatible sequence:

   Item_func_conv_charset -> old Item_cache -> Item_func_concat
parent 94a520dd
......@@ -10583,5 +10583,17 @@ SELECT CONVERT(1, CHAR) IN ('100', '10', '1');
CONVERT(1, CHAR) IN ('100', '10', '1')
1
#
# MDEV-23535 SIGSEGV, SIGABRT and SIGILL in typeinfo for Item_func_set_collation (on optimized builds)
#
SET NAMES utf8;
CREATE OR REPLACE TABLE t1(a DATETIME) ENGINE=MYISAM;
INSERT INTO t1 VALUES ('2019-03-10 02:55:05');
CREATE OR REPLACE TABLE t2(a VARCHAR(50) CHARACTER SET latin1) ENGINE=MYISAM;
INSERT INTO t2 VALUES ('2019-03-10 02:55:05');
SELECT * FROM t1 WHERE (SELECT 1,CONCAT(a) FROM t1) = (SELECT 1,CONCAT(a) FROM t2);
a
2019-03-10 02:55:05
DROP TABLE t1, t2;
#
# End of 10.1 tests
#
......@@ -615,3 +615,17 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2`,`test`.`t3`.`f3` AS `f3` from `test`.`t1` join `test`.`t2` semi join (`test`.`t4`) join `test`.`t3` where ((`test`.`t4`.`f4` = 1) and (`test`.`t1`.`f1` >= `test`.`t2`.`f2`))
DROP TABLE t1,t2,t3,t4;
#
# MDEV-23535: SIGSEGV, SIGABRT and SIGILL in typeinfo for Item_func_set_collation (on optimized builds)
#
set @save_character_set_connection=@@character_set_connection;
set character_set_connection='utf8';
CREATE TABLE t1(a DATETIME, b VARCHAR(50)) ENGINE=INNODB;
INSERT INTO t1 VALUES ('2019-03-10 02:55:05', '2019-03-10 02:55:05');
CREATE TABLE t2(a VARCHAR(50)) ENGINE=INNODB;
INSERT INTO t2 VALUES ('2019-03-10 02:55:05');
SELECT * FROM t1 WHERE (SELECT 1,CONCAT(a) FROM t1) = (SELECT 1,CONCAT(a) FROM t2);
a b
2019-03-10 02:55:05 2019-03-10 02:55:05
DROP TABLE t1,t2;
set character_set_connection=@save_character_set_connection;
......@@ -2040,6 +2040,18 @@ SELECT CONVERT(1, CHAR) IN ('100', 10, '101');
SELECT CONVERT(1, CHAR) IN ('100', 10, '1');
SELECT CONVERT(1, CHAR) IN ('100', '10', '1');
--echo #
--echo # MDEV-23535 SIGSEGV, SIGABRT and SIGILL in typeinfo for Item_func_set_collation (on optimized builds)
--echo #
SET NAMES utf8;
CREATE OR REPLACE TABLE t1(a DATETIME) ENGINE=MYISAM;
INSERT INTO t1 VALUES ('2019-03-10 02:55:05');
CREATE OR REPLACE TABLE t2(a VARCHAR(50) CHARACTER SET latin1) ENGINE=MYISAM;
INSERT INTO t2 VALUES ('2019-03-10 02:55:05');
SELECT * FROM t1 WHERE (SELECT 1,CONCAT(a) FROM t1) = (SELECT 1,CONCAT(a) FROM t2);
DROP TABLE t1, t2;
--echo #
--echo # End of 10.1 tests
......
......@@ -611,3 +611,19 @@ FROM t1
DROP TABLE t1,t2,t3,t4;
--echo #
--echo # MDEV-23535: SIGSEGV, SIGABRT and SIGILL in typeinfo for Item_func_set_collation (on optimized builds)
--echo #
set @save_character_set_connection=@@character_set_connection;
set character_set_connection='utf8';
CREATE TABLE t1(a DATETIME, b VARCHAR(50)) ENGINE=INNODB;
INSERT INTO t1 VALUES ('2019-03-10 02:55:05', '2019-03-10 02:55:05');
CREATE TABLE t2(a VARCHAR(50)) ENGINE=INNODB;
INSERT INTO t2 VALUES ('2019-03-10 02:55:05');
SELECT * FROM t1 WHERE (SELECT 1,CONCAT(a) FROM t1) = (SELECT 1,CONCAT(a) FROM t2);
DROP TABLE t1,t2;
set character_set_connection=@save_character_set_connection;
......@@ -2188,8 +2188,6 @@ bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll,
Item* conv= (*arg)->safe_charset_converter(thd, coll.collation);
if (conv == *arg)
continue;
if (!conv && ((*arg)->collation.repertoire == MY_REPERTOIRE_ASCII))
conv= new (thd->mem_root) Item_func_conv_charset(thd, *arg, coll.collation, 1);
if (!conv)
{
......
......@@ -1053,11 +1053,19 @@ class Item_func_conv_charset :public Item_str_func
/*
Conversion from and to "binary" is safe.
Conversion to Unicode is safe.
Conversion from an expression with the ASCII repertoire
to any character set that can store characters U+0000..U+007F
is safe:
- All supported multibyte character sets can store U+0000..U+007F
- All supported 7bit character sets can store U+0000..U+007F
except those marked with MY_CS_NONASCII (e.g. swe7).
Other kind of conversions are potentially lossy.
*/
safe= (args[0]->collation.collation == &my_charset_bin ||
cs == &my_charset_bin ||
(cs->state & MY_CS_UNICODE));
(cs->state & MY_CS_UNICODE) ||
(args[0]->collation.repertoire == MY_REPERTOIRE_ASCII &&
(cs->mbmaxlen > 1 || !(cs->state & MY_CS_NONASCII))));
}
}
String *val_str(String *);
......
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