From 5683c113b817644ffa5ba13c2485ce259250a8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 5 Dec 2019 07:58:02 +0200 Subject: [PATCH 1/5] Use get_ident_len in heartbeat event error messages The string doesn't appear to be null-terminated when binlog checksums are enabled. This causes a corrupt binlog name in the error message when a slave is ahead of the master. --- sql/slave.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index a8946c69d18..ae1c5ca2cf8 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4444,7 +4444,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) error= ER_SLAVE_HEARTBEAT_FAILURE; error_msg.append(STRING_WITH_LEN("inconsistent heartbeat event content;")); error_msg.append(STRING_WITH_LEN("the event's data: log_file_name ")); - error_msg.append(hb.get_log_ident(), (uint) strlen(hb.get_log_ident())); + error_msg.append(hb.get_log_ident(), (uint) hb.get_ident_len()); error_msg.append(STRING_WITH_LEN(" log_pos ")); llstr(hb.log_pos, llbuf); error_msg.append(llbuf, strlen(llbuf)); @@ -4471,7 +4471,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) error= ER_SLAVE_HEARTBEAT_FAILURE; error_msg.append(STRING_WITH_LEN("heartbeat is not compatible with local info;")); error_msg.append(STRING_WITH_LEN("the event's data: log_file_name ")); - error_msg.append(hb.get_log_ident(), (uint) strlen(hb.get_log_ident())); + error_msg.append(hb.get_log_ident(), (uint) hb.get_ident_len()); error_msg.append(STRING_WITH_LEN(" log_pos ")); llstr(hb.log_pos, llbuf); error_msg.append(llbuf, strlen(llbuf)); From 409aba3d997e97287bc67467ef437164c9e70b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 16 Jan 2020 12:40:45 +0200 Subject: [PATCH 2/5] Improve documentation of Unique class * size represents the size of an element in the Unique class * full_size is used when the Unique class counts the number of duplicates stored per element. This requires additional space per Unique element. --- sql/sql_class.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sql/sql_class.h b/sql/sql_class.h index 4a390545593..2fac8d4e87f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3923,16 +3923,21 @@ class user_var_entry class Unique :public Sql_alloc { DYNAMIC_ARRAY file_ptrs; - ulong max_elements; + ulong max_elements; /* Total number of elements that will be stored in-memory */ ulonglong max_in_memory_size; IO_CACHE file; TREE tree; uchar *record_pointers; + /* Number of elements filtered out due to min_dupl_count when storing results + to table. See Unique::get */ ulong filtered_out_elems; bool flush(); - uint size; - uint full_size; - uint min_dupl_count; /* always 0 for unions, > 0 for intersections */ + uint size; /* Size of element stored in unique object. */ + uint full_size; /* Size of element + space needed to store the number of + duplicates found for the element. */ + uint min_dupl_count; /* Minimum number of occurences of element required for + it to be written to record_pointers. + always 0 for unions, > 0 for intersections */ bool merge(TABLE *table, uchar *buff, bool without_last_merge); From 1bee9efcc44d94e92a0908a3b431fc45f4490807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 16 Jan 2020 13:37:21 +0200 Subject: [PATCH 3/5] MDEV-21210: main.uniques_crash-7912 tries to allocate 1TB of memory Remove the offending test case. This sort of error is hard to test in all possible corner cases and thus makes the test less valuable. The overflow error will be covered by warnings generated by the compiler, which is much more reliable in the general case. --- mysql-test/r/uniques_crash-7912.result | 11 ----------- mysql-test/t/uniques_crash-7912.test | 26 -------------------------- 2 files changed, 37 deletions(-) delete mode 100644 mysql-test/r/uniques_crash-7912.result delete mode 100644 mysql-test/t/uniques_crash-7912.test diff --git a/mysql-test/r/uniques_crash-7912.result b/mysql-test/r/uniques_crash-7912.result deleted file mode 100644 index bf3aab684ae..00000000000 --- a/mysql-test/r/uniques_crash-7912.result +++ /dev/null @@ -1,11 +0,0 @@ -call mtr.add_suppression("Out of memory"); -set sql_mode=""; -drop table if exists t1,t2; -create table `t1` (`a` datetime not null) engine=InnoDB; -create table `t2` (`a` int not null) engine=innodb; -replace into t1 values (),(); -insert into t2 values(0); -set session sort_buffer_size = 1024*1024*1024*1024; -delete d2 from t2 as d1, t1 as d2 where d1.a <=> d2.a; -drop table t2; -drop table t1; diff --git a/mysql-test/t/uniques_crash-7912.test b/mysql-test/t/uniques_crash-7912.test deleted file mode 100644 index 8dc82f8f540..00000000000 --- a/mysql-test/t/uniques_crash-7912.test +++ /dev/null @@ -1,26 +0,0 @@ -# -# MDEV-7912 -# -# multitable delete with wrongly set sort_buffer_size crashes in merge_buffers - ---source include/have_innodb.inc ---source include/have_debug.inc ---source include/windows.inc - -call mtr.add_suppression("Out of memory"); - -set sql_mode=""; ---disable_warnings -drop table if exists t1,t2; -create table `t1` (`a` datetime not null) engine=InnoDB; -create table `t2` (`a` int not null) engine=innodb; -replace into t1 values (),(); -insert into t2 values(0); -set session sort_buffer_size = 1024*1024*1024*1024; -#Either fail with EE_OUTOFMEMORY, or succeed ---error 0 , 5 -delete d2 from t2 as d1, t1 as d2 where d1.a <=> d2.a; ---enable_warnings - -drop table t2; -drop table t1; From 49b9ce15ef1e27ce27b6c173ec8f82dcdffba956 Mon Sep 17 00:00:00 2001 From: Maheedhar PV Date: Wed, 20 Nov 2019 08:10:36 +0530 Subject: [PATCH 4/5] Bug#30194841 INSERT ON DUPLICATE KEY UPDATE UPDATES THE WRONG ROW test case only --- mysql-test/r/insert_debug.result | 25 +++++++++++++ mysql-test/t/insert_debug-master.opt | 1 + mysql-test/t/insert_debug.test | 54 ++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 mysql-test/r/insert_debug.result create mode 100644 mysql-test/t/insert_debug-master.opt create mode 100644 mysql-test/t/insert_debug.test diff --git a/mysql-test/r/insert_debug.result b/mysql-test/r/insert_debug.result new file mode 100644 index 00000000000..ef4f304800a --- /dev/null +++ b/mysql-test/r/insert_debug.result @@ -0,0 +1,25 @@ +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +CREATE TABLE t1(c1 VARCHAR(10) NOT NULL, c2 VARCHAR(10) NOT NULL, c3 VARCHAR(10) NOT NULL); +INSERT INTO t1(c1, c2, c3) VALUES('A1','B1','IT1'), ('A2','B2','IT1'), ('A3','B3','IT1'), ('A4','B4','IT1'), ('A5','B5','IT1'), ('A6','B6','IT1'), ('A7','B7','IT1'); +CREATE TABLE t2(c1 VARCHAR(10) NOT NULL, c2 VARCHAR(10) NOT NULL, c3 VARCHAR(10) NOT NULL); +INSERT INTO t2(c1, c2, c3) VALUES ('A3','B3','IT2'), ('A2','B2','IT2'), ('A4','B4','IT2'), ('A5','B5','II2'); +CREATE TABLE result(id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, c1 VARCHAR(10) NOT NULL, c2 VARCHAR(10), +c3 VARCHAR(10), update_count INT DEFAULT 0, UNIQUE KEY uniq_idx (c1,c2), PRIMARY KEY (id)) ENGINE = innodb; +SET DEBUG_SYNC = "ha_write_row_end WAIT_FOR flushed EXECUTE 1"; +INSERT INTO result(c1, c2, c3) SELECT * FROM t1 ON DUPLICATE KEY UPDATE c2=t1.c2, c3='UT1', update_count=update_count+1; +INSERT INTO result(c1, c2, c3) SELECT * FROM t2 ON DUPLICATE KEY UPDATE c2=t2.c2, c3='UT2', update_count=update_count+1; +SET DEBUG_SYNC = "now SIGNAL flushed"; +SELECT * FROM result; +id c1 c2 c3 update_count +1 A1 B1 IT1 0 +2 A3 B3 UT1 1 +3 A2 B2 UT1 1 +4 A4 B4 UT1 1 +5 A5 B5 UT1 1 +9 A6 B6 IT1 0 +10 A7 B7 IT1 0 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE result; +SET DEBUG_SYNC = "RESET"; diff --git a/mysql-test/t/insert_debug-master.opt b/mysql-test/t/insert_debug-master.opt new file mode 100644 index 00000000000..824f656cbd5 --- /dev/null +++ b/mysql-test/t/insert_debug-master.opt @@ -0,0 +1 @@ +--innodb_autoinc_lock_mode=2 diff --git a/mysql-test/t/insert_debug.test b/mysql-test/t/insert_debug.test new file mode 100644 index 00000000000..b35d6b838da --- /dev/null +++ b/mysql-test/t/insert_debug.test @@ -0,0 +1,54 @@ +source include/have_innodb.inc; +source include/have_debug.inc; +source include/have_debug_sync.inc; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; + +connect (con1, localhost, root,,); +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; + +connection default; + +let $conn0_id= `SELECT CONNECTION_ID()`; + +CREATE TABLE t1(c1 VARCHAR(10) NOT NULL, c2 VARCHAR(10) NOT NULL, c3 VARCHAR(10) NOT NULL); +INSERT INTO t1(c1, c2, c3) VALUES('A1','B1','IT1'), ('A2','B2','IT1'), ('A3','B3','IT1'), ('A4','B4','IT1'), ('A5','B5','IT1'), ('A6','B6','IT1'), ('A7','B7','IT1'); + +CREATE TABLE t2(c1 VARCHAR(10) NOT NULL, c2 VARCHAR(10) NOT NULL, c3 VARCHAR(10) NOT NULL); +INSERT INTO t2(c1, c2, c3) VALUES ('A3','B3','IT2'), ('A2','B2','IT2'), ('A4','B4','IT2'), ('A5','B5','II2'); + +CREATE TABLE result(id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, c1 VARCHAR(10) NOT NULL, c2 VARCHAR(10), +c3 VARCHAR(10), update_count INT DEFAULT 0, UNIQUE KEY uniq_idx (c1,c2), PRIMARY KEY (id)) ENGINE = innodb; + +# Insert one row from 't1' into the 'result' table and wait on a debug sync +# point. The next insert statement from an session 2 inserts values that would +# lead to unique key clash, when this insert resumes. +# The subsequent inserts of this statement(after resume) will fail because of a +# clash with the unique index, and are expected to update the row which clashes +# with the unique key. +# Without the fix for bug#30194841 a stale auto increment value, would cause a +# collision with existing auto increment column value and ends up updating that +# colliding row, instead of the row colliding with the unique index. +SET DEBUG_SYNC = "ha_write_row_end WAIT_FOR flushed EXECUTE 1"; +send INSERT INTO result(c1, c2, c3) SELECT * FROM t1 ON DUPLICATE KEY UPDATE c2=t1.c2, c3='UT1', update_count=update_count+1; + +# While session 1 is waiting (after one insert), insert rows that will cause a clash +# with the inserts of session 1 on the unique key. +connection con1; + +# Wait for the session 1 to hit the debug sync point. +let $wait_condition=SELECT 1 FROM information_schema.processlist WHERE id = $conn0_id AND state LIKE '%ha_write_row_end%'; +--source include/wait_condition.inc + +INSERT INTO result(c1, c2, c3) SELECT * FROM t2 ON DUPLICATE KEY UPDATE c2=t2.c2, c3='UT2', update_count=update_count+1; + +# Signal to resume the insert statement in session 1 +SET DEBUG_SYNC = "now SIGNAL flushed"; +connection default; +reap; +SELECT * FROM result; + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE result; +SET DEBUG_SYNC = "RESET"; From 4d1c1b23e1373bbd4e72f524e855f1db076d2c73 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 17 Jan 2020 15:08:11 +0100 Subject: [PATCH 5/5] Bug#29630767 - USE OF UNINITIALIZED VALUE IN LIBMYSQL (CLIENT.CC FUNCTION RUN_PLUGIN_AUTH) --- mysql-test/r/connect_debug.result | 8 ++++++++ mysql-test/t/connect_debug.test | 15 +++++++++++++++ sql-common/client.c | 5 ++++- sql/sql_acl.cc | 1 + 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/connect_debug.result b/mysql-test/r/connect_debug.result index 3151166a0e6..c455363eb41 100644 --- a/mysql-test/r/connect_debug.result +++ b/mysql-test/r/connect_debug.result @@ -8,3 +8,11 @@ create user 'bad' identified by 'worse'; ERROR 2059 (HY000): Authentication plugin 'foo/bar' cannot be loaded: invalid plugin name set global debug_dbug=@old_dbug; drop user bad; +set global debug_dbug='+d,increase_srv_handshake_scramble_len'; +connect(localhost,root,,test,MASTER_MYPORT,MYSQL_TMP_DIR/mysqld.1.sock); +ERROR HY000: Malformed packet +set global debug_dbug=@old_dbug; +set global debug_dbug='+d,poison_srv_handshake_scramble_len'; +connect(localhost,root,,test,MASTER_MYPORT,MYSQL_TMP_DIR/mysqld.1.sock); +ERROR HY000: Malformed packet +set global debug_dbug=@old_dbug; diff --git a/mysql-test/t/connect_debug.test b/mysql-test/t/connect_debug.test index 7a2f2872b79..de7a292ce67 100644 --- a/mysql-test/t/connect_debug.test +++ b/mysql-test/t/connect_debug.test @@ -21,3 +21,18 @@ create user 'bad' identified by 'worse'; --exec $MYSQL --default-auth=mysql_old_password --user=bad --password=worse 2>&1 set global debug_dbug=@old_dbug; drop user bad; + +# +# Bug#29630767 - USE OF UNINITIALIZED VALUE IN LIBMYSQL (CLIENT.CC FUNCTION RUN_PLUGIN_AUTH) +# +set global debug_dbug='+d,increase_srv_handshake_scramble_len'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR $MASTER_MYPORT MASTER_MYPORT +--error 2027 +connect con1,localhost,root; +set global debug_dbug=@old_dbug; + +set global debug_dbug='+d,poison_srv_handshake_scramble_len'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR $MASTER_MYPORT MASTER_MYPORT +--error 2027 +connect con2,localhost,root; +set global debug_dbug=@old_dbug; diff --git a/sql-common/client.c b/sql-common/client.c index f535b5119b7..c7fb70fbeef 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -3538,7 +3538,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, scramble_data_len= pkt_scramble_len; scramble_plugin= scramble_data + scramble_data_len; if (scramble_data + scramble_data_len > pkt_end) - scramble_data_len= pkt_end - scramble_data; + { + set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate); + goto error; + } } else { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8670f5b390d..ac1adf9e58b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8178,6 +8178,7 @@ static bool send_server_handshake_packet(MPVIO_EXT *mpvio, int2store(end+5, thd->client_capabilities >> 16); end[7]= data_len; DBUG_EXECUTE_IF("poison_srv_handshake_scramble_len", end[7]= -100;); + DBUG_EXECUTE_IF("increase_srv_handshake_scramble_len", end[7]= 50;); bzero(end + 8, 10); end+= 18; /* write scramble tail */