From c2854c7863aa01895febfb6503f542fce6825bd6 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 14 Oct 2019 16:45:51 +0200 Subject: [PATCH 1/6] MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes Data should be sent with length. --- mysql-test/r/processlist.result | 1 + mysql-test/r/processlist_MDEV-20466.result | Bin 0 -> 775 bytes mysql-test/t/processlist.test | 2 ++ mysql-test/t/processlist_MDEV-20466.test | 35 +++++++++++++++++++++ sql/sql_show.cc | 8 +++-- 5 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/processlist_MDEV-20466.result create mode 100644 mysql-test/t/processlist_MDEV-20466.test diff --git a/mysql-test/r/processlist.result b/mysql-test/r/processlist.result index eb3af67c5bf..55d2425d269 100644 --- a/mysql-test/r/processlist.result +++ b/mysql-test/r/processlist.result @@ -17,3 +17,4 @@ select command, time < 5 from information_schema.processlist where id != connect command time < 5 Sleep 1 set debug_sync='reset'; +End of 5.5 tests diff --git a/mysql-test/r/processlist_MDEV-20466.result b/mysql-test/r/processlist_MDEV-20466.result new file mode 100644 index 0000000000000000000000000000000000000000..7120212d0f03a73094a9dd164838e3ef9a6a9e20 GIT binary patch literal 775 zcmbtSUvJYe5a-qX6esPWOoD0xwue=FD6O|fYMT*fR7glsnmCJD;_G~lO8E4g(}AE* zNW3Ju*!TN)cLtEwhQMp`Q0D|WI89yS!PmJ5V~eIMHNn>l*!5mdMrQ!3D{8(MYH0H( zJ}pgEfk*I8bCa(%9BOPdRE8f6x-&L+{hQF7+cMmAy6Q-Wuc6oY0Xb#PF>!OxAiq@c zd*1~q%t?BmyPSCg@_>$eX5t1G*Qa01sg1HEuJMCDJ{_X?dOBBQiN~W-oA0O^A^<^`^f$>gP z=ydiCjm>cHO>2H=P|@9HwqgSr^|lyKxosuqDR2M|Zj*QoZBNh5WT>}GnaJbO&6u#& zuf~85sL^^4uiu|fL;DG<#RF_-QJUSx$)7YQj;5oi6c0=)mPlTdJ2A($<$;LQv|1?7 zW<_Kx6!#7vc@1b3Erdh#Vi~J6+sxKdghdgbLLefIxZdW*8~Yf7DUhK~V;pW}YxNIM iLE6!%_@9J+Gya_u@OTo*|9AkBmyq}2a&mdxhS5)qp!L20 literal 0 HcmV?d00001 diff --git a/mysql-test/t/processlist.test b/mysql-test/t/processlist.test index a8f8a4ed64c..8a8995f43b0 100644 --- a/mysql-test/t/processlist.test +++ b/mysql-test/t/processlist.test @@ -50,3 +50,5 @@ select command, time < 5 from information_schema.processlist where id != connect disconnect con1; set debug_sync='reset'; + +--echo End of 5.5 tests diff --git a/mysql-test/t/processlist_MDEV-20466.test b/mysql-test/t/processlist_MDEV-20466.test new file mode 100644 index 00000000000..70b56d25d72 --- /dev/null +++ b/mysql-test/t/processlist_MDEV-20466.test @@ -0,0 +1,35 @@ +--echo # This test has a result that includes \0 byte. +--echo # Such a byte makes diff to treat the whole file as binary, +--echo # and to refuse to diff it. +--echo # That's why this test is put in a separate file, +--echo # so that diff would still work on results of other tests. + +source include/have_debug.inc; +source include/have_debug_sync.inc; + +--echo # +--echo # MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes +--echo # + +connect (con1,localhost,root,,); + +#select * from information_schema.processlist; +connection con1; + +let $q= `select CONCAT("SELECT user FROM mysql.user WHERE user ='some", CHAR(0), "' or sleep (3)")`; + +SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync'; +--send_eval $q; + +connection default; + +SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; + +--replace_column 1 ID 3 HOST_NAME 6 TIME 9 TIME_MS +SHOW PROCESSLIST; + +disconnect con1; + +SET DEBUG_SYNC = 'RESET'; + +--echo End of 5.5 tests diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 0cf992ce25b..998432e8443 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2278,8 +2278,12 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) else protocol->store_null(); protocol->store(thd_info->state_info, system_charset_info); - protocol->store(thd_info->query_string.str(), - thd_info->query_string.charset()); + if (thd_info->query_string.length()) + protocol->store(thd_info->query_string.str(), + thd_info->query_string.length(), + thd_info->query_string.charset()); + else + protocol->store_null(); if (!thd->variables.old_mode && !(thd->variables.old_behavior & OLD_MODE_NO_PROGRESS_INFO)) protocol->store(thd_info->progress, 3, &store_buffer); From 4ba763db77a954e355cdb90a7ef30572e2a4317b Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 15 Oct 2019 12:24:23 +0200 Subject: [PATCH 2/6] MDEV-13172: Wrong result / SELECT ... WHERE EXISTS ... (with UNIQUE Key) IS NULL or <=> with unique field does not mean unique row, because several NULL possible, so we can not convert to normal join in this case. --- mysql-test/r/subselect_sj.result | 26 ++++++++++++++++++++++++++ mysql-test/r/subselect_sj_jcl6.result | 26 ++++++++++++++++++++++++++ mysql-test/t/subselect_sj.test | 26 ++++++++++++++++++++++++++ sql/opt_subselect.cc | 12 ++++++++++-- 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index d0b8b626ba2..6f4f363326a 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -3186,5 +3186,31 @@ create table t1 (a1 varchar(25)); create table t2 (a2 varchar(25)) ; insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2); drop table t1,t2; +# +# MDEV-13172: Wrong result / SELECT ... WHERE EXISTS ... (with UNIQUE Key) +# +CREATE TABLE `t1` ( +`Id` int(11) NOT NULL, +PRIMARY KEY (`Id`) +); +INSERT INTO `t1` (`Id`) VALUES (1); +CREATE TABLE `t2` ( +`t1_Id` int(11) NOT NULL DEFAULT 0, +`col1` int(11) DEFAULT NULL, +UNIQUE KEY `col1` (`col1`) +); +INSERT INTO `t2` (`t1_Id`, `col1`) VALUES (1, NULL), (1, NULL); +SELECT Id FROM t1 WHERE Id in (SELECT t1_Id FROM t2 WHERE t2.col1 IS NULL); +Id +1 +explain extended +SELECT Id FROM t1 WHERE Id in (SELECT t1_Id FROM t2 WHERE t2.col1 IS NULL); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 100.00 +1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 MATERIALIZED t2 ref col1 col1 5 const 1 100.00 Using index condition; Using where +Warnings: +Note 1003 select 1 AS `Id` from (`test`.`t2`) where ((`test`.`t2`.`t1_Id` = 1) and isnull(`test`.`t2`.`col1`)) +DROP TABLE t1, t2; # End of 5.5 test set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index e9a8b7301f7..6b5cf9dea1c 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -3200,6 +3200,32 @@ create table t1 (a1 varchar(25)); create table t2 (a2 varchar(25)) ; insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2); drop table t1,t2; +# +# MDEV-13172: Wrong result / SELECT ... WHERE EXISTS ... (with UNIQUE Key) +# +CREATE TABLE `t1` ( +`Id` int(11) NOT NULL, +PRIMARY KEY (`Id`) +); +INSERT INTO `t1` (`Id`) VALUES (1); +CREATE TABLE `t2` ( +`t1_Id` int(11) NOT NULL DEFAULT 0, +`col1` int(11) DEFAULT NULL, +UNIQUE KEY `col1` (`col1`) +); +INSERT INTO `t2` (`t1_Id`, `col1`) VALUES (1, NULL), (1, NULL); +SELECT Id FROM t1 WHERE Id in (SELECT t1_Id FROM t2 WHERE t2.col1 IS NULL); +Id +1 +explain extended +SELECT Id FROM t1 WHERE Id in (SELECT t1_Id FROM t2 WHERE t2.col1 IS NULL); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 100.00 +1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 MATERIALIZED t2 ref col1 col1 5 const 1 100.00 Using index condition; Using where +Warnings: +Note 1003 select 1 AS `Id` from (`test`.`t2`) where ((`test`.`t2`.`t1_Id` = 1) and isnull(`test`.`t2`.`col1`)) +DROP TABLE t1, t2; # End of 5.5 test set optimizer_switch=@subselect_sj_tmp; # diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index 6b59049bc4f..befa2c7af5a 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2881,6 +2881,32 @@ insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2); drop table t1,t2; + +--echo # +--echo # MDEV-13172: Wrong result / SELECT ... WHERE EXISTS ... (with UNIQUE Key) +--echo # + +CREATE TABLE `t1` ( + `Id` int(11) NOT NULL, + PRIMARY KEY (`Id`) +); + +INSERT INTO `t1` (`Id`) VALUES (1); + +CREATE TABLE `t2` ( + `t1_Id` int(11) NOT NULL DEFAULT 0, + `col1` int(11) DEFAULT NULL, + UNIQUE KEY `col1` (`col1`) +); + +INSERT INTO `t2` (`t1_Id`, `col1`) VALUES (1, NULL), (1, NULL); + +SELECT Id FROM t1 WHERE Id in (SELECT t1_Id FROM t2 WHERE t2.col1 IS NULL); +explain extended +SELECT Id FROM t1 WHERE Id in (SELECT t1_Id FROM t2 WHERE t2.col1 IS NULL); + +DROP TABLE t1, t2; + --echo # End of 5.5 test # The following command must be the last one the file diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index cb821325e57..f876129aed7 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -2640,9 +2640,17 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables) { do /* For all equalities on all key parts */ { - /* Check if this is "t.keypart = expr(outer_tables) */ + /* + Check if this is "t.keypart = expr(outer_tables) + + Don't allow variants that can produce duplicates: + - Dont allow "ref or null" + - the keyuse (that is, the operation) must be null-rejecting, + unless the other expression is non-NULLable. + */ if (!(keyuse->used_tables & sj_inner_tables) && - !(keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)) + !(keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && + (keyuse->null_rejecting || !keyuse->val->maybe_null)) { bound_parts |= 1 << keyuse->keypart; } From b7bc8c3fcbe718717934b404963305c6772a5c23 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 15 Oct 2019 19:28:24 +0200 Subject: [PATCH 3/6] MDEV-20466: fix of test suite --- mysql-test/r/processlist.result | 6 ++++ mysql-test/r/processlist_MDEV-20466.result | Bin 775 -> 0 bytes mysql-test/t/processlist.test | 29 +++++++++++++++++ mysql-test/t/processlist_MDEV-20466.test | 35 --------------------- 4 files changed, 35 insertions(+), 35 deletions(-) delete mode 100644 mysql-test/r/processlist_MDEV-20466.result delete mode 100644 mysql-test/t/processlist_MDEV-20466.test diff --git a/mysql-test/r/processlist.result b/mysql-test/r/processlist.result index 55d2425d269..24802cb2425 100644 --- a/mysql-test/r/processlist.result +++ b/mysql-test/r/processlist.result @@ -17,4 +17,10 @@ select command, time < 5 from information_schema.processlist where id != connect command time < 5 Sleep 1 set debug_sync='reset'; +# +# MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes +# +SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync'; +SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; +SET DEBUG_SYNC = 'RESET'; End of 5.5 tests diff --git a/mysql-test/r/processlist_MDEV-20466.result b/mysql-test/r/processlist_MDEV-20466.result deleted file mode 100644 index 7120212d0f03a73094a9dd164838e3ef9a6a9e20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 775 zcmbtSUvJYe5a-qX6esPWOoD0xwue=FD6O|fYMT*fR7glsnmCJD;_G~lO8E4g(}AE* zNW3Ju*!TN)cLtEwhQMp`Q0D|WI89yS!PmJ5V~eIMHNn>l*!5mdMrQ!3D{8(MYH0H( zJ}pgEfk*I8bCa(%9BOPdRE8f6x-&L+{hQF7+cMmAy6Q-Wuc6oY0Xb#PF>!OxAiq@c zd*1~q%t?BmyPSCg@_>$eX5t1G*Qa01sg1HEuJMCDJ{_X?dOBBQiN~W-oA0O^A^<^`^f$>gP z=ydiCjm>cHO>2H=P|@9HwqgSr^|lyKxosuqDR2M|Zj*QoZBNh5WT>}GnaJbO&6u#& zuf~85sL^^4uiu|fL;DG<#RF_-QJUSx$)7YQj;5oi6c0=)mPlTdJ2A($<$;LQv|1?7 zW<_Kx6!#7vc@1b3Erdh#Vi~J6+sxKdghdgbLLefIxZdW*8~Yf7DUhK~V;pW}YxNIM iLE6!%_@9J+Gya_u@OTo*|9AkBmyq}2a&mdxhS5)qp!L20 diff --git a/mysql-test/t/processlist.test b/mysql-test/t/processlist.test index 8a8995f43b0..52cb6b31919 100644 --- a/mysql-test/t/processlist.test +++ b/mysql-test/t/processlist.test @@ -51,4 +51,33 @@ select command, time < 5 from information_schema.processlist where id != connect disconnect con1; set debug_sync='reset'; +--echo # +--echo # MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes +--echo # + +connect (con1,localhost,root,,); + +connection con1; + +let $q= `select CONCAT("SELECT user FROM mysql.user WHERE user ='some", CHAR(0), "' or sleep (30)")`; + +SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync'; +--disable_query_log +--send_eval $q; +--enable_query_log +connection default; + +SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; + +exec $MYSQL test -e "SHOW PROCESSLIST" > $MYSQLTEST_VARDIR/tmp/MDEV-20466.text; + +let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/MDEV-20466.text; +let SEARCH_PATTERN=sleep; +source include/search_pattern_in_file.inc; +remove_file $MYSQLTEST_VARDIR/tmp//MDEV-20466.text; + +disconnect con1; + +SET DEBUG_SYNC = 'RESET'; + --echo End of 5.5 tests diff --git a/mysql-test/t/processlist_MDEV-20466.test b/mysql-test/t/processlist_MDEV-20466.test deleted file mode 100644 index 70b56d25d72..00000000000 --- a/mysql-test/t/processlist_MDEV-20466.test +++ /dev/null @@ -1,35 +0,0 @@ ---echo # This test has a result that includes \0 byte. ---echo # Such a byte makes diff to treat the whole file as binary, ---echo # and to refuse to diff it. ---echo # That's why this test is put in a separate file, ---echo # so that diff would still work on results of other tests. - -source include/have_debug.inc; -source include/have_debug_sync.inc; - ---echo # ---echo # MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes ---echo # - -connect (con1,localhost,root,,); - -#select * from information_schema.processlist; -connection con1; - -let $q= `select CONCAT("SELECT user FROM mysql.user WHERE user ='some", CHAR(0), "' or sleep (3)")`; - -SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync'; ---send_eval $q; - -connection default; - -SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; - ---replace_column 1 ID 3 HOST_NAME 6 TIME 9 TIME_MS -SHOW PROCESSLIST; - -disconnect con1; - -SET DEBUG_SYNC = 'RESET'; - ---echo End of 5.5 tests From c9b5280371b0ceddb9a805f0bc4cd5265d9fab86 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Sat, 19 Oct 2019 10:01:26 +0200 Subject: [PATCH 4/6] MDEV-20466: fix of embedded test suite --- mysql-test/r/processlist.result | 6 ---- mysql-test/r/processlist_notembedded.result | 7 +++++ mysql-test/t/processlist.test | 29 ------------------ mysql-test/t/processlist_notembedded.test | 34 +++++++++++++++++++++ 4 files changed, 41 insertions(+), 35 deletions(-) create mode 100644 mysql-test/r/processlist_notembedded.result create mode 100644 mysql-test/t/processlist_notembedded.test diff --git a/mysql-test/r/processlist.result b/mysql-test/r/processlist.result index 24802cb2425..55d2425d269 100644 --- a/mysql-test/r/processlist.result +++ b/mysql-test/r/processlist.result @@ -17,10 +17,4 @@ select command, time < 5 from information_schema.processlist where id != connect command time < 5 Sleep 1 set debug_sync='reset'; -# -# MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes -# -SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync'; -SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; -SET DEBUG_SYNC = 'RESET'; End of 5.5 tests diff --git a/mysql-test/r/processlist_notembedded.result b/mysql-test/r/processlist_notembedded.result new file mode 100644 index 00000000000..f5b2a310813 --- /dev/null +++ b/mysql-test/r/processlist_notembedded.result @@ -0,0 +1,7 @@ +# +# MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes +# +SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync'; +SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; +SET DEBUG_SYNC = 'RESET'; +End of 5.5 tests diff --git a/mysql-test/t/processlist.test b/mysql-test/t/processlist.test index 52cb6b31919..8a8995f43b0 100644 --- a/mysql-test/t/processlist.test +++ b/mysql-test/t/processlist.test @@ -51,33 +51,4 @@ select command, time < 5 from information_schema.processlist where id != connect disconnect con1; set debug_sync='reset'; ---echo # ---echo # MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes ---echo # - -connect (con1,localhost,root,,); - -connection con1; - -let $q= `select CONCAT("SELECT user FROM mysql.user WHERE user ='some", CHAR(0), "' or sleep (30)")`; - -SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync'; ---disable_query_log ---send_eval $q; ---enable_query_log -connection default; - -SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; - -exec $MYSQL test -e "SHOW PROCESSLIST" > $MYSQLTEST_VARDIR/tmp/MDEV-20466.text; - -let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/MDEV-20466.text; -let SEARCH_PATTERN=sleep; -source include/search_pattern_in_file.inc; -remove_file $MYSQLTEST_VARDIR/tmp//MDEV-20466.text; - -disconnect con1; - -SET DEBUG_SYNC = 'RESET'; - --echo End of 5.5 tests diff --git a/mysql-test/t/processlist_notembedded.test b/mysql-test/t/processlist_notembedded.test new file mode 100644 index 00000000000..dc970cf5709 --- /dev/null +++ b/mysql-test/t/processlist_notembedded.test @@ -0,0 +1,34 @@ +source include/have_debug.inc; +source include/have_debug_sync.inc; +source include/not_embedded.inc; + +--echo # +--echo # MDEV-20466: SHOW PROCESSLIST truncates query text on \0 bytes +--echo # + +connect (con1,localhost,root,,); + +connection con1; + +let $q= `select CONCAT("SELECT user FROM mysql.user WHERE user ='some", CHAR(0), "' or sleep (30)")`; + +SET DEBUG_SYNC= 'before_join_optimize SIGNAL in_sync'; +--disable_query_log +--send_eval $q; +--enable_query_log +connection default; + +SET DEBUG_SYNC= 'now WAIT_FOR in_sync'; + +exec $MYSQL test -e "SHOW PROCESSLIST" > $MYSQLTEST_VARDIR/tmp/MDEV-20466.text; + +let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/MDEV-20466.text; +let SEARCH_PATTERN=sleep; +source include/search_pattern_in_file.inc; +remove_file $MYSQLTEST_VARDIR/tmp//MDEV-20466.text; + +disconnect con1; + +SET DEBUG_SYNC = 'RESET'; + +--echo End of 5.5 tests From 412e3e6917233fe612354622a18b3f9cdf3a350c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 13 Sep 2019 09:52:30 +0200 Subject: [PATCH 5/6] MDEV-9546 mysqlaccess script shows an old version (which was vulnerable to CVE-2005-0004) update mysqlaccess version --- scripts/mysqlaccess.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysqlaccess.sh b/scripts/mysqlaccess.sh index b75a8b74ece..6f2fb5aae7d 100644 --- a/scripts/mysqlaccess.sh +++ b/scripts/mysqlaccess.sh @@ -26,7 +26,7 @@ use Fcntl; BEGIN { # **************************** # static information... - $VERSION = "2.06, 20 Dec 2000"; + $VERSION = "2.10, 13 Sep 2019"; $0 =~ m%/([^/]+)$%o; $script = $1; $script = 'MySQLAccess' unless $script; From 719ac0ad4af0dd1e20dbc94eff8f8c9f786b3393 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 19 Oct 2019 09:32:11 +0200 Subject: [PATCH 6/6] crash in string-to-int conversion using a specially crafted strings one could overflow `shift` variable and cause a crash by dereferencing d10[-2147483648] (on a sufficiently old gcc). This is a correct fix and a test case for Bug #29723340: MYSQL SERVER CRASH AFTER SQL QUERY WITH DATA ?AST --- mysql-test/r/func_math.result | 40 +++++++++++++++++++++++++++++++++++ mysql-test/t/func_math.test | 25 ++++++++++++++++++++++ strings/ctype-simple.c | 18 ++++++++++++---- 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 6edaa2e4d96..7e010297885 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -829,5 +829,45 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; # +# Bug #29723340: MYSQL SERVER CRASH AFTER SQL QUERY WITH DATA ?AST +# +create table t1(a int); +insert t1 values("1e-214748364"); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +insert t1 values("1e-2147483648"); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +insert t1 values("1e-21474836480"); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +insert t1 values("1e+214748364"); +Warnings: +Warning 1264 Out of range value for column 'a' at row 1 +insert t1 values("1e+2147483647"); +Warnings: +Warning 1264 Out of range value for column 'a' at row 1 +insert t1 values("1e+21474836470"); +Warnings: +Warning 1264 Out of range value for column 'a' at row 1 +set global max_allowed_packet= cast(2*1024*1024*1024+1024 as unsigned); +Warnings: +Warning 1292 Truncated incorrect max_allowed_packet value: '2147484672' +set @a=2147483647; +insert t1 values (concat('1', repeat('0', @a+18), 'e-', @a-1, '0')); +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1073741824) - truncated +set global max_allowed_packet=default; +select * from t1; +a +0 +0 +0 +2147483647 +2147483647 +2147483647 +NULL +drop table t1; +# # End of 5.5 tests # diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 1b5fa519c09..aca81e96de1 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -614,6 +614,31 @@ SHOW CREATE TABLE t1; DROP TABLE t1; +--echo # +--echo # Bug #29723340: MYSQL SERVER CRASH AFTER SQL QUERY WITH DATA ?AST +--echo # + +create table t1(a int); +insert t1 values("1e-214748364"); +insert t1 values("1e-2147483648"); +insert t1 values("1e-21474836480"); +insert t1 values("1e+214748364"); +insert t1 values("1e+2147483647"); +insert t1 values("1e+21474836470"); + +# if max max_allowed_packet will ever be increased beyond 2GB, this could +# break again: +set global max_allowed_packet= cast(2*1024*1024*1024+1024 as unsigned); +connect foo,localhost,root; +set @a=2147483647; +insert t1 values (concat('1', repeat('0', @a+18), 'e-', @a-1, '0')); +disconnect foo; +connection default; +set global max_allowed_packet=default; + +select * from t1; +drop table t1; + --echo # --echo # End of 5.5 tests --echo # diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 5c9790966d8..ba446a7df54 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1,5 +1,5 @@ /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. + Copyright (c) 2009, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1524,10 +1524,20 @@ exp: /* [ E [ ] ] */ if (++str == end) goto ret_sign; } - for (exponent= 0 ; - str < end && (ch= (uchar) (*str - '0')) < 10; - str++) + if (shift > 0 && !negative_exp) + goto ret_too_big; + for (exponent= 0 ; str < end && (ch= (uchar) (*str - '0')) < 10; str++) { + if (negative_exp) + { + if (exponent - shift > DIGITS_IN_ULONGLONG) + goto ret_zero; + } + else + { + if (exponent + shift > DIGITS_IN_ULONGLONG) + goto ret_too_big; + } exponent= exponent * 10 + ch; } shift+= negative_exp ? -exponent : exponent;