diff --git a/VERSION b/VERSION index fa6843f2474d8..9289180a2f935 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=11 -MYSQL_VERSION_PATCH=17 +MYSQL_VERSION_PATCH=18 SERVER_MATURITY=stable diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 356d41115984f..d32bd446bc7e1 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1942,6 +1942,14 @@ decrypt_decompress_file(const char *filepath, uint thread_n) msg(thread_n,"%s\n", message.str().c_str()); + /* all valid *.qp files are table-name-safe */ + for (const char *s=filepath; *s; s++) + if (!isalnum(*s) && !strchr("-.@/_#", *s)) + { + msg(thread_n,"Error: invalid file name\n"); + return(false); + } + if (system(cmd.str().c_str()) != 0) { return(false); } diff --git a/mysql-test/CMakeLists.txt b/mysql-test/CMakeLists.txt index 07bc3c7088661..73fcfe8538f86 100644 --- a/mysql-test/CMakeLists.txt +++ b/mysql-test/CMakeLists.txt @@ -16,6 +16,11 @@ INSTALL_MYSQL_TEST("." "") +IF (NOT CMAKE_REAL_SOURCE_DIR) + get_filename_component(CMAKE_REAL_SOURCE_DIR "${CMAKE_SOURCE_DIR}" REALPATH) + get_filename_component(CMAKE_REAL_BINARY_DIR "${CMAKE_BINARY_DIR}" REALPATH) +ENDIF() + IF(NOT ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) # Enable running mtr from build directory CONFIGURE_FILE( diff --git a/mysql-test/main/dyncol.result b/mysql-test/main/dyncol.result index ca97c5455aa1c..5eb450765d142 100644 --- a/mysql-test/main/dyncol.result +++ b/mysql-test/main/dyncol.result @@ -1979,4 +1979,11 @@ drop table t1; # SELECT COLUMN_JSON(1000); ERROR HY000: Encountered illegal format of dynamic column string +# +# MDEV-39581 dynamic column header missing sanity checks +# +SELECT COLUMN_LIST(0x040100FFFF00000300666F6F21626172); +ERROR HY000: Encountered illegal format of dynamic column string +SELECT COLUMN_JSON(CONCAT(0x040200020001000000000000004241, REPEAT('D', 512))); +ERROR HY000: Encountered illegal format of dynamic column string # End of 10.6 tests diff --git a/mysql-test/main/dyncol.test b/mysql-test/main/dyncol.test index 7f38c82f5fbcc..9ee276f4bef82 100644 --- a/mysql-test/main/dyncol.test +++ b/mysql-test/main/dyncol.test @@ -1033,4 +1033,14 @@ drop table t1; --error ER_DYN_COL_WRONG_FORMAT SELECT COLUMN_JSON(1000); + +--echo # +--echo # MDEV-39581 dynamic column header missing sanity checks +--echo # +--error ER_DYN_COL_WRONG_FORMAT +SELECT COLUMN_LIST(0x040100FFFF00000300666F6F21626172); + +--error ER_DYN_COL_WRONG_FORMAT +SELECT COLUMN_JSON(CONCAT(0x040200020001000000000000004241, REPEAT('D', 512))); + --echo # End of 10.6 tests diff --git a/mysql-test/main/func_gconcat.result b/mysql-test/main/func_gconcat.result index d725029a5335a..6c50416ee2717 100644 --- a/mysql-test/main/func_gconcat.result +++ b/mysql-test/main/func_gconcat.result @@ -1538,3 +1538,21 @@ DROP VIEW v1; DROP TABLE t1; SET NAMES latin1; # End of 10.5 tests +# +# MDEV-39673 group_concat ignores max_allowed_packet +# +connect u,localhost,root; +set group_concat_max_len=2*1024*1024*1024; +Warnings: +Warning 1292 Truncated incorrect group_concat_max_len value: '2147483648' +select @@group_concat_max_len; +@@group_concat_max_len +1073741824 +select length(group_concat(repeat('a', @@max_allowed_packet-1), repeat('a', @@max_allowed_packet-1))) from dual; +length(group_concat(repeat('a', @@max_allowed_packet-1), repeat('a', @@max_allowed_packet-1))) +16777216 +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +disconnect u; +connection default; +# End of 10.6 tests diff --git a/mysql-test/main/func_gconcat.test b/mysql-test/main/func_gconcat.test index 5694c245033f3..90bfc9188e7dd 100644 --- a/mysql-test/main/func_gconcat.test +++ b/mysql-test/main/func_gconcat.test @@ -1125,3 +1125,15 @@ DROP TABLE t1; SET NAMES latin1; --echo # End of 10.5 tests + +--echo # +--echo # MDEV-39673 group_concat ignores max_allowed_packet +--echo # +connect u,localhost,root; +set group_concat_max_len=2*1024*1024*1024; +select @@group_concat_max_len; +select length(group_concat(repeat('a', @@max_allowed_packet-1), repeat('a', @@max_allowed_packet-1))) from dual; +disconnect u; +connection default; + +--echo # End of 10.6 tests diff --git a/mysql-test/main/func_json_notembedded.result b/mysql-test/main/func_json_notembedded.result index ba4d38dd623f3..e6f1e0eb42594 100644 --- a/mysql-test/main/func_json_notembedded.result +++ b/mysql-test/main/func_json_notembedded.result @@ -3,7 +3,7 @@ connect u,localhost,root; # # MDEV-24909 JSON functions don't respect KILL QUERY / max_statement_time limit # -set group_concat_max_len= 4294967295; +set group_concat_max_len= 1000000000; set @obj=concat_ws('','{', repeat('"a":"b",', 1250000/2), '"c":"d"}'); set @arr=concat_ws('','[', repeat('1234567,', 1250000/2), '2345678]'); select length(@obj), length(@arr); diff --git a/mysql-test/main/func_json_notembedded.test b/mysql-test/main/func_json_notembedded.test index 1e05571e16f83..101dc7bdeae41 100644 --- a/mysql-test/main/func_json_notembedded.test +++ b/mysql-test/main/func_json_notembedded.test @@ -9,7 +9,7 @@ connect u,localhost,root; --echo # --echo # MDEV-24909 JSON functions don't respect KILL QUERY / max_statement_time limit --echo # -set group_concat_max_len= 4294967295; +set group_concat_max_len= 1000000000; set @obj=concat_ws('','{', repeat('"a":"b",', 1250000/2), '"c":"d"}'); set @arr=concat_ws('','[', repeat('1234567,', 1250000/2), '2345678]'); diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index 14339781ed7ec..90c8f34e68d4f 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -5595,4 +5595,10 @@ mp SELECT ST_GeomFromWKB(x'01070000000100000001070000000100000001070000000100000001020000000100000000000000') IS NOT NULL AS gc; gc 0 +# +# MDEV-39657 ASAN error on malformed WKB point +# +SELECT HEX(ST_GeometryN(0x000000000107000000010000000101000000, 1)); +HEX(ST_GeometryN(0x000000000107000000010000000101000000, 1)) +NULL # End of 10.6 tests diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index c079fcfec6a5d..24d5582ee3c8d 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -3568,4 +3568,9 @@ SELECT ST_GeomFromWKB(x'01050000000200000001020000000200000000000000000000000000 SELECT ST_GeomFromWKB(x'01060000000100000001030000000100000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') IS NOT NULL AS mp; SELECT ST_GeomFromWKB(x'01070000000100000001070000000100000001070000000100000001020000000100000000000000') IS NOT NULL AS gc; +--echo # +--echo # MDEV-39657 ASAN error on malformed WKB point +--echo # +SELECT HEX(ST_GeometryN(0x000000000107000000010000000101000000, 1)); + --echo # End of 10.6 tests diff --git a/mysql-test/main/parser.result b/mysql-test/main/parser.result index f25c51944e6fb..d0f5d756e9a9d 100644 --- a/mysql-test/main/parser.result +++ b/mysql-test/main/parser.result @@ -2266,47 +2266,15 @@ LEAVE sysdate; END WHILE ; END; $$ -# # End of 10.6 tests # +# MDEV-39654 schema-qualified unquoted table name starting with digit fails to parse # -# MDEV-17677 : Keywords are parsed as identifiers when followed by a dot -# -SET NAMES utf8; -test for Nd (should work) -SELECT.1; -.1 -0.1 -SELECT.123+0; -.123+0 -0.123 -SELECT.5 * 2; -.5 * 2 -1.0 -test for Mn -SELECT.́1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT.́1' at line 1 -SELECT.̈abc; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT.̈abc' at line 1 -test for Mc -SELECT.ःtest; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT.ःtest' at line 1 -test for Pc -SELECT.‿a; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT.‿a' at line 1 -test for Cf -SELECT.‎abc; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT.‎abc' at line 1 -test for Middle-dot and underscore -SELECT.·123; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT.·123' at line 1 -ٍSELECT._1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ٍSELECT._1' at line 1 -still work as identifier -CREATE TABLE `SELECT` (a INT); -INSERT INTO `SELECT` VALUES (5); -SELECT `SELECT`.a FROM `SELECT`; -a -5 -DROP TABLE `SELECT`; -SET NAMES DEFAULT; +create table 1a (1b int); +create table `select` (1c int); +select 1b from test.1a; +1b +select select.1c from test.select; +1c +drop table 1a, `select`; +# End of 10.11 tests diff --git a/mysql-test/main/parser.test b/mysql-test/main/parser.test index e54137b092b77..138234a4d25c7 100644 --- a/mysql-test/main/parser.test +++ b/mysql-test/main/parser.test @@ -2064,52 +2064,18 @@ DELIMITER ;$$ --disable_prepare_warnings ---echo # --echo # End of 10.6 tests ---echo # --echo # ---echo # MDEV-17677 : Keywords are parsed as identifiers when followed by a dot +--echo # MDEV-39654 schema-qualified unquoted table name starting with digit fails to parse --echo # -SET NAMES utf8; - ---echo test for Nd (should work) -SELECT.1; -SELECT.123+0; -SELECT.5 * 2; - ---character_set utf8mb4 ---echo test for Mn ---error ER_PARSE_ERROR -SELECT.́1; - ---error ER_PARSE_ERROR -SELECT.̈abc; - +create table 1a (1b int); +create table `select` (1c int); --- echo test for Mc ---error ER_PARSE_ERROR -SELECT.ःtest; - ---echo test for Pc ---error ER_PARSE_ERROR -SELECT.‿a; - ---echo test for Cf ---error ER_PARSE_ERROR -SELECT.‎abc; - ---echo test for Middle-dot and underscore ---error ER_PARSE_ERROR -SELECT.·123; ---error ER_PARSE_ERROR -ٍSELECT._1; +select 1b from test.1a; +select select.1c from test.select; ---echo still work as identifier -CREATE TABLE `SELECT` (a INT); -INSERT INTO `SELECT` VALUES (5); -SELECT `SELECT`.a FROM `SELECT`; -DROP TABLE `SELECT`; +drop table 1a, `select`; -SET NAMES DEFAULT; +--echo # End of 10.11 tests diff --git a/mysql-test/main/rpl_info_file_line_count.result b/mysql-test/main/rpl_info_file_line_count.result new file mode 100644 index 0000000000000..0a747059c5558 --- /dev/null +++ b/mysql-test/main/rpl_info_file_line_count.result @@ -0,0 +1,8 @@ +CHANGE MASTER TO master_host='127.0.0.1'; +# restart: --skip-slave-start +Master_SSL_Key = '' +Using_Gtid = 'Current_Pos' +SQL_Delay = '0' +RESET SLAVE ALL; +Warnings: +Note 4190 RESET SLAVE is implicitly changing the value of 'Using_Gtid' from 'Current_Pos' to 'Slave_Pos' diff --git a/mysql-test/main/rpl_info_file_line_count.test b/mysql-test/main/rpl_info_file_line_count.test new file mode 100644 index 0000000000000..aa338f6c37463 --- /dev/null +++ b/mysql-test/main/rpl_info_file_line_count.test @@ -0,0 +1,74 @@ +# Line count / upgrading test for `@@master_info_file` & `@@relay_log_info_file` +# +# This regression test reminds that the line count includes the line count line. +# +# Reference: +# MDEV-39788 CHANGE MASTER savefiles read and write one line to many + +--source include/have_binlog_format_mixed.inc # format-agnostic +CHANGE MASTER TO master_host='127.0.0.1'; # have_info_files + +--let $MYSQLD_DATADIR= `SELECT @@datadir` + + +# `using_gtid` is the key-value section, not the 33rd option. +--remove_file $MYSQLD_DATADIR/master.info +--write_file $MYSQLD_DATADIR/master.info +33 + +4 +127.0.0.1 +root + +3306 +60 +1 + + + + + +1 +60.000 + +0 + +100000 + + + + + + + + + + + + + +using_gtid=1 +EOF + +# This file does not have the 6th option +# (neither does the current `@@relay_log_info_file`). +--remove_file $MYSQLD_DATADIR/relay-log.info +--write_file $MYSQLD_DATADIR/relay-log.info +6 +./mysqld-relay-bin.000001 +4 + +0 +0 +EOF + + +--let $restart_parameters= --skip-slave-start +--source include/restart_mysqld.inc + +--let $status_items= Master_SSL_Key, Using_Gtid, SQL_Delay +--source include/show_slave_status.inc + + +# Reset +RESET SLAVE ALL; diff --git a/mysql-test/mtr.out-of-source b/mysql-test/mtr.out-of-source index abab0be90df6c..dbaa521e2f50f 100644 --- a/mysql-test/mtr.out-of-source +++ b/mysql-test/mtr.out-of-source @@ -1,5 +1,14 @@ #!/usr/bin/env perl # Call mtr in out-of-source build + +use Cwd qw(cwd abs_path); $ENV{MTR_BINDIR} = '@CMAKE_BINARY_DIR@'; +my $dir= cwd(); +my $new_dir= abs_path('@CMAKE_SOURCE_DIR@'); +if ($dir eq $new_dir . '/mysql-test') +{ + print stderr "Something went wrong. Do 'git checkout mysql-test/mariadb-test-run.pl' and try again"; + exit 1; +} chdir('@CMAKE_SOURCE_DIR@/mysql-test'); exit(system($^X, '@CMAKE_SOURCE_DIR@/mysql-test/mariadb-test-run.pl', @ARGV) >> 8); diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_0407.result b/mysql-test/suite/funcs_1/r/innodb_trig_0407.result index 5b9a16d2f17fd..281e4e8d0f6c3 100644 --- a/mysql-test/suite/funcs_1/r/innodb_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/innodb_trig_0407.result @@ -138,7 +138,7 @@ create table t1_433a (f1a char (5)) engine = ; CREATE TRIGGER trg3 BEFORE INSERT on t1_433 for each row set new.f1 = 'Trigger 3.5.4.3'; Drop trigger t1.433.trg3; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.433.trg3' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.trg3' at line 1 Drop trigger db_drop3.t1.433.trg3; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.433.trg3' at line 1 Drop trigger mysql.trg3; diff --git a/mysql-test/suite/funcs_1/r/memory_trig_0407.result b/mysql-test/suite/funcs_1/r/memory_trig_0407.result index bf9d20da2f13b..c9a15b46aba07 100644 --- a/mysql-test/suite/funcs_1/r/memory_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/memory_trig_0407.result @@ -138,7 +138,7 @@ create table t1_433a (f1a char (5)) engine = ; CREATE TRIGGER trg3 BEFORE INSERT on t1_433 for each row set new.f1 = 'Trigger 3.5.4.3'; Drop trigger t1.433.trg3; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.433.trg3' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.trg3' at line 1 Drop trigger db_drop3.t1.433.trg3; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.433.trg3' at line 1 Drop trigger mysql.trg3; diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_0407.result b/mysql-test/suite/funcs_1/r/myisam_trig_0407.result index bf9d20da2f13b..c9a15b46aba07 100644 --- a/mysql-test/suite/funcs_1/r/myisam_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/myisam_trig_0407.result @@ -138,7 +138,7 @@ create table t1_433a (f1a char (5)) engine = ; CREATE TRIGGER trg3 BEFORE INSERT on t1_433 for each row set new.f1 = 'Trigger 3.5.4.3'; Drop trigger t1.433.trg3; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.433.trg3' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.trg3' at line 1 Drop trigger db_drop3.t1.433.trg3; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.433.trg3' at line 1 Drop trigger mysql.trg3; diff --git a/mysql-test/suite/galera/r/MDEV-39685.result b/mysql-test/suite/galera/r/MDEV-39685.result new file mode 100644 index 0000000000000..ab4d01526b9f3 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-39685.result @@ -0,0 +1,13 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 ( +pk int PRIMARY KEY, +c varchar(8), +i int +) ENGINE=InnoDB; +CREATE TABLE t2 (f int) ENGINE=InnoDB; +CREATE TABLE t3 (x int, +FOREIGN KEY (x) REFERENCES t1 (pk) +) ENGINE=InnoDB; +UPDATE t1 JOIN t2 ON t1.i = t2.f SET t1.c = 'foo'; +DROP TABLE t3, t2, t1; diff --git a/mysql-test/suite/galera/r/galera_sst_rsync_encrypt_with_key_server.result b/mysql-test/suite/galera/r/galera_sst_rsync_encrypt_with_key_server.result new file mode 100644 index 0000000000000..48b296a96f56d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_rsync_encrypt_with_key_server.result @@ -0,0 +1,27 @@ +connection node_2; +connection node_1; +SELECT 1; +1 +1 +connection node_2; +FOUND 1 /wsrep_sst_rsync/ in mysqld.1.err +connection node_1; +call mtr.add_suppression('Invalid value for WSREP_SST_OPT_REMOTE_USER'); +call mtr.add_suppression('Failed to read from: wsrep_sst_rsync'); +call mtr.add_suppression('Process completed with error: wsrep_sst_rsync'); +call mtr.add_suppression('Command did not run: wsrep_sst_rsync'); +call mtr.add_suppression('State transfer to .* failed'); +call mtr.add_suppression('Will never receive state. Need to abort'); +call mtr.add_suppression('Error while getting data from donor node'); +call mtr.add_suppression('Cleanup after exit with status'); +call mtr.add_suppression('Removing .*/sst_in_progress'); +call mtr.add_suppression('Parent mysqld process .* terminated unexpectedly'); +connection node_2; +connection node_1; +FOUND 1 /Invalid value for WSREP_SST_OPT_REMOTE_USER/ in mysqld.1.err +connection node_2; +# restart +call mtr.add_suppression('Will never receive state. Need to abort'); +call mtr.add_suppression('Parent mysqld process .* terminated unexpectedly'); +call mtr.add_suppression('Cleanup after exit with status'); +call mtr.add_suppression('State transfer to .* failed'); diff --git a/mysql-test/suite/galera/r/galera_var_sst_donor.result b/mysql-test/suite/galera/r/galera_var_sst_donor.result new file mode 100644 index 0000000000000..e9cb5d696c981 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_sst_donor.result @@ -0,0 +1,30 @@ +connection node_2; +connection node_1; +connection node_1; +SET @sst_donor_orig=@@GLOBAL.wsrep_sst_donor; +set global wsrep_sst_donor='127.0.0.1;'; +ERROR 42000: Variable 'wsrep_sst_donor' can't be set to the value of '127.0.0.1;' +select @@wsrep_sst_donor; +@@wsrep_sst_donor + +set global wsrep_sst_donor='node1\''; +ERROR 42000: Variable 'wsrep_sst_donor' can't be set to the value of 'node1'' +select @@wsrep_sst_donor; +@@wsrep_sst_donor + +set global wsrep_sst_donor='node_2&'; +ERROR 42000: Variable 'wsrep_sst_donor' can't be set to the value of 'node_2&' +select @@wsrep_sst_donor; +@@wsrep_sst_donor + +set global wsrep_sst_donor='127.0.0.1|'; +ERROR 42000: Variable 'wsrep_sst_donor' can't be set to the value of '127.0.0.1|' +select @@wsrep_sst_donor; +@@wsrep_sst_donor + +set global wsrep_sst_donor='node2'; +select @@wsrep_sst_donor; +@@wsrep_sst_donor +node2 +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/r/galera_var_sst_method.result b/mysql-test/suite/galera/r/galera_var_sst_method.result new file mode 100644 index 0000000000000..3cdd757544cf3 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_sst_method.result @@ -0,0 +1,44 @@ +connection node_2; +connection node_1; +connection node_1; +SET @sst_method_orig=@@GLOBAL.wsrep_sst_method; +set global wsrep_sst_method='mariabackup;'; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'mariabackup;' +select @@wsrep_sst_method; +@@wsrep_sst_method +rsync +set global wsrep_sst_method='mariabackup\''; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'mariabackup'' +select @@wsrep_sst_method; +@@wsrep_sst_method +rsync +set global wsrep_sst_method='mariabackup&'; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'mariabackup&' +select @@wsrep_sst_method; +@@wsrep_sst_method +rsync +set global wsrep_sst_method='mariabackup|'; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'mariabackup|' +select @@wsrep_sst_method; +@@wsrep_sst_method +rsync +set global wsrep_sst_method=NULL; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'NULL' +select @@wsrep_sst_method; +@@wsrep_sst_method +rsync +set global wsrep_sst_method=''; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of '' +select @@wsrep_sst_method; +@@wsrep_sst_method +rsync +set global wsrep_sst_method='mariabackup'; +select @@wsrep_sst_method; +@@wsrep_sst_method +mariabackup +set global wsrep_sst_method='rsync'; +select @@wsrep_sst_method; +@@wsrep_sst_method +rsync +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/r/galera_var_sst_receive_address.result b/mysql-test/suite/galera/r/galera_var_sst_receive_address.result new file mode 100644 index 0000000000000..3c20305b62827 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_sst_receive_address.result @@ -0,0 +1,17 @@ +connection node_2; +connection node_1; +connection node_1; +SET @sst_receive_address_orig=@@GLOBAL.wsrep_sst_receive_address; +set global wsrep_sst_receive_address='127.0.0.1;'; +ERROR 42000: Variable 'wsrep_sst_receive_address' can't be set to the value of '127.0.0.1;' +set global wsrep_sst_receive_address='127.0.0.1\''; +ERROR 42000: Variable 'wsrep_sst_receive_address' can't be set to the value of '127.0.0.1'' +set global wsrep_sst_receive_address='127.0.0.1&'; +ERROR 42000: Variable 'wsrep_sst_receive_address' can't be set to the value of '127.0.0.1&' +set global wsrep_sst_receive_address='127.0.0.1|'; +ERROR 42000: Variable 'wsrep_sst_receive_address' can't be set to the value of '127.0.0.1|' +set global wsrep_sst_receive_address=NULL; +set global wsrep_sst_receive_address=''; +set global wsrep_sst_receive_address='127.0.0.1:19000'; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/r/galera_wsrep_notify_cmd_injection.result b/mysql-test/suite/galera/r/galera_wsrep_notify_cmd_injection.result new file mode 100644 index 0000000000000..3757e4f3dc291 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_wsrep_notify_cmd_injection.result @@ -0,0 +1,10 @@ +connection node_2; +connection node_1; +SELECT 1; +1 +1 +connection node_1; +call mtr.add_suppression('Process completed with error'); +call mtr.add_suppression('Notification command failed'); +call mtr.add_suppression('Unsafe characters in cluster member'); +FOUND 3 /Unsafe characters in cluster member/ in mysqld.1.err diff --git a/mysql-test/suite/galera/t/MDEV-39685.test b/mysql-test/suite/galera/t/MDEV-39685.test new file mode 100644 index 0000000000000..19775610d0add --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-39685.test @@ -0,0 +1,18 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 ( + pk int PRIMARY KEY, + c varchar(8), + i int +) ENGINE=InnoDB; + +CREATE TABLE t2 (f int) ENGINE=InnoDB; + +CREATE TABLE t3 (x int, + FOREIGN KEY (x) REFERENCES t1 (pk) +) ENGINE=InnoDB; + +UPDATE t1 JOIN t2 ON t1.i = t2.f SET t1.c = 'foo'; + +DROP TABLE t3, t2, t1; diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key_server.test b/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key_server.test index a570c75216fc2..0418be4d797a0 100644 --- a/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key_server.test +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key_server.test @@ -45,7 +45,9 @@ call mtr.add_suppression('Removing .*/xtrabackup_galera_info file due to signal' --exec echo ssl-key=$MYSQL_TEST_DIR/std_data/server-new-key.pem >> $MYSQLTEST_VARDIR/my.cnf --echo # start the server ---error 0,134 +# Joiner mariadbd exits when SST is aborted; the exit code varies by +# platform (clean 0 on some systems, signalled 134 / 1 on others). +--error 0,134,1 --exec $MYSQLD_LAST_CMD --echo # the server failed to start @@ -55,7 +57,8 @@ call mtr.add_suppression('Removing .*/xtrabackup_galera_info file due to signal' --echo # cleanup # we have to kill joiner's socat here, because the donor has aborted SST # and joiner's socat will timeout in 5 minutes ---error 0,15 +# pkill exit code varies by platform 0 or 1 +--error 0,1 --exec pkill -f 'socat.*server-new-cert' --exec echo ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem >> $MYSQLTEST_VARDIR/my.cnf --exec echo ssl-key=$MYSQL_TEST_DIR/std_data/server-key.pem >> $MYSQLTEST_VARDIR/my.cnf diff --git a/mysql-test/suite/galera/t/galera_sst_rsync_encrypt_with_key_server.cnf b/mysql-test/suite/galera/t/galera_sst_rsync_encrypt_with_key_server.cnf new file mode 100644 index 0000000000000..9b919145a316d --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_rsync_encrypt_with_key_server.cnf @@ -0,0 +1,13 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=rsync +wsrep_sst_auth="root:" +wsrep_debug=1 + +ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem +ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem +ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem + +[sst] +ssl-mode=VERIFY_CA diff --git a/mysql-test/suite/galera/t/galera_sst_rsync_encrypt_with_key_server.test b/mysql-test/suite/galera/t/galera_sst_rsync_encrypt_with_key_server.test new file mode 100644 index 0000000000000..f0458e1f62fd2 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_rsync_encrypt_with_key_server.test @@ -0,0 +1,99 @@ +# +# Verifies that wsrep_sst_rsync.sh rejects a joiner-supplied certificate +# whose CN contains shell-unsafe characters. +# +# Brings up a 2-node cluster with rsync SST and ssl-mode=VERIFY_CA, then +# forces a fresh SST on node_2 using std_data/server-new-cert.pem -- a +# cert whose CN intentionally contains shell metacharacters. Confirms +# that the donor (node_1) logs +# "Invalid value for WSREP_SST_OPT_REMOTE_USER" +# i.e. the rsync SST script refuses the value rather than interpolating +# it into stunnel.conf or the rsync magic file. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +SELECT 1; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'WSREP_LOCAL_STATE_COMMENT' +--source include/wait_condition.inc + +# Confirm the initial SST went via rsync + stunnel (sanity check for the +# test configuration). +--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN = wsrep_sst_rsync +--source include/search_pattern_in_file.inc + + +# Reject shell-unsafe joiner-supplied auth (rsync) + +# Suppressions are per-server. node_1 will log the donor-side rejection +# ("Invalid value for WSREP_SST_OPT_REMOTE_USER"); node_2 will log the +# joiner-side "Will never receive state" abort. Add to both. +--connection node_1 +call mtr.add_suppression('Invalid value for WSREP_SST_OPT_REMOTE_USER'); +call mtr.add_suppression('Failed to read from: wsrep_sst_rsync'); +call mtr.add_suppression('Process completed with error: wsrep_sst_rsync'); +call mtr.add_suppression('Command did not run: wsrep_sst_rsync'); +call mtr.add_suppression('State transfer to .* failed'); +call mtr.add_suppression('Will never receive state. Need to abort'); +call mtr.add_suppression('Error while getting data from donor node'); +call mtr.add_suppression('Cleanup after exit with status'); +call mtr.add_suppression('Removing .*/sst_in_progress'); +call mtr.add_suppression('Parent mysqld process .* terminated unexpectedly'); + +--connection node_2 +--source include/shutdown_mysqld.inc + +# force SST again +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat +# using a cert with shell-unsafe CN +--exec echo '[mysqld.2]' >> $MYSQLTEST_VARDIR/my.cnf +--exec echo ssl-cert=$MYSQL_TEST_DIR/std_data/server-new-cert.pem >> $MYSQLTEST_VARDIR/my.cnf +--exec echo ssl-key=$MYSQL_TEST_DIR/std_data/server-new-key.pem >> $MYSQLTEST_VARDIR/my.cnf + +# start the server +# Joiner mariadbd exits when SST is aborted; the exit code varies by +# platform (clean 0 on some systems, signalled 134 / 1 on others). +--error 0,1,134 +--exec $MYSQLD_LAST_CMD +# the donor refused the SST request + +--connection node_1 +# safe() in wsrep_sst_common.sh logs this when it rejects the joiner CN; +# wsrep_sst_rsync.sh wraps the joiner-supplied REMOTE_USER with $(safe ..) +# at line 249 so the value never reaches the stunnel.conf heredoc. +--let SEARCH_PATTERN = Invalid value for WSREP_SST_OPT_REMOTE_USER +--source include/search_pattern_in_file.inc + +# cleanup +# Kill joiner's stunnel / rsync that may linger after the aborted SST. +# Use a perl block because --exec with pkill -f matches the mtr cmdline +# itself (which contains the pattern) and tears down the wrong process. +perl; + open(my $fh, '-|', 'ps', '-eo', 'pid,args') or die "ps: $!"; + while (<$fh>) { + next unless /server-new-cert/; + next unless /^\s*(\d+)\s+(?:.*\/)?(stunnel|socat|rsync)\b/; + kill 'TERM', $1; + } + close $fh; +EOF +--exec echo ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem >> $MYSQLTEST_VARDIR/my.cnf +--exec echo ssl-key=$MYSQL_TEST_DIR/std_data/server-key.pem >> $MYSQLTEST_VARDIR/my.cnf + +# Switch back to node_2 before restarting it; the connection associates +# with the soon-to-be-restarted server so mtr auto-reconnects and the +# wait_condition + late suppressions land on the new instance. +--connection node_2 +--source $MYSQL_TEST_DIR/include/start_mysqld.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +call mtr.add_suppression('Will never receive state. Need to abort'); +call mtr.add_suppression('Parent mysqld process .* terminated unexpectedly'); +call mtr.add_suppression('Cleanup after exit with status'); +call mtr.add_suppression('State transfer to .* failed'); diff --git a/mysql-test/suite/galera/t/galera_var_sst_donor.test b/mysql-test/suite/galera/t/galera_var_sst_donor.test new file mode 100644 index 0000000000000..a83d68bf531da --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_sst_donor.test @@ -0,0 +1,27 @@ +# +# Check the handling of @@wsrep_sst_donor +# +--source include/galera_cluster.inc + +--connection node_1 +SET @sst_donor_orig=@@GLOBAL.wsrep_sst_donor; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_donor='127.0.0.1;'; +select @@wsrep_sst_donor; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_donor='node1\''; +select @@wsrep_sst_donor; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_donor='node_2&'; +select @@wsrep_sst_donor; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_donor='127.0.0.1|'; +select @@wsrep_sst_donor; +set global wsrep_sst_donor='node2'; +select @@wsrep_sst_donor; + +--disable_query_log +SET GLOBAL wsrep_sst_donor = @sst_donor_orig; +--enable_query_log + +--source include/galera_end.inc diff --git a/mysql-test/suite/galera/t/galera_var_sst_method.test b/mysql-test/suite/galera/t/galera_var_sst_method.test new file mode 100644 index 0000000000000..a0215ce37466e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_sst_method.test @@ -0,0 +1,36 @@ +# +# Check the handling of @@wsrep_sst_method +# +--source include/galera_cluster.inc + +--connection node_1 +SET @sst_method_orig=@@GLOBAL.wsrep_sst_method; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_method='mariabackup;'; +select @@wsrep_sst_method; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_method='mariabackup\''; +select @@wsrep_sst_method; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_method='mariabackup&'; +select @@wsrep_sst_method; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_method='mariabackup|'; +select @@wsrep_sst_method; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_method=NULL; +select @@wsrep_sst_method; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_method=''; +select @@wsrep_sst_method; + +set global wsrep_sst_method='mariabackup'; +select @@wsrep_sst_method; +set global wsrep_sst_method='rsync'; +select @@wsrep_sst_method; + +--disable_query_log +SET GLOBAL wsrep_sst_method = @sst_method_orig; +--enable_query_log + +--source include/galera_end.inc diff --git a/mysql-test/suite/galera/t/galera_var_sst_receive_address.test b/mysql-test/suite/galera/t/galera_var_sst_receive_address.test new file mode 100644 index 0000000000000..aa97e86219e62 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_sst_receive_address.test @@ -0,0 +1,26 @@ +# +# Check the handling of @@wsrep_sst_receive_address +# + +--source include/galera_cluster.inc + +--connection node_1 +SET @sst_receive_address_orig=@@GLOBAL.wsrep_sst_receive_address; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_receive_address='127.0.0.1;'; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_receive_address='127.0.0.1\''; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_receive_address='127.0.0.1&'; +--error ER_WRONG_VALUE_FOR_VAR +set global wsrep_sst_receive_address='127.0.0.1|'; + +set global wsrep_sst_receive_address=NULL; +set global wsrep_sst_receive_address=''; +set global wsrep_sst_receive_address='127.0.0.1:19000'; + +--disable_query_log +SET GLOBAL wsrep_sst_receive_address = @sst_receive_address_orig; +--enable_query_log + +--source include/galera_end.inc diff --git a/mysql-test/suite/galera/t/galera_wsrep_notify_cmd_injection.cnf b/mysql-test/suite/galera/t/galera_wsrep_notify_cmd_injection.cnf new file mode 100644 index 0000000000000..9c55be86036ec --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_notify_cmd_injection.cnf @@ -0,0 +1,10 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +# Victim: /bin/true exits 0 ignoring argv, so injection happens in sh -c parsing. +wsrep_notify_cmd=/bin/true + +[mysqld.2] +# Attacker: shell metacharacters in wsrep_node_name; trailing '#' comments +# out whatever the server appends after the name. +wsrep_node_name='n;touch PWN;#' diff --git a/mysql-test/suite/galera/t/galera_wsrep_notify_cmd_injection.test b/mysql-test/suite/galera/t/galera_wsrep_notify_cmd_injection.test new file mode 100644 index 0000000000000..474179267c834 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_notify_cmd_injection.test @@ -0,0 +1,30 @@ +# +# Joiner-supplied wsrep_node_name must not inject shell commands into +# the donor's wsrep_notify_cmd. Fails if "Notification command failed" +# co-occurs with ";touch" in node_1's error log. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +SELECT 1; + +--connection node_1 +call mtr.add_suppression('Process completed with error'); +call mtr.add_suppression('Notification command failed'); +call mtr.add_suppression('Unsafe characters in cluster member'); +--let $datadir=`select @@datadir` + +--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'WSREP_LOCAL_STATE_COMMENT' +--source include/wait_condition.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--sleep 2 + +--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN = Unsafe characters in cluster member +--source include/search_pattern_in_file.inc + +--list_files $datadir PWN diff --git a/mysql-test/suite/mariabackup/options_check.result b/mysql-test/suite/mariabackup/options_check.result index 59666754f04af..71ccf29dcaa5a 100644 --- a/mysql-test/suite/mariabackup/options_check.result +++ b/mysql-test/suite/mariabackup/options_check.result @@ -6,3 +6,12 @@ # Check if uknown options that follow --mysqld-args are ingored # Check if [mariadb-client] group is not loaded (MDEV-22894) # Check if --help presents +# +# MDEV-39565 missing filename check in mariadb-backup --decompress +# +[##] ####-##-## ##:##:## decompressing ./a;touch b.qp + +[##] ####-##-## ##:##:## Error: invalid file name + +[##] ####-##-## ##:##:## Error: thread # failed. +# End of 10.6 tests diff --git a/mysql-test/suite/mariabackup/options_check.test b/mysql-test/suite/mariabackup/options_check.test index 022bcbd5d1017..b6c45c01a7a57 100644 --- a/mysql-test/suite/mariabackup/options_check.test +++ b/mysql-test/suite/mariabackup/options_check.test @@ -67,3 +67,16 @@ exec $XTRABACKUP --help; exec $XTRABACKUP -?; --enable_result_log +--echo # +--echo # MDEV-39565 missing filename check in mariadb-backup --decompress +--echo # +--write_file "$MYSQL_TMP_DIR/a;touch b.qp" +foo +EOF + +--replace_regex /.*based.*\n// /\d/#/ /[\\]/\// +--error 1 +exec $XTRABACKUP --decompress --target-dir=$MYSQL_TMP_DIR 2>&1; +--list_files $MYSQL_TMP_DIR b.qp + +--echo # End of 10.6 tests diff --git a/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result b/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result index 01f44ae51be67..e38f1f6ccb2b6 100644 --- a/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result +++ b/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result @@ -118,29 +118,11 @@ SELECT * FROM ( SELECT GROUP_CONCAT(val) AS nested FROM t1) As tmp; nested bar,foo SET group_concat_max_len = 1073741825; +Warnings: +Warning 1292 Truncated incorrect group_concat_max_len value: '1073741825' SHOW VARIABLES LIKE 'group_concat_max_len'; Variable_name Value -group_concat_max_len 1073741825 -SELECT GROUP_CONCAT(val) AS simple FROM t1; -simple -bar,foo -SELECT * FROM ( SELECT GROUP_CONCAT(val) AS nested FROM t1) As tmp; -nested -bar,foo -SET group_concat_max_len = 1073741826; -SHOW VARIABLES LIKE 'group_concat_max_len'; -Variable_name Value -group_concat_max_len 1073741826 -SELECT GROUP_CONCAT(val) AS simple FROM t1; -simple -bar,foo -SELECT * FROM ( SELECT GROUP_CONCAT(val) AS nested FROM t1) As tmp; -nested -bar,foo -SET group_concat_max_len = 2147483649; -SHOW VARIABLES LIKE 'group_concat_max_len'; -Variable_name Value -group_concat_max_len 2147483649 +group_concat_max_len 1073741824 SELECT GROUP_CONCAT(val) AS simple FROM t1; simple bar,foo diff --git a/mysql-test/suite/sys_vars/r/proxy_protocol_networks_grant.result b/mysql-test/suite/sys_vars/r/proxy_protocol_networks_grant.result index b6bae2724430a..4d663628c91e9 100644 --- a/mysql-test/suite/sys_vars/r/proxy_protocol_networks_grant.result +++ b/mysql-test/suite/sys_vars/r/proxy_protocol_networks_grant.result @@ -7,7 +7,6 @@ CREATE USER user1@localhost; GRANT ALL PRIVILEGES ON *.* TO user1@localhost; REVOKE CONNECTION ADMIN, SUPER ON *.* FROM user1@localhost; connect user1,localhost,user1,,; -connection user1; SET GLOBAL proxy_protocol_networks=""; ERROR 42000: Access denied; you need (at least one of) the SUPER, CONNECTION ADMIN privilege(s) for this operation SET proxy_protocol_networks=""; @@ -21,7 +20,6 @@ DROP USER user1@localhost; CREATE USER user1@localhost; GRANT CONNECTION ADMIN ON *.* TO user1@localhost; connect user1,localhost,user1,,; -connection user1; SET GLOBAL proxy_protocol_networks=""; SET proxy_protocol_networks=""; ERROR HY000: Variable 'proxy_protocol_networks' is a GLOBAL variable and should be set with SET GLOBAL @@ -34,7 +32,6 @@ DROP USER user1@localhost; CREATE USER user1@localhost; GRANT SUPER ON *.* TO user1@localhost; connect user1,localhost,user1,,; -connection user1; SET GLOBAL proxy_protocol_networks=""; SET proxy_protocol_networks=""; ERROR HY000: Variable 'proxy_protocol_networks' is a GLOBAL variable and should be set with SET GLOBAL @@ -43,4 +40,10 @@ ERROR HY000: Variable 'proxy_protocol_networks' is a GLOBAL variable and should disconnect user1; connection default; DROP USER user1@localhost; +# +# MDEV-39658 ASAN crash on invalid proxy_protocol_networks value +# +SET GLOBAL proxy_protocol_networks='1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0'; +ERROR 42000: Error parsing proxy_protocol_networks parameter, near '1' +# End of 10.6 tests SET @@global.proxy_protocol_networks=@global; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 712f1cfd740a2..15e9fc5089c99 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -1097,7 +1097,7 @@ VARIABLE_SCOPE SESSION VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The maximum length of the result of function GROUP_CONCAT() NUMERIC_MIN_VALUE 4 -NUMERIC_MAX_VALUE 4294967295 +NUMERIC_MAX_VALUE 1073741824 NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 95514d6e510c1..e25a7df7591c6 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -1127,7 +1127,7 @@ VARIABLE_SCOPE SESSION VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The maximum length of the result of function GROUP_CONCAT() NUMERIC_MIN_VALUE 4 -NUMERIC_MAX_VALUE 4294967295 +NUMERIC_MAX_VALUE 1073741824 NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO diff --git a/mysql-test/suite/sys_vars/r/wsrep_sst_receive_address_basic.result b/mysql-test/suite/sys_vars/r/wsrep_sst_receive_address_basic.result index 3e1fb6cad79de..2f3f1bc6e120e 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_sst_receive_address_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_sst_receive_address_basic.result @@ -28,16 +28,19 @@ SET @@global.wsrep_sst_receive_address='192.168.2.254'; SELECT @@global.wsrep_sst_receive_address; @@global.wsrep_sst_receive_address 192.168.2.254 - -# invalid values +SET @@global.wsrep_sst_receive_address=NULL; SELECT @@global.wsrep_sst_receive_address; @@global.wsrep_sst_receive_address -192.168.2.254 -SET @@global.wsrep_sst_receive_address=NULL; -ERROR 42000: Variable 'wsrep_sst_receive_address' can't be set to the value of 'NULL' +NULL +SET @@global.wsrep_sst_receive_address=''; SELECT @@global.wsrep_sst_receive_address; @@global.wsrep_sst_receive_address -192.168.2.254 + + +# invalid values +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address + SET @@global.wsrep_sst_receive_address='OFF'; SELECT @@global.wsrep_sst_receive_address; @@global.wsrep_sst_receive_address @@ -46,10 +49,6 @@ SET @@global.wsrep_sst_receive_address=ON; SELECT @@global.wsrep_sst_receive_address; @@global.wsrep_sst_receive_address ON -SET @@global.wsrep_sst_receive_address=''; -SELECT @@global.wsrep_sst_receive_address; -@@global.wsrep_sst_receive_address - SET @@global.wsrep_sst_receive_address='junk'; SELECT @@global.wsrep_sst_receive_address; @@global.wsrep_sst_receive_address diff --git a/mysql-test/suite/sys_vars/t/group_concat_max_len_func.test b/mysql-test/suite/sys_vars/t/group_concat_max_len_func.test index 4957afc088057..d590fd5915e99 100644 --- a/mysql-test/suite/sys_vars/t/group_concat_max_len_func.test +++ b/mysql-test/suite/sys_vars/t/group_concat_max_len_func.test @@ -155,16 +155,6 @@ SHOW VARIABLES LIKE 'group_concat_max_len'; SELECT GROUP_CONCAT(val) AS simple FROM t1; SELECT * FROM ( SELECT GROUP_CONCAT(val) AS nested FROM t1) As tmp; -SET group_concat_max_len = 1073741826; -SHOW VARIABLES LIKE 'group_concat_max_len'; -SELECT GROUP_CONCAT(val) AS simple FROM t1; -SELECT * FROM ( SELECT GROUP_CONCAT(val) AS nested FROM t1) As tmp; - -SET group_concat_max_len = 2147483649; -SHOW VARIABLES LIKE 'group_concat_max_len'; -SELECT GROUP_CONCAT(val) AS simple FROM t1; -SELECT * FROM ( SELECT GROUP_CONCAT(val) AS nested FROM t1) As tmp; - DROP TABLE t1; SET @@global.group_concat_max_len = @save; diff --git a/mysql-test/suite/sys_vars/t/proxy_protocol_networks_grant.test b/mysql-test/suite/sys_vars/t/proxy_protocol_networks_grant.test index f2dd815842489..b2ef86fd04739 100644 --- a/mysql-test/suite/sys_vars/t/proxy_protocol_networks_grant.test +++ b/mysql-test/suite/sys_vars/t/proxy_protocol_networks_grant.test @@ -12,7 +12,6 @@ CREATE USER user1@localhost; GRANT ALL PRIVILEGES ON *.* TO user1@localhost; REVOKE CONNECTION ADMIN, SUPER ON *.* FROM user1@localhost; --connect(user1,localhost,user1,,) ---connection user1 --error ER_SPECIFIC_ACCESS_DENIED_ERROR SET GLOBAL proxy_protocol_networks=""; --error ER_GLOBAL_VARIABLE @@ -28,7 +27,6 @@ DROP USER user1@localhost; CREATE USER user1@localhost; GRANT CONNECTION ADMIN ON *.* TO user1@localhost; --connect(user1,localhost,user1,,) ---connection user1 SET GLOBAL proxy_protocol_networks=""; --error ER_GLOBAL_VARIABLE SET proxy_protocol_networks=""; @@ -43,7 +41,6 @@ DROP USER user1@localhost; CREATE USER user1@localhost; GRANT SUPER ON *.* TO user1@localhost; --connect(user1,localhost,user1,,) ---connection user1 SET GLOBAL proxy_protocol_networks=""; --error ER_GLOBAL_VARIABLE SET proxy_protocol_networks=""; @@ -53,4 +50,11 @@ SET SESSION proxy_protocol_networks=""; --connection default DROP USER user1@localhost; +--echo # +--echo # MDEV-39658 ASAN crash on invalid proxy_protocol_networks value +--echo # +--error ER_PARSE_ERROR +SET GLOBAL proxy_protocol_networks='1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0'; + +--echo # End of 10.6 tests SET @@global.proxy_protocol_networks=@global; diff --git a/mysql-test/suite/sys_vars/t/wsrep_sst_receive_address_basic.test b/mysql-test/suite/sys_vars/t/wsrep_sst_receive_address_basic.test index 59f69c14dfb87..f65ddee3ca85a 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_sst_receive_address_basic.test +++ b/mysql-test/suite/sys_vars/t/wsrep_sst_receive_address_basic.test @@ -24,21 +24,20 @@ SET @@global.wsrep_sst_receive_address=default; SELECT @@global.wsrep_sst_receive_address; SET @@global.wsrep_sst_receive_address='192.168.2.254'; SELECT @@global.wsrep_sst_receive_address; +SET @@global.wsrep_sst_receive_address=NULL; +SELECT @@global.wsrep_sst_receive_address; +SET @@global.wsrep_sst_receive_address=''; +SELECT @@global.wsrep_sst_receive_address; --echo --echo # invalid values SELECT @@global.wsrep_sst_receive_address; ---error ER_WRONG_VALUE_FOR_VAR -SET @@global.wsrep_sst_receive_address=NULL; -SELECT @@global.wsrep_sst_receive_address; # Currently there is no strict checking performed for wsrep_sst_receive_address # so following values jusr pass through. SET @@global.wsrep_sst_receive_address='OFF'; SELECT @@global.wsrep_sst_receive_address; SET @@global.wsrep_sst_receive_address=ON; SELECT @@global.wsrep_sst_receive_address; -SET @@global.wsrep_sst_receive_address=''; -SELECT @@global.wsrep_sst_receive_address; SET @@global.wsrep_sst_receive_address='junk'; SELECT @@global.wsrep_sst_receive_address; diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index c82d0ae02c2ff..1b5cf30b6de09 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -3,7 +3,7 @@ --source include/have_innodb.inc --source include/galera_no_debug_sync.inc ---let $galera_version=26.4.23 +--let $galera_version=26.4.27 source include/check_galera_version.inc; source include/galera_variables_ok.inc; diff --git a/mysql-test/suite/wsrep/t/variables_debug.test b/mysql-test/suite/wsrep/t/variables_debug.test index e50cee28a1592..abae2e15b8350 100644 --- a/mysql-test/suite/wsrep/t/variables_debug.test +++ b/mysql-test/suite/wsrep/t/variables_debug.test @@ -5,7 +5,7 @@ --source include/have_debug_sync.inc --source include/galera_have_debug_sync.inc ---let $galera_version=26.4.23 +--let $galera_version=26.4.27 source include/check_galera_version.inc; source include/galera_variables_ok_debug.inc; diff --git a/mysql-test/suite/wsrep/t/wsrep_protocol_versions.test b/mysql-test/suite/wsrep/t/wsrep_protocol_versions.test index 9ac59eee071ab..860ab1905201b 100644 --- a/mysql-test/suite/wsrep/t/wsrep_protocol_versions.test +++ b/mysql-test/suite/wsrep/t/wsrep_protocol_versions.test @@ -2,7 +2,7 @@ --source include/force_restart.inc --source include/have_innodb.inc ---let $galera_version=26.4.25 +--let $galera_version=26.4.27 source include/check_galera_version.inc; --sorted_result diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index 60aaffba2278a..e0107a5601a18 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -658,6 +658,7 @@ static struct st_service_funcs fmt_data[2]= static enum enum_dyncol_func_result init_read_hdr(DYN_HEADER *hdr, DYNAMIC_COLUMN *str) { + size_t nodata_size; if (read_fixed_header(hdr, str)) return ER_DYNCOL_FORMAT; hdr->header= (uchar*)str->str + fmt_data[hdr->format].fixed_hdr; @@ -666,8 +667,11 @@ init_read_hdr(DYN_HEADER *hdr, DYNAMIC_COLUMN *str) hdr->column_count); hdr->nmpool= hdr->header + hdr->header_size; hdr->dtpool= hdr->nmpool + hdr->nmpool_size; - hdr->data_size= str->length - fmt_data[hdr->format].fixed_hdr - - hdr->header_size - hdr->nmpool_size; + nodata_size= fmt_data[hdr->format].fixed_hdr + hdr->header_size + + hdr->nmpool_size; + if (str->length < nodata_size) + return ER_DYNCOL_FORMAT; + hdr->data_size= str->length - nodata_size; hdr->data_end= (uchar*)str->str + str->length; return ER_DYNCOL_OK; } @@ -2018,7 +2022,7 @@ static my_bool read_name(DYN_HEADER *hdr, uchar *entry, LEX_STRING *name) else { size_t next_nmoffset= uint2korr(next_entry); - if (next_nmoffset > hdr->nmpool_size) + if (next_nmoffset > hdr->nmpool_size || next_nmoffset < nmoffset) return 1; name->length= next_nmoffset - nmoffset; } diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 79956002b6940..ec991480da7a1 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -31,7 +31,7 @@ fi safe() { - if [[ "${!1}" = *[\ \'\`]* ]]; then + if [[ "${!1}" = *[\ \'\`\$]* ]]; then wsrep_log_error "Invalid value for $1: ${!1}" exit 21 fi diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 5b7efbf3b60d9..540fe432dd2d3 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -251,7 +251,7 @@ if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then exit 22 # EINVAL fi if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then - CHECK_OPT="checkHost = $WSREP_SST_OPT_REMOTE_USER" + CHECK_OPT="checkHost = $(safe WSREP_SST_OPT_REMOTE_USER)" elif [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then # check if the address is an ip-address (v4 or v6): if echo "$WSREP_SST_OPT_HOST_UNESCAPED" | \ @@ -645,8 +645,9 @@ FILTER="-f '- /lost+found' echo "$STATE" > "$MAGIC_FILE" if [ -n "$WSREP_SST_OPT_REMOTE_PSWD" ]; then - # Let joiner know that we know its secret - echo "$SECRET_TAG $WSREP_SST_OPT_REMOTE_PSWD" >> "$MAGIC_FILE" + # Let joiner know that we know its secret. + WSREP_SST_OPT_REMOTE_PSWD_=$(safe WSREP_SST_OPT_REMOTE_PSWD) + echo "$SECRET_TAG $WSREP_SST_OPT_REMOTE_PSWD_" >> "$MAGIC_FILE" fi if [ $WSREP_SST_OPT_BYPASS -ne 0 ]; then diff --git a/sql/field.cc b/sql/field.cc index 9f1ec7d318a5d..231224e2f461c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8830,7 +8830,7 @@ int Field_blob::store(const char *from,size_t length,CHARSET_INFO *cs) DBUG_ASSERT(length <= max_data_length()); new_length= length; - copy_length= table->in_use->variables.group_concat_max_len; + copy_length= table->in_use->gconcat_max_len(); if (new_length > copy_length) { new_length= Well_formed_prefix(cs, diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 13d2f86128a9a..103fdf199373b 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -4451,9 +4451,10 @@ Item_func_json_objectagg::fix_fields(THD *thd, Item **ref) result.set_charset(collation.collation); result_field= 0; null_value= 1; - max_length= (uint32)(thd->variables.group_concat_max_len - / collation.collation->mbminlen - * collation.collation->mbmaxlen); + max_length= (uint32) MY_MIN((ulonglong) thd->gconcat_max_len() + / collation.collation->mbminlen + * collation.collation->mbmaxlen, UINT_MAX32); + if (check_sum_func(thd, ref)) return TRUE; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 45c8c4e87b0bf..b1caf4767494c 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -4413,7 +4413,7 @@ String *Item_func_quote::val_str(String *str) ulong max_allowed_packet= current_thd->variables.max_allowed_packet; char *from, *to, *end, *start; String *arg= args[0]->val_str(&tmp_value); - uint arg_length, new_length; + size_t arg_length, new_length; if (!arg) // Null argument { /* Return the string 'NULL' */ diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 580a13e1c5445..c306869d7fc57 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3819,7 +3819,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), { Item_func_group_concat *item= (Item_func_group_concat *) item_arg; TABLE *table= item->table; - uint max_length= table->in_use->variables.group_concat_max_len; + uint max_length= table->in_use->gconcat_max_len(); String tmp((char *)table->record[1], table->s->reclength, default_charset_info); String tmp2; @@ -4149,7 +4149,7 @@ bool Item_func_group_concat::repack_tree(THD *thd) DBUG_ASSERT(tree->size_of_element == st.tree.size_of_element); st.table= table; st.len= 0; - st.maxlen= thd->variables.group_concat_max_len; + st.maxlen= thd->gconcat_max_len(); tree_walk(tree, ©_to_tree, &st, left_root_right); if (st.len <= st.maxlen) // Copying aborted. Must be OOM { @@ -4228,7 +4228,7 @@ bool Item_func_group_concat::add(bool exclude_nulls) { THD *thd= table->in_use; table->field[0]->store(row_str_len, FALSE); - if ((tree_len >> GCONCAT_REPACK_FACTOR) > thd->variables.group_concat_max_len + if ((tree_len >> GCONCAT_REPACK_FACTOR) > thd->gconcat_max_len() && tree->elements_in_tree > 1) if (repack_tree(thd)) return 1; @@ -4281,7 +4281,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) result.set_charset(collation.collation); result_field= 0; null_value= 1; - max_length= (uint32) MY_MIN((ulonglong) thd->variables.group_concat_max_len + max_length= (uint32) MY_MIN((ulonglong) thd->gconcat_max_len() / collation.collation->mbminlen * collation.collation->mbmaxlen, UINT_MAX32); @@ -4373,8 +4373,7 @@ bool Item_func_group_concat::setup(THD *thd) Prepend the field to store the length of the string representation of this row. Used to detect when the tree goes over group_concat_max_len */ - Item *item= new (thd->mem_root) - Item_uint(thd, thd->variables.group_concat_max_len); + Item *item= new (thd->mem_root) Item_uint(thd, thd->gconcat_max_len()); if (!item || all_fields.push_front(item, thd->mem_root)) DBUG_RETURN(TRUE); } diff --git a/sql/proxy_protocol.cc b/sql/proxy_protocol.cc index f3ae2f729584a..8b458815aef36 100644 --- a/sql/proxy_protocol.cc +++ b/sql/proxy_protocol.cc @@ -129,11 +129,15 @@ static int parse_v2_header(uchar *hdr, size_t len,proxy_peer_info *peer_info) switch (fam) { case 0x11: /* TCPv4 */ + if (len < 25) + return -1; sin->sin_family= AF_INET; memcpy(&(sin->sin_addr), hdr + 16, 4); peer_info->port= (hdr[24] << 8) + hdr[25]; break; case 0x21: /* TCPv6 */ + if (len < 49) + return -1; sin6->sin6_family= AF_INET6; memcpy(&(sin6->sin6_addr), hdr + 16, 16); peer_info->port= (hdr[48] << 8) + hdr[49]; @@ -218,7 +222,7 @@ int parse_proxy_protocol_header(NET *net, proxy_peer_info *peer_info) if (len < 0) return -1; // 2 last bytes are the length in network byte order of the part following header - ushort trail_len= ((ushort)hdr[PROXY_V2_HEADER_LEN-2] >> 8) + hdr[PROXY_V2_HEADER_LEN-1]; + ushort trail_len= ((ushort)hdr[PROXY_V2_HEADER_LEN-2] << 8) + hdr[PROXY_V2_HEADER_LEN-1]; if (trail_len > sizeof(hdr) - PROXY_V2_HEADER_LEN) return -1; if (trail_len > 0) @@ -304,6 +308,8 @@ static int parse_subnet(char *addr_str, struct subnet *subnet) subnet->bits= 0; return 0; } + else + return -1; char *pmask= strchr(addr_str, '/'); if (!pmask) @@ -364,7 +370,7 @@ static int parse_networks(const char *subnets_str, subnet **out_subnets, size_t goto end; } - max_subnets= MY_MAX(3,strlen(subnets_str)/2); + max_subnets= MY_MAX(3,strlen(subnets_str)/3+1); subnets= (subnet *)my_malloc(PSI_INSTRUMENT_ME, max_subnets * sizeof(subnet), MY_ZEROFILL); diff --git a/sql/spatial.cc b/sql/spatial.cc index 38df7072154b9..2a7c8104584d0 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -916,7 +916,7 @@ const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data, uint32 Gis_point::get_data_size() const { - return POINT_DATA_SIZE; + return no_data(m_data, POINT_DATA_SIZE) ? GET_SIZE_ERROR : POINT_DATA_SIZE; } diff --git a/sql/sql_class.h b/sql/sql_class.h index aa78312c3b6a5..ea7ddca949a27 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5905,6 +5905,12 @@ class THD: public THD_count, /* this must be first */ (variables.note_verbosity & NOTE_VERBOSITY_EXPLAIN))); } + uint gconcat_max_len() + { + return MY_MIN(variables.group_concat_max_len, + (uint)variables.max_allowed_packet); + } + bool vers_insert_history_fast(const TABLE *table) { DBUG_ASSERT(table->versioned()); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 8a5b1a14bcca7..bb0d5630a4c4c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2853,7 +2853,7 @@ int Lex_input_stream::scan_ident_middle(THD *thd, Lex_ident_cli_st *str, yylineno++; } } - if (start == get_ptr() && c == '.' && ident_map[(uchar) yyPeek()] && !my_isdigit(cs, yyPeek())) + if (start == get_ptr() && c == '.' && ident_map[(uchar) yyPeek()]) next_state= MY_LEX_IDENT_SEP; else { // '(' must follow directly if function @@ -12511,4 +12511,4 @@ bool SELECT_LEX_UNIT::is_derived_eliminated() const if (!derived->table) return true; return derived->table->map & outer_select()->join->eliminated_tables; -} \ No newline at end of file +} diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 7a18cc640ee5c..891624f2f7edc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2037,29 +2037,43 @@ bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List *fields, #ifdef WITH_WSREP if (WSREP(thd)) { - bool transactional= false; - bool non_trans= false; - for (TABLE_LIST *tablel= table_list; tablel; tablel= tablel->next_global) - { - TABLE *table= tablel->table; - if (table->file->has_transactions_and_rollback()) - transactional= true; - else - non_trans= true; - } - /* In multi-table update Galera does not support update to both - transactional and non-transactional engines if write-set - size is limited. */ - bool limited = (wsrep_max_ws_rows || wsrep_max_ws_size != WSREP_MAX_WS_SIZE); - if (transactional && non_trans && limited) + const bool limited = (wsrep_max_ws_rows || + (wsrep_max_ws_size != WSREP_MAX_WS_SIZE)); + + if (limited) { - my_error(ER_GALERA_REPLICATION_NOT_SUPPORTED, MYF(0)); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_GALERA_REPLICATION_NOT_SUPPORTED, - "Galera does not support multi-table update", - " to both transactional and non-transactional engines" - " if write-set size is limited."); - DBUG_RETURN(1); + /* Write set size is limited, check if this update contains + updates to both transactional and non-transactional table. */ + bool transactional= false; + bool non_trans= false; + for (TABLE_LIST *tablel= table_list; tablel; tablel= tablel->next_global) + { + TABLE *table= tablel->table; + /* This can happen on multi-table update if one of the + tables updated is referenced by foreign key from other not + updated table. Not updated table is not yet opened, thus + there is item on table list but actual table is NULL. */ + if (!table) + continue; + /* Table has been opened, check is SE transactional or not. */ + if (table->file->has_transactions_and_rollback()) + transactional= true; + else + non_trans= true; + } + /* In multi-table update Galera does not support update to both + transactional and non-transactional engines if write-set + size is limited. */ + if (transactional && non_trans) + { + my_error(ER_GALERA_REPLICATION_NOT_SUPPORTED, MYF(0)); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_GALERA_REPLICATION_NOT_SUPPORTED, + "Galera does not support multi-table update", + " to both transactional and non-transactional engines" + " if write-set size is limited."); + DBUG_RETURN(1); + } } } #endif /* WITH_WSREP */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 01b04ac446392..9b2e76b00b836 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1687,7 +1687,7 @@ static Sys_var_ulong Sys_max_allowed_packet( "max_allowed_packet", "Max packet length to send to or receive from the server", SESSION_VAR(max_allowed_packet), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(1024, 1024*1024*1024), DEFAULT(16*1024*1024), + VALID_RANGE(1024, MAX_MAX_ALLOWED_PACKET), DEFAULT(16*1024*1024), BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_max_allowed_packet)); @@ -5087,7 +5087,8 @@ static Sys_var_uint Sys_group_concat_max_len( "group_concat_max_len", "The maximum length of the result of function GROUP_CONCAT()", SESSION_VAR(group_concat_max_len), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(4, UINT_MAX32), DEFAULT(1024*1024), BLOCK_SIZE(1)); + VALID_RANGE(4, MAX_MAX_ALLOWED_PACKET), DEFAULT(1024*1024), + BLOCK_SIZE(1)); static char *glob_hostname_ptr; static Sys_var_charptr Sys_hostname( diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc index fd086ce4a891f..fa17541d3e8d4 100644 --- a/sql/wsrep_notify.cc +++ b/sql/wsrep_notify.cc @@ -14,11 +14,39 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #include "mariadb.h" +#include #include #include "wsrep_priv.h" #include "wsrep_utils.h" #include "wsrep_status.h" +/* Allow only alnum and -_. */ +static bool is_valid_node_name(const char* s) +{ + if (!s) return true; + for (; *s; ++s) + { + unsigned char c= (unsigned char) *s; + if (!isalnum(c) && c != '-' && c != '_' && c != '.') + return false; + } + return true; +} + +/* Allow alnum and -_.:[]/ (host:port and [ipv6] forms). */ +static bool is_valid_node_addr(const char* s) +{ + if (!s) return true; + for (; *s; ++s) + { + unsigned char c= (unsigned char) *s; + if (!isalnum(c) && c != '-' && c != '_' && c != '.' && + c != ':' && c != '[' && c != ']' && c != '/') + return false; + } + return true; +} + void wsrep_notify_status(enum wsrep::server_state::state status, const wsrep::view* view) { @@ -71,13 +99,22 @@ void wsrep_notify_status(enum wsrep::server_state::state status, for (unsigned int i= 0; i < members.size(); i++) { + const char* name= members[i].name().c_str(); + const char* incoming= members[i].incoming().c_str(); + if (!is_valid_node_name(name) || !is_valid_node_addr(incoming)) + { + WSREP_ERROR("Unsafe characters in cluster member %u " + "wsrep_node_name or wsrep_node_incoming_address, " + "aborting notification.", i); + my_free(cmd_ptr); + return; + } std::ostringstream id; id << members[i].id(); cmd_off += snprintf(cmd_ptr + cmd_off, cmd_len - cmd_off, "%c%s/%s/%s", i > 0 ? ',' : ' ', id.str().c_str(), - members[i].name().c_str(), - members[i].incoming().c_str()); + name, incoming); } } } diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 7866d7d016625..176fc55433da9 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1,5 +1,5 @@ -/* Copyright 2008-2022 Codership Oy - Copyright (c) 2008, 2022, MariaDB +/* Copyright (C) 2008, 2025 Codership Oy + Copyright (c) 2008, 2026, MariaDB 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 @@ -182,6 +182,12 @@ static bool filename_char(int const c) return isalnum(c) || (c == '-') || (c == '_') || (c == '.'); } +/* return true if string is comma seprated list */ +static bool comma_char(int const c) +{ + return (c == ','); +} + /* return true if character can be a part of an address string */ static bool address_char(int const c) { @@ -189,6 +195,12 @@ static bool address_char(int const c) (c == ':') || (c == '[') || (c == ']') || (c == '/'); } +/* return true if character can be a part of an address string list */ +static bool names_list(int const c) +{ + return address_char(c) || comma_char(c); +} + static bool check_request_str(const char* const str, bool (*check) (int c), bool log_warn = true) @@ -260,8 +272,19 @@ static void make_wsrep_defaults_file() bool wsrep_sst_receive_address_check (sys_var *self, THD* thd, set_var* var) { - if ((! var->save_result.string_value.str) || - (var->save_result.string_value.length > (FN_REFLEN - 1))) // safety + /* Allow empty value */ + if (!var->save_result.string_value.str || var->save_result.string_value.length == 0) + return 0; + + /* Check length */ + if ((var->save_result.string_value.length > (FN_REFLEN - 1))) // safety + { + goto err; + } + + /* check also that address contains only accepted characters */ + if (check_request_str(var->save_result.string_value.str, + address_char, false)) { goto err; } @@ -343,16 +366,29 @@ void wsrep_sst_auth_init () bool wsrep_sst_donor_check (sys_var *self, THD* thd, set_var* var) { - if ((! var->save_result.string_value.str) || - (var->save_result.string_value.length > (FN_REFLEN -1))) // safety + /* Check length */ + if (!var->save_result.string_value.str || + var->save_result.string_value.length > FN_REFLEN-1) // safety + goto err; + + /* Allow empty value */ + if (var->save_result.string_value.length == 0) + return 0; + + /* check also that donor string contains only accepted characters */ + if (check_request_str(var->save_result.string_value.str, + names_list, false)) { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - var->save_result.string_value.str ? - var->save_result.string_value.str : "NULL"); - return 1; + goto err; } return 0; + +err: + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL"); + return 1; } bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) diff --git a/storage/columnstore/CMakeLists.txt b/storage/columnstore/CMakeLists.txt index 03b4db7047da4..690ac604300fb 100644 --- a/storage/columnstore/CMakeLists.txt +++ b/storage/columnstore/CMakeLists.txt @@ -28,6 +28,7 @@ CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") MY_CHECK_AND_SET_COMPILER_FLAG("-fno-lto") SET(PCRE_INCLUDES "${PCRE_INCLUDE_DIRS}") + set(CMAKE_POLICY_VERSION_MINIMUM 3.5) add_subdirectory(columnstore) IF(TARGET columnstore) diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 7d46daa210769..1f559a3864a7e 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -219,23 +219,13 @@ trx_print_low( /*!< in: mem_heap_get_size(trx->lock.lock_heap) */ /**********************************************************************//** -Prints info about a transaction. -When possible, use trx_print() instead. */ +Prints info about a transaction. */ void trx_print_latched( /*==============*/ FILE* f, /*!< in: output stream */ const trx_t* trx); /*!< in: transaction */ -/**********************************************************************//** -Prints info about a transaction. -Acquires and releases lock_sys.latch. */ -void -trx_print( -/*======*/ - FILE* f, /*!< in: output stream */ - const trx_t* trx); /*!< in: transaction */ - /**********************************************************************//** Determines if a transaction is in the given state. The caller must hold trx->mutex, or it must be the thread diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index e622b7f78f323..b3b2b48eb1f19 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1864,8 +1864,7 @@ trx_print_low( /**********************************************************************//** Prints info about a transaction. -The caller must hold lock_sys.latch. -When possible, use trx_print() instead. */ +The caller must hold lock_sys.latch. */ void trx_print_latched( /*==============*/ @@ -1880,27 +1879,6 @@ trx_print_latched( mem_heap_get_size(trx->lock.lock_heap)); } -/**********************************************************************//** -Prints info about a transaction. -Acquires and releases lock_sys.latch. */ -TRANSACTIONAL_TARGET -void -trx_print( -/*======*/ - FILE* f, /*!< in: output stream */ - const trx_t* trx) /*!< in: transaction */ -{ - ulint n_rec_locks, n_trx_locks, heap_size; - { - TMLockMutexGuard g{SRW_LOCK_CALL}; - n_rec_locks= trx->lock.n_rec_locks; - n_trx_locks= UT_LIST_GET_LEN(trx->lock.trx_locks); - heap_size= mem_heap_get_size(trx->lock.lock_heap); - } - - trx_print_low(f, trx, n_rec_locks, n_trx_locks, heap_size); -} - /** Prepare a transaction. @return log sequence number that makes the XA PREPARE durable @retval 0 if no changes needed to be made durable */ diff --git a/storage/perfschema/table_events_waits.cc b/storage/perfschema/table_events_waits.cc index 59b99dabc0f37..dbfe98e105de4 100644 --- a/storage/perfschema/table_events_waits.cc +++ b/storage/perfschema/table_events_waits.cc @@ -39,6 +39,8 @@ THR_LOCK table_events_waits_current::m_table_lock; +#define OBJECT_INSTANCE_BEGIN(X) (((intptr)X) - ((intptr) &pfs_truncatable_acl)) + PFS_engine_table_share_state table_events_waits_current::m_share_state = { false /* m_checked */ @@ -251,7 +253,7 @@ int table_events_waits_common::make_table_object_columns(PFS_events_waits *wait) m_row.m_index_name_length= 0; } - m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr; + m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); return 0; } @@ -266,7 +268,7 @@ int table_events_waits_common::make_file_object_columns(PFS_events_waits *wait) m_row.m_object_type= "FILE"; m_row.m_object_type_length= 4; m_row.m_object_schema_length= 0; - m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr; + m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); if (safe_file->get_version() == wait->m_weak_version) { @@ -298,7 +300,7 @@ int table_events_waits_common::make_socket_object_columns(PFS_events_waits *wait m_row.m_object_type= "SOCKET"; m_row.m_object_type_length= 6; m_row.m_object_schema_length= 0; - m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr; + m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); if (safe_socket->get_version() == wait->m_weak_version) { @@ -432,7 +434,7 @@ int table_events_waits_common::make_metadata_lock_object_columns(PFS_events_wait if (m_row.m_object_name_length > 0) memcpy(m_row.m_object_name, mdl->name(), m_row.m_object_name_length); - m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr; + m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); } else { @@ -498,17 +500,17 @@ void table_events_waits_common::make_row(PFS_events_waits *wait) break; case WAIT_CLASS_MUTEX: clear_object_columns(); - m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr; + m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); safe_class= sanitize_mutex_class((PFS_mutex_class*) wait->m_class); break; case WAIT_CLASS_RWLOCK: clear_object_columns(); - m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr; + m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); safe_class= sanitize_rwlock_class((PFS_rwlock_class*) wait->m_class); break; case WAIT_CLASS_COND: clear_object_columns(); - m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr; + m_row.m_object_instance_addr= OBJECT_INSTANCE_BEGIN(wait->m_object_instance_addr); safe_class= sanitize_cond_class((PFS_cond_class*) wait->m_class); break; case WAIT_CLASS_TABLE: diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 41b624206dc43..59ab2bc2af73a 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -20572,12 +20572,12 @@ static void test_proxy_header_tcp(const char *ipaddr, int port) MYSQL_RES *result; int family = (strchr(ipaddr,':') == NULL)?AF_INET:AF_INET6; char query[256]; - char text_header[256]; + char text_header[256], bad_text_header[256]; char addr_bin[16]; - v2_proxy_header v2_header; - void *header_data[2]; - size_t header_lengths[2]; - int i; + v2_proxy_header v2_header, bad_v2_header; + void *header_data[4]; + size_t header_lengths[4]; + size_t i; // normalize IPv4-mapped IPv6 addresses, e.g ::ffff:127.0.0.2 to 127.0.0.2 const char *normalized_addr= strncmp(ipaddr, "::ffff:", 7)?ipaddr : ipaddr + 7; @@ -20615,9 +20615,19 @@ static void test_proxy_header_tcp(const char *ipaddr, int port) header_data[0]= text_header; header_data[1]= &v2_header; + header_data[2]= bad_text_header; + header_data[3]= &bad_v2_header; header_lengths[0]= strlen(text_header); header_lengths[1]= family == AF_INET ? 28 : 52; + header_lengths[2]= sizeof(text_header)-4; + header_lengths[3]= header_lengths[1]; + + memset(bad_text_header, ' ', sizeof(bad_text_header)); + memcpy(bad_text_header, text_header, header_lengths[1]-6); + + bad_v2_header= v2_header; + bad_v2_header.len= 0; for (i = 0; i < 2; i++) { @@ -20628,9 +20638,8 @@ static void test_proxy_header_tcp(const char *ipaddr, int port) DIE_UNLESS(m); mysql_optionsv(m, MARIADB_OPT_PROXY_HEADER, header_data[i], header_lengths[i]); if (!mysql_real_connect(m, opt_host, "u", "password", NULL, opt_port, opt_unix_socket, 0)) - { - DIE_UNLESS(0); - } + DIE(0); + rc= mysql_query(m, "select host from information_schema.processlist WHERE ID = connection_id()"); myquery(rc); /* get the result */ @@ -20647,6 +20656,21 @@ static void test_proxy_header_tcp(const char *ipaddr, int port) /* do "dirty" close, to get aborted message in error log.*/ mariadb_cancel(m); } + + mysql_close(m); + } + for (; i < array_elements(header_data); i++) + { + MYSQL *m; + m = mysql_client_init(NULL); + DIE_UNLESS(m); + mysql_optionsv(m, MARIADB_OPT_PROXY_HEADER, header_data[i], header_lengths[i]); + if (mysql_real_connect(m, opt_host, "u", "password", NULL, opt_port, opt_unix_socket, 0)) + DIE(0); + printf("pass %zu error %i - %s\n", i, mysql_errno(m), + mysql_error(m)); + DIE_IF(i == 2 && mysql_errno(m) != ER_UNKNOWN_ERROR); + DIE_IF(i == 3 && mysql_errno(m) != ER_UNKNOWN_ERROR); mysql_close(m); } snprintf(query, sizeof(query), "DROP USER 'u'@'%s'",normalized_addr);