From a2770e98a6b53e6ec5d502c1e2228078ee149b3b Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 2 May 2016 09:26:00 +0200 Subject: Raise version number after cloning 5.5.50 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 58a6b369de9..db9d497c141 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=50 +MYSQL_VERSION_PATCH=51 MYSQL_VERSION_EXTRA= -- cgit v1.2.1 From 818b3a91231119663a95b854ab1e0e2d7a2d3feb Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Wed, 4 May 2016 14:06:45 +0530 Subject: Bug#12818255: READ-ONLY OPTION DOES NOT ALLOW INSERTS/UPDATES ON TEMPORARY TABLES Bug#14294223: CHANGES NOT ALLOWED TO TEMPORARY TABLES ON READ-ONLY SERVERS Problem: ======== Running 5.5.14 in read only we can create temporary tables but can not insert or update records in the table. When we try we get Error 1290 : The MySQL server is running with the --read-only option so it cannot execute this statement. Analysis: ========= This bug is very specific to binlog being enabled and binlog-format being stmt/mixed. Standalone server without binlog enabled or with row based binlog-mode works fine. How standalone server and row based replication work: ===================================================== Standalone server and row based replication mark the transactions as read_write only when they are modifying non temporary tables as part of their current transaction. Because of this when code enters commit phase it checks if a transaction is read_write or not. If the transaction is read_write and global read only mode is enabled those transaction will fail with 'server is read only mode' error. In the case of statement based mode at the time of writing to binary log a binlog handler is created and it is always marked as read_write. In case of temporary tables even though the engine did not mark the transaction as read_write but the new transaction that is started by binlog handler is considered as read_write. Hence in this case when code enters commit phase it finds one handler which has a read_write transaction even when we are modifying temporary table. This causes the server to throw an error when global read-only mode is enabled. Fix: ==== At the time of commit in "ha_commit_trans" if a read_write transaction is found, we should check if this transaction is coming from a handler other than binlog_handler. This will ensure that there is a genuine read_write transaction being sent by the engine apart from binlog_handler and only then it should be blocked. --- .../r/binlog_dmls_on_tmp_tables_readonly.result | 58 ++++++++++++++ .../t/binlog_dmls_on_tmp_tables_readonly.test | 90 ++++++++++++++++++++++ sql/handler.cc | 2 +- sql/log.cc | 8 +- sql/log.h | 2 +- sql/log_event.cc | 3 +- 6 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 mysql-test/suite/binlog/r/binlog_dmls_on_tmp_tables_readonly.result create mode 100644 mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test diff --git a/mysql-test/suite/binlog/r/binlog_dmls_on_tmp_tables_readonly.result b/mysql-test/suite/binlog/r/binlog_dmls_on_tmp_tables_readonly.result new file mode 100644 index 00000000000..1dfac08e762 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_dmls_on_tmp_tables_readonly.result @@ -0,0 +1,58 @@ +DROP TABLE IF EXISTS t1 ; +# READ_ONLY does nothing to SUPER users +# so we use a non-SUPER one: +GRANT CREATE, SELECT, DROP ON *.* TO test@localhost; +connect con1,localhost,test,,test; +connection default; +SET GLOBAL READ_ONLY=1; +connection con1; +CREATE TEMPORARY TABLE t1 (a INT) ENGINE=INNODB; +# Test INSERTS with autocommit being off and on. +BEGIN; +INSERT INTO t1 VALUES (10); +COMMIT; +INSERT INTO t1 VALUES (20); +# Test UPDATES with autocommit being off and on. +BEGIN; +UPDATE t1 SET a=30 WHERE a=10; +COMMIT; +UPDATE t1 SET a=40 WHERE a=20; +connection default; +SET GLOBAL READ_ONLY=0; +# Test scenario where global read_only is enabled in the middle of transaction. +# Test INSERT operations on temporary tables, INSERTs should be successful even +# when global read_only is enabled. +connection con1; +BEGIN; +INSERT INTO t1 VALUES(50); +connection default; +SET GLOBAL READ_ONLY=1; +connection con1; +SELECT @@GLOBAL.READ_ONLY; +@@GLOBAL.READ_ONLY +1 +COMMIT; +connection default; +SET GLOBAL READ_ONLY=0; +# Test UPDATE operations on temporary tables, UPDATEs should be successful even +# when global read_only is enabled. +connection con1; +BEGIN; +UPDATE t1 SET a=60 WHERE a=50; +connection default; +SET GLOBAL READ_ONLY=1; +connection con1; +SELECT @@GLOBAL.READ_ONLY; +@@GLOBAL.READ_ONLY +1 +COMMIT; +SELECT * FROM t1; +a +30 +40 +60 +# Clean up +connection default; +SET GLOBAL READ_ONLY=0; +disconnect con1; +DROP USER test@localhost; diff --git a/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test b/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test new file mode 100644 index 00000000000..30a6471bf61 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_dmls_on_tmp_tables_readonly.test @@ -0,0 +1,90 @@ +# ==== Purpose ==== +# +# Check that DMLs are allowed on temporary tables, when server is in read only +# mode and binary log is enabled with binlog-format being stmt/mixed mode. +# +# ==== Implementation ==== +# +# Start the server with binary log being enabled. Mark the server as read only. +# Create a non-SUPER user and let the user to create a temporary table and +# perform DML operations on that temporary table. DMLs should not be blocked +# with a 'server read-only mode' error. +# +# ==== References ==== +# +# Bug#12818255: READ-ONLY OPTION DOES NOT ALLOW INSERTS/UPDATES ON TEMPORARY +# TABLES +# Bug#14294223: CHANGES NOT ALLOWED TO TEMPORARY TABLES ON READ-ONLY SERVERS +############################################################################### +--source include/have_log_bin.inc +--disable_warnings +DROP TABLE IF EXISTS t1 ; +--enable_warnings + +--enable_connect_log +--echo # READ_ONLY does nothing to SUPER users +--echo # so we use a non-SUPER one: +GRANT CREATE, SELECT, DROP ON *.* TO test@localhost; + +connect (con1,localhost,test,,test); + +connection default; +SET GLOBAL READ_ONLY=1; + +connection con1; +CREATE TEMPORARY TABLE t1 (a INT) ENGINE=INNODB; + +--echo # Test INSERTS with autocommit being off and on. +BEGIN; +INSERT INTO t1 VALUES (10); +COMMIT; +INSERT INTO t1 VALUES (20); + +--echo # Test UPDATES with autocommit being off and on. +BEGIN; +UPDATE t1 SET a=30 WHERE a=10; +COMMIT; +UPDATE t1 SET a=40 WHERE a=20; + +connection default; +SET GLOBAL READ_ONLY=0; + +--echo # Test scenario where global read_only is enabled in the middle of transaction. +--echo # Test INSERT operations on temporary tables, INSERTs should be successful even +--echo # when global read_only is enabled. +connection con1; +BEGIN; +INSERT INTO t1 VALUES(50); + +connection default; +SET GLOBAL READ_ONLY=1; + +connection con1; +SELECT @@GLOBAL.READ_ONLY; +COMMIT; + +connection default; +SET GLOBAL READ_ONLY=0; + +--echo # Test UPDATE operations on temporary tables, UPDATEs should be successful even +--echo # when global read_only is enabled. +connection con1; +BEGIN; +UPDATE t1 SET a=60 WHERE a=50; + +connection default; +SET GLOBAL READ_ONLY=1; + +connection con1; +SELECT @@GLOBAL.READ_ONLY; +COMMIT; + +SELECT * FROM t1; + +--echo # Clean up +connection default; +SET GLOBAL READ_ONLY=0; + +disconnect con1; +DROP USER test@localhost; +--disable_connect_log diff --git a/sql/handler.cc b/sql/handler.cc index 9d57cba73dc..79cf7ac2fd9 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1279,7 +1279,7 @@ int ha_commit_trans(THD *thd, bool all) DEBUG_SYNC(thd, "ha_commit_trans_after_acquire_commit_lock"); } - if (rw_trans && + if (rw_trans && stmt_has_updated_trans_table(ha_info) && opt_readonly && !(thd->security_ctx->master_access & SUPER_ACL) && !thd->slave_thread) diff --git a/sql/log.cc b/sql/log.cc index a7f05905514..e0ba93b0959 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4562,17 +4562,15 @@ trans_has_updated_trans_table(const THD* thd) This function checks if a transactional table was updated by the current statement. - @param thd The client thread that executed the current statement. + @param ha_list Registered storage engine handler list. @return @c true if a transactional table was updated, @c false otherwise. */ bool -stmt_has_updated_trans_table(const THD *thd) +stmt_has_updated_trans_table(Ha_trx_info* ha_list) { Ha_trx_info *ha_info; - - for (ha_info= thd->transaction.stmt.ha_list; ha_info; - ha_info= ha_info->next()) + for (ha_info= ha_list; ha_info; ha_info= ha_info->next()) { if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton) return (TRUE); diff --git a/sql/log.h b/sql/log.h index 7d1c3161ac2..dd09cb41026 100644 --- a/sql/log.h +++ b/sql/log.h @@ -25,7 +25,7 @@ class Master_info; class Format_description_log_event; bool trans_has_updated_trans_table(const THD* thd); -bool stmt_has_updated_trans_table(const THD *thd); +bool stmt_has_updated_trans_table(Ha_trx_info* ha_list); bool use_trans_cache(const THD* thd, bool is_transactional); bool ending_trans(THD* thd, const bool all); bool ending_single_stmt_trans(THD* thd, const bool all); diff --git a/sql/log_event.cc b/sql/log_event.cc index 702cf1d575a..5dbeb1eb4b9 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2637,7 +2637,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, { cache_type= Log_event::EVENT_NO_CACHE; } - else if (using_trans || trx_cache || stmt_has_updated_trans_table(thd) || + else if (using_trans || trx_cache || + stmt_has_updated_trans_table(thd->transaction.stmt.ha_list) || thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(), thd->variables.binlog_direct_non_trans_update, trans_has_updated_trans_table(thd), -- cgit v1.2.1 From df7ecf64f5b9c6fb4b7789a414306de89b58bec7 Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Fri, 13 May 2016 16:42:45 +0530 Subject: Bug#23251517: SEMISYNC REPLICATION HANGING Revert following bug fix: Bug#20685029: SLAVE IO THREAD SHOULD STOP WHEN DISK IS FULL Bug#21753696: MAKE SHOW SLAVE STATUS NON BLOCKING IF IO THREAD WAITS FOR DISK SPACE This fix results in a deadlock between slave IO thread and SQL thread. --- mysql-test/include/assert_grep.inc | 154 --------------------- mysql-test/include/rpl_init.inc | 31 +---- mysql-test/include/rpl_reconnect.inc | 33 ++--- mysql-test/include/start_slave_sql.inc | 39 ------ .../rpl/r/rpl_io_thd_wait_for_disk_space.result | 15 -- .../rpl/t/rpl_io_thd_wait_for_disk_space.test | 71 ---------- mysys/errors.c | 14 +- mysys/my_write.c | 8 +- sql/log.cc | 75 +--------- sql/log.h | 5 +- sql/slave.cc | 38 ++--- sql/slave.h | 2 +- sql/sql_reload.cc | 2 +- 13 files changed, 41 insertions(+), 446 deletions(-) delete mode 100644 mysql-test/include/assert_grep.inc delete mode 100644 mysql-test/include/start_slave_sql.inc delete mode 100644 mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result delete mode 100644 mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test diff --git a/mysql-test/include/assert_grep.inc b/mysql-test/include/assert_grep.inc deleted file mode 100644 index a980a6d73b1..00000000000 --- a/mysql-test/include/assert_grep.inc +++ /dev/null @@ -1,154 +0,0 @@ -# ==== Purpose ==== -# -# Grep a file for a pattern, produce a single string out of the -# matching lines, and assert that the string matches a given regular -# expression. -# -# ==== Usage ==== -# -# --let $assert_text= TEXT -# --let $assert_file= FILE -# --let $assert_select= REGEX -# [--let $assert_match= REGEX | --let $assert_count= NUMBER] -# [--let $assert_only_after= REGEX] -# --source include/assert_grep.inc -# -# Parameters: -# -# $assert_text -# Text that describes what is being checked. This text is written to -# the query log so it should not contain non-deterministic elements. -# -# $assert_file -# File to search. -# -# $assert_select -# All lines matching this text will be checked. -# -# $assert_match -# The script will find all lines that match $assert_select, -# concatenate them to a long string, and assert that it matches -# $assert_match. -# -# $assert_count -# Instead of asserting that the selected lines match -# $assert_match, assert that there were exactly $assert_count -# matching lines. -# -# $assert_only_after -# Reset all the lines matched and the counter when finding this pattern. -# It is useful for searching things in the mysqld.err log file just -# after the last server restart for example (discarding the log content -# of previous server executions). - - -if (!$assert_text) -{ - --die !!!ERROR IN TEST: you must set $assert_text -} -if (!$assert_file) -{ - --die !!!ERROR IN TEST: you must set $assert_file -} -if (!$assert_select) -{ - --die !!!ERROR IN TEST: you must set $assert_select -} -if ($assert_match == '') -{ - if ($assert_count == '') - { - --die !!!ERROR IN TEST: you must set either $assert_match or $assert_count - } -} -if ($assert_match != '') -{ - if ($assert_count != '') - { - --echo assert_text='$assert_text' assert_count='$assert_count' - --die !!!ERROR IN TEST: you must set only one of $assert_match or $assert_count - } -} - - ---let $include_filename= assert_grep.inc [$assert_text] ---source include/begin_include_file.inc - - ---let _AG_ASSERT_TEXT= $assert_text ---let _AG_ASSERT_FILE= $assert_file ---let _AG_ASSERT_SELECT= $assert_select ---let _AG_ASSERT_MATCH= $assert_match ---let _AG_ASSERT_COUNT= $assert_count ---let _AG_OUT= `SELECT CONCAT('$MYSQLTEST_VARDIR/tmp/_ag_', UUID())` ---let _AG_ASSERT_ONLY_AFTER= $assert_only_after - - ---perl - use strict; - use warnings; - my $file= $ENV{'_AG_ASSERT_FILE'}; - my $assert_select= $ENV{'_AG_ASSERT_SELECT'}; - my $assert_match= $ENV{'_AG_ASSERT_MATCH'}; - my $assert_count= $ENV{'_AG_ASSERT_COUNT'}; - my $assert_only_after= $ENV{'_AG_ASSERT_ONLY_AFTER'}; - my $out= $ENV{'_AG_OUT'}; - - my $result= ''; - my $count= 0; - open(FILE, "$file") or die("Error $? opening $file: $!\n"); - while () { - my $line = $_; - if ($assert_only_after && $line =~ /$assert_only_after/) { - $result = ""; - $count = 0; - } - if ($line =~ /$assert_select/) { - if ($assert_count ne '') { - $count++; - } - else { - $result .= $line; - } - } - } - close(FILE) or die("Error $? closing $file: $!"); - open OUT, "> $out" or die("Error $? opening $out: $!"); - if ($assert_count ne '' && ($count != $assert_count)) { - print OUT ($count) or die("Error $? writing $out: $!"); - } - elsif ($assert_count eq '' && $result !~ /$assert_match/) { - print OUT ($result) or die("Error $? writing $out: $!"); - } - else { - print OUT ("assert_grep.inc ok"); - } - close OUT or die("Error $? closing $out: $!"); -EOF - - ---let $_ag_outcome= `SELECT LOAD_FILE('$_AG_OUT')` -if ($_ag_outcome != 'assert_grep.inc ok') -{ - --source include/show_rpl_debug_info.inc - --echo include/assert_grep.inc failed! - --echo assert_text: '$assert_text' - --echo assert_file: '$assert_file' - --echo assert_select: '$assert_select' - --echo assert_match: '$assert_match' - --echo assert_count: '$assert_count' - --echo assert_only_after: '$assert_only_after' - if ($assert_match != '') - { - --echo matching lines: '$_ag_outcome' - } - if ($assert_count != '') - { - --echo number of matching lines: $_ag_outcome - } - --die assert_grep.inc failed. -} - - ---let $include_filename= include/assert_grep.inc [$assert_text] ---source include/end_include_file.inc diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc index 820bc8e9016..2abfd901b03 100644 --- a/mysql-test/include/rpl_init.inc +++ b/mysql-test/include/rpl_init.inc @@ -43,7 +43,6 @@ # # [--let $rpl_server_count= 7] # --let $rpl_topology= 1->2->3->1->4, 2->5, 6->7 -# [--let $rpl_extra_connections_per_server= 1] # [--let $rpl_check_server_ids= 1] # [--let $rpl_skip_change_master= 1] # [--let $rpl_skip_start_slave= 1] @@ -66,12 +65,6 @@ # want to specify the empty topology (no server replicates at # all), you have to set $rpl_topology=none. # -# $rpl_extra_connections_per_server -# By default, this script creates connections server_N and -# server_N_1. If you can set this variable to a number, the -# script creates: -# server_N, server_N_1, ..., server_N_$rpl_extra_connections_per_server -# # $rpl_check_server_ids # If $rpl_check_server_ids is set, this script checks that the # @@server_id of all servers are different. This is normally @@ -146,17 +139,8 @@ if (!$SERVER_MYPORT_4) # Check that $rpl_server_count is set if (!$rpl_server_count) { - --let $rpl_server_count= `SELECT REPLACE('$rpl_topology', '->', ',')` - if (`SELECT LOCATE(',', '$rpl_server_count')`) - { - --let $rpl_server_count= `SELECT GREATEST($rpl_server_count)` - } -} - ---let $_rpl_extra_connections_per_server= $rpl_extra_connections_per_server -if ($_rpl_extra_connections_per_server == '') -{ - --let $_rpl_extra_connections_per_server= 1 + --let $_compute_rpl_server_count= `SELECT REPLACE('$rpl_topology', '->', ',')` + --let $rpl_server_count= `SELECT GREATEST($_compute_rpl_server_count)` } @@ -175,20 +159,15 @@ if (!$rpl_debug) # Create two connections to each server; reset master/slave, select # database, set autoinc variables. --let $_rpl_server= $rpl_server_count ---let $underscore= _ +--let $_rpl_one= _1 while ($_rpl_server) { # Connect. --let $rpl_server_number= $_rpl_server --let $rpl_connection_name= server_$_rpl_server --source include/rpl_connect.inc - --let $_rpl_connection_number= 1 - while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) - { - --let $rpl_connection_name= server_$_rpl_server$underscore$_rpl_connection_number - --source include/rpl_connect.inc - --inc $_rpl_connection_number - } + --let $rpl_connection_name= server_$_rpl_server$_rpl_one + --source include/rpl_connect.inc # Configure server. --let $rpl_connection_name= server_$_rpl_server diff --git a/mysql-test/include/rpl_reconnect.inc b/mysql-test/include/rpl_reconnect.inc index 673f382bac0..cdbbd0a1bf1 100644 --- a/mysql-test/include/rpl_reconnect.inc +++ b/mysql-test/include/rpl_reconnect.inc @@ -12,7 +12,6 @@ # ==== Usage ==== # # --let $rpl_server_number= N -# [--let $rpl_extra_connections_per_server= 1] # [--let $rpl_debug= 1] # --source include/rpl_reconnect.inc # @@ -22,7 +21,7 @@ # master server, 2 the slave server, 3 the 3rd server, and so on. # Cf. include/rpl_init.inc # -# $rpl_extra_connections_per_server, $rpl_debug +# $rpl_debug # See include/rpl_init.inc --let $include_filename= rpl_reconnect.inc @@ -33,11 +32,6 @@ if (!$rpl_server_number) --die ERROR IN TEST: you must set $rpl_server_number before you source rpl_connect.inc } -if ($_rpl_extra_connections_per_server == '') -{ - --let $_rpl_extra_connections_per_server= 1 -} - if ($rpl_debug) { @@ -78,14 +72,10 @@ if (!$_rpl_server_number) --source include/rpl_connection.inc --enable_reconnect ---let $_rpl_connection_number= 1 -while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) -{ - --let $rpl_connection_name= server_$rpl_server_number$underscore$_rpl_connection_number - --source include/rpl_connection.inc - --enable_reconnect - --inc $_rpl_connection_number -} +--let $_rpl_one= _1 +--let $rpl_connection_name= server_$rpl_server_number$_rpl_one +--source include/rpl_connection.inc +--enable_reconnect if ($rpl_debug) { @@ -132,15 +122,10 @@ if (!$_rpl_server_number) --source include/wait_until_connected_again.inc --disable_reconnect ---let $_rpl_connection_number= 1 -while ($_rpl_connection_number <= $_rpl_extra_connections_per_server) -{ - --let $rpl_connection_name= server_$rpl_server_number$underscore$_rpl_connection_number - --source include/rpl_connection.inc - --source include/wait_until_connected_again.inc - --disable_reconnect - --inc $_rpl_connection_number -} +--let $rpl_connection_name= server_$rpl_server_number$_rpl_one +--source include/rpl_connection.inc +--source include/wait_until_connected_again.inc +--disable_reconnect --let $include_filename= rpl_reconnect.inc diff --git a/mysql-test/include/start_slave_sql.inc b/mysql-test/include/start_slave_sql.inc deleted file mode 100644 index 9cb66a2eb40..00000000000 --- a/mysql-test/include/start_slave_sql.inc +++ /dev/null @@ -1,39 +0,0 @@ -# ==== Purpose ==== -# -# Issues START SLAVE SQL_THREAD on the current connection. Then waits -# until the SQL thread has started, or until a timeout is reached. -# -# Please use this instead of 'START SLAVE SQL_THREAD', to reduce the -# risk of races in test cases. -# -# -# ==== Usage ==== -# -# [--let $slave_timeout= NUMBER] -# [--let $rpl_debug= 1] -# --source include/start_slave_sql.inc -# -# Parameters: -# $slave_timeout -# See include/wait_for_slave_param.inc -# -# $rpl_debug -# See include/rpl_init.inc - - ---let $include_filename= start_slave_sql.inc ---source include/begin_include_file.inc - - -if (!$rpl_debug) -{ - --disable_query_log -} - - -START SLAVE SQL_THREAD; ---source include/wait_for_slave_sql_to_start.inc - - ---let $include_filename= start_slave_sql.inc ---source include/end_include_file.inc diff --git a/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result b/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result deleted file mode 100644 index b11ad4f53bd..00000000000 --- a/mysql-test/suite/rpl/r/rpl_io_thd_wait_for_disk_space.result +++ /dev/null @@ -1,15 +0,0 @@ -include/master-slave.inc -[connection master] -CREATE TABLE t1(a INT); -INSERT INTO t1 VALUES(1); -CALL mtr.add_suppression("Disk is full writing"); -CALL mtr.add_suppression("Retry in 60 secs"); -include/stop_slave_sql.inc -SET @@GLOBAL.DEBUG= 'd,simulate_io_thd_wait_for_disk_space'; -INSERT INTO t1 VALUES(2); -SET DEBUG_SYNC='now WAIT_FOR parked'; -SET @@GLOBAL.DEBUG= '$debug_saved'; -include/assert_grep.inc [Found the disk full error message on the slave] -include/start_slave_sql.inc -DROP TABLE t1; -include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test b/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test deleted file mode 100644 index 6076be60ebc..00000000000 --- a/mysql-test/suite/rpl/t/rpl_io_thd_wait_for_disk_space.test +++ /dev/null @@ -1,71 +0,0 @@ -# ==== Purpose ==== -# -# Check that the execution of SHOW SLAVE STATUS command is not blocked when IO -# thread is blocked waiting for disk space. -# -# ==== Implementation ==== -# -# Simulate a scenario where IO thread is waiting for disk space while writing -# into the relay log. Execute SHOW SLAVE STATUS command after IO thread is -# blocked waiting for space. The command should not be blocked. -# -# ==== References ==== -# -# Bug#21753696: MAKE SHOW SLAVE STATUS NON BLOCKING IF IO THREAD WAITS FOR -# DISK SPACE -# Bug#20685029: SLAVE IO THREAD SHOULD STOP WHEN DISK IS FULL -# -############################################################################### ---source include/have_debug.inc -# Inorder to grep a specific error pattern in error log a fresh error log -# needs to be generated. ---source include/force_restart.inc ---source include/master-slave.inc - -# Generate events to be replicated to the slave -CREATE TABLE t1(a INT); -INSERT INTO t1 VALUES(1); ---sync_slave_with_master - -# Those errors will only happen in the slave -CALL mtr.add_suppression("Disk is full writing"); -CALL mtr.add_suppression("Retry in 60 secs"); - -# Stop the SQL thread to avoid writing on disk ---source include/stop_slave_sql.inc - -# Set the debug option that will simulate disk full ---let $debug_saved= `SELECT @@GLOBAL.DEBUG` -SET @@GLOBAL.DEBUG= 'd,simulate_io_thd_wait_for_disk_space'; - -# Generate events to be replicated to the slave ---connection master -INSERT INTO t1 VALUES(2); - ---connection slave1 -SET DEBUG_SYNC='now WAIT_FOR parked'; - -# Get the relay log file name using SHOW SLAVE STATUS ---let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) - ---connection slave -# Restore the debug options to "simulate" freed space on disk -SET @@GLOBAL.DEBUG= '$debug_saved'; - -# There should be a message in the error log of the slave stating -# that it was waiting for space to write on the relay log. ---let $assert_file=$MYSQLTEST_VARDIR/log/mysqld.2.err -# Grep only after the message that the I/O thread has started ---let $assert_only_after= Slave I/O .* connected to master .*replication started in log .* at position ---let $assert_count= 1 ---let $assert_select=Disk is full writing .*$relay_log_file.* ---let $assert_text= Found the disk full error message on the slave ---source include/assert_grep.inc - -# Start the SQL thread to let the slave to sync and finish gracefully ---source include/start_slave_sql.inc - -# Cleanup ---connection master -DROP TABLE t1; ---source include/rpl_end.inc diff --git a/mysys/errors.c b/mysys/errors.c index b6064460535..a6e2e300a1f 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -15,7 +15,7 @@ #include "mysys_priv.h" #include "mysys_err.h" -#include "m_string.h" + #ifndef SHARED_LIBRARY const char *globerrs[GLOBERRS]= @@ -109,7 +109,6 @@ void init_glob_errs() */ void wait_for_free_space(const char *filename, int errors) { - size_t time_to_sleep= MY_WAIT_FOR_USER_TO_FIX_PANIC; if (!(errors % MY_WAIT_GIVE_USER_A_MESSAGE)) { my_printf_warning(EE(EE_DISK_FULL), @@ -120,15 +119,10 @@ void wait_for_free_space(const char *filename, int errors) } DBUG_EXECUTE_IF("simulate_no_free_space_error", { - time_to_sleep= 1; - }); - DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", - { - time_to_sleep= 1; + (void) sleep(1); + return; }); - - (void) sleep(time_to_sleep); - DEBUG_SYNC_C("disk_full_reached"); + (void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); } const char **get_global_errmsgs() diff --git a/mysys/my_write.c b/mysys/my_write.c index 2e68a4dcff3..f092420756e 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -24,7 +24,6 @@ size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { size_t writtenbytes, written; uint errors; - size_t ToWriteCount; DBUG_ENTER("my_write"); DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", Filedes, Buffer, (ulong) Count, MyFlags)); @@ -38,14 +37,11 @@ size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { DBUG_SET("+d,simulate_file_write_error");}); for (;;) { - ToWriteCount= Count; - DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", { ToWriteCount= 1; }); #ifdef _WIN32 - writtenbytes= my_win_write(Filedes, Buffer, ToWriteCount); + writtenbytes= my_win_write(Filedes, Buffer, Count); #else - writtenbytes= write(Filedes, Buffer, ToWriteCount); + writtenbytes= write(Filedes, Buffer, Count); #endif - DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", { errno= ENOSPC; }); DBUG_EXECUTE_IF("simulate_file_write_error", { errno= ENOSPC; diff --git a/sql/log.cc b/sql/log.cc index e0ba93b0959..50d7762af6d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -37,7 +37,6 @@ #include "log_event.h" // Query_log_event #include "rpl_filter.h" #include "rpl_rli.h" -#include "rpl_mi.h" #include "sql_audit.h" #include "sql_show.h" @@ -4378,22 +4377,13 @@ end: } -#ifdef HAVE_REPLICATION -bool MYSQL_BIN_LOG::append(Log_event* ev, Master_info *mi) +bool MYSQL_BIN_LOG::append(Log_event* ev) { bool error = 0; - mysql_mutex_assert_owner(&mi->data_lock); mysql_mutex_lock(&LOCK_log); DBUG_ENTER("MYSQL_BIN_LOG::append"); DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); - /* - Release data_lock by holding LOCK_log, while writing into the relay log. - If slave IO thread waits here for free space, we don't want - SHOW SLAVE STATUS to hang on mi->data_lock. Note LOCK_log mutex is - sufficient to block SQL thread when IO thread is updating relay log here. - */ - mysql_mutex_unlock(&mi->data_lock); /* Log_event::write() is smart enough to use my_b_write() or my_b_append() depending on the kind of cache we have. @@ -4408,58 +4398,24 @@ bool MYSQL_BIN_LOG::append(Log_event* ev, Master_info *mi) if (flush_and_sync(0)) goto err; if ((uint) my_b_append_tell(&log_file) > max_size) - { - /* - If rotation is required we must acquire data_lock to protect - description_event from clients executing FLUSH LOGS in parallel. - In order do that we must release the existing LOCK_log so that we - get it once again in proper locking order to avoid dead locks. - i.e data_lock , LOCK_log. - */ - mysql_mutex_unlock(&LOCK_log); - mysql_mutex_lock(&mi->data_lock); - mysql_mutex_lock(&LOCK_log); error= new_file_without_locking(); - /* - After rotation release data_lock, we need the LOCK_log till we signal - the updation. - */ - mysql_mutex_unlock(&mi->data_lock); - } err: - signal_update(); // Safe as we don't call close mysql_mutex_unlock(&LOCK_log); - mysql_mutex_lock(&mi->data_lock); + signal_update(); // Safe as we don't call close DBUG_RETURN(error); } -bool MYSQL_BIN_LOG::appendv(Master_info* mi, const char* buf, uint len,...) +bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...) { bool error= 0; DBUG_ENTER("MYSQL_BIN_LOG::appendv"); va_list(args); va_start(args,len); - mysql_mutex_assert_owner(&mi->data_lock); - mysql_mutex_lock(&LOCK_log); DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); - /* - Release data_lock by holding LOCK_log, while writing into the relay log. - If slave IO thread waits here for free space, we don't want - SHOW SLAVE STATUS to hang on mi->data_lock. Note LOCK_log mutex is - sufficient to block SQL thread when IO thread is updating relay log here. - */ - mysql_mutex_unlock(&mi->data_lock); - DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", - { - const char act[]= "disk_full_reached SIGNAL parked"; - DBUG_ASSERT(opt_debug_sync_timeout > 0); - DBUG_ASSERT(!debug_sync_set_action(current_thd, - STRING_WITH_LEN(act))); - };); - + mysql_mutex_assert_owner(&LOCK_log); do { if (my_b_append(&log_file,(uchar*) buf,len)) @@ -4472,34 +4428,13 @@ bool MYSQL_BIN_LOG::appendv(Master_info* mi, const char* buf, uint len,...) DBUG_PRINT("info",("max_size: %lu",max_size)); if (flush_and_sync(0)) goto err; - if ((uint) my_b_append_tell(&log_file) > - DBUG_EVALUATE_IF("rotate_slave_debug_group", 500, max_size)) - { - /* - If rotation is required we must acquire data_lock to protect - description_event from clients executing FLUSH LOGS in parallel. - In order do that we must release the existing LOCK_log so that we - get it once again in proper locking order to avoid dead locks. - i.e data_lock , LOCK_log. - */ - mysql_mutex_unlock(&LOCK_log); - mysql_mutex_lock(&mi->data_lock); - mysql_mutex_lock(&LOCK_log); + if ((uint) my_b_append_tell(&log_file) > max_size) error= new_file_without_locking(); - /* - After rotation release data_lock, we need the LOCK_log till we signal - the updation. - */ - mysql_mutex_unlock(&mi->data_lock); - } err: if (!error) signal_update(); - mysql_mutex_unlock(&LOCK_log); - mysql_mutex_lock(&mi->data_lock); DBUG_RETURN(error); } -#endif bool MYSQL_BIN_LOG::flush_and_sync(bool *synced) { diff --git a/sql/log.h b/sql/log.h index dd09cb41026..b5e751386a6 100644 --- a/sql/log.h +++ b/sql/log.h @@ -20,7 +20,6 @@ #include "handler.h" /* my_xid */ class Relay_log_info; -class Master_info; class Format_description_log_event; @@ -455,8 +454,8 @@ public: v stands for vector invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0) */ - bool appendv(Master_info* mi, const char* buf,uint len,...); - bool append(Log_event* ev, Master_info* mi); + bool appendv(const char* buf,uint len,...); + bool append(Log_event* ev); void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); diff --git a/sql/slave.cc b/sql/slave.cc index 31037c453d3..acf68e231f3 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1660,7 +1660,7 @@ Waiting for the slave SQL thread to free enough relay log space"); #endif if (rli->sql_force_rotate_relay) { - rotate_relay_log(rli->mi, true/*need_data_lock=true*/); + rotate_relay_log(rli->mi); rli->sql_force_rotate_relay= false; } @@ -1705,7 +1705,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) if (likely((bool)ev)) { ev->server_id= 0; // don't be ignored by slave SQL thread - if (unlikely(rli->relay_log.append(ev, mi))) + if (unlikely(rli->relay_log.append(ev))) mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), "failed to write a Rotate event" @@ -3605,7 +3605,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) break; Execute_load_log_event xev(thd,0,0); xev.log_pos = cev->log_pos; - if (unlikely(mi->rli.relay_log.append(&xev, mi))) + if (unlikely(mi->rli.relay_log.append(&xev))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3619,7 +3619,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) { cev->block = net->read_pos; cev->block_len = num_bytes; - if (unlikely(mi->rli.relay_log.append(cev, mi))) + if (unlikely(mi->rli.relay_log.append(cev))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3634,7 +3634,7 @@ static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) aev.block = net->read_pos; aev.block_len = num_bytes; aev.log_pos = cev->log_pos; - if (unlikely(mi->rli.relay_log.append(&aev, mi))) + if (unlikely(mi->rli.relay_log.append(&aev))) { mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE), @@ -3713,7 +3713,7 @@ static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) Rotate the relay log makes binlog format detection easier (at next slave start or mysqlbinlog) */ - DBUG_RETURN(rotate_relay_log(mi, false/*need_data_lock=false*/)); + DBUG_RETURN(rotate_relay_log(mi) /* will take the right mutexes */); } /* @@ -3819,7 +3819,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, Log_event::Log_event(const char* buf...) in log_event.cc). */ ev->log_pos+= event_len; /* make log_pos be the pos of the end of the event */ - if (unlikely(rli->relay_log.append(ev, mi))) + if (unlikely(rli->relay_log.append(ev))) { delete ev; mysql_mutex_unlock(&mi->data_lock); @@ -3875,7 +3875,7 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, inc_pos= event_len; break; } - if (unlikely(rli->relay_log.append(ev, mi))) + if (unlikely(rli->relay_log.append(ev))) { delete ev; mysql_mutex_unlock(&mi->data_lock); @@ -4083,6 +4083,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) direct master (an unsupported, useless setup!). */ + mysql_mutex_lock(log_lock); s_id= uint4korr(buf + SERVER_ID_OFFSET); if ((s_id == ::server_id && !mi->rli.replicate_same_server_id) || /* @@ -4115,7 +4116,6 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) IGNORE_SERVER_IDS it increments mi->master_log_pos as well as rli->group_relay_log_pos. */ - mysql_mutex_lock(log_lock); if (!(s_id == ::server_id && !mi->rli.replicate_same_server_id) || (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT && @@ -4127,14 +4127,13 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) rli->ign_master_log_pos_end= mi->master_log_pos; } rli->relay_log.signal_update(); // the slave SQL thread needs to re-check - mysql_mutex_unlock(log_lock); DBUG_PRINT("info", ("master_log_pos: %lu, event originating from %u server, ignored", (ulong) mi->master_log_pos, uint4korr(buf + SERVER_ID_OFFSET))); } else { /* write the event to the relay log */ - if (likely(!(rli->relay_log.appendv(mi, buf,event_len,0)))) + if (likely(!(rli->relay_log.appendv(buf,event_len,0)))) { mi->master_log_pos+= inc_pos; DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); @@ -4144,10 +4143,9 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) { error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE; } - mysql_mutex_lock(log_lock); rli->ign_master_log_name_end[0]= 0; // last event is not ignored - mysql_mutex_unlock(log_lock); } + mysql_mutex_unlock(log_lock); skip_relay_logging: @@ -5007,21 +5005,11 @@ err: locks; here we don't, so this function is mainly taking locks). Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file() is void). - - @param mi Master_info for the IO thread. - @param need_data_lock If true, mi->data_lock will be acquired otherwise, - mi->data_lock must be held by the caller. */ -int rotate_relay_log(Master_info* mi, bool need_data_lock) +int rotate_relay_log(Master_info* mi) { DBUG_ENTER("rotate_relay_log"); - if (need_data_lock) - mysql_mutex_lock(&mi->data_lock); - else - { - mysql_mutex_assert_owner(&mi->data_lock); - } Relay_log_info* rli= &mi->rli; int error= 0; @@ -5056,8 +5044,6 @@ int rotate_relay_log(Master_info* mi, bool need_data_lock) */ rli->relay_log.harvest_bytes_written(&rli->log_space_total); end: - if (need_data_lock) - mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); } diff --git a/sql/slave.h b/sql/slave.h index 0cf8adb0315..7bf136694cc 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -205,7 +205,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, const char** errmsg); void set_slave_thread_options(THD* thd); void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli); -int rotate_relay_log(Master_info* mi, bool need_data_lock); +int rotate_relay_log(Master_info* mi); int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli); pthread_handler_t handle_slave_io(void *arg); diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index f24f31b6399..b29cc9a9433 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -157,7 +157,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, { #ifdef HAVE_REPLICATION mysql_mutex_lock(&LOCK_active_mi); - if (rotate_relay_log(active_mi, true/*need_data_lock=true*/)) + if (rotate_relay_log(active_mi)) *write_to_binlog= -1; mysql_mutex_unlock(&LOCK_active_mi); #endif -- cgit v1.2.1 From cb2974156823977fd2c700c64ff0867183b3f744 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Mon, 16 May 2016 13:46:49 +0530 Subject: Bug#21977380 - POSSIBLE BUFFER OVERFLOW ISSUES DESCRIPTION =========== Buffer overflow is reported in a lot of code sections spanning across server, client programs, Regex libraries etc. If not handled appropriately, they can cause abnormal behaviour. ANALYSIS ======== The reported casea are the ones which are likely to result in SEGFAULT, MEMORY LEAK etc. FIX === - sprintf() has been replaced by my_snprintf() to avoid buffer overflow. - my_free() is done after checking if the pointer isn't NULL already and setting it to NULL thereafter at few places. - Buffer is ensured to be large enough to hold the data. - 'unsigned int' (aka 'uint') is replaced with 'size_t' to avoid wraparound. - Memory is freed (if not done so) after its alloced and used. - Inserted assert() for size check in InnoDb memcached code (from 5.6 onwards) - Other minor changes --- client/mysqlcheck.c | 42 ++++++++++++++++++++++++++---------------- client/mysqldump.c | 49 +++++++++++++++++++++++++++---------------------- client/mysqlshow.c | 36 +++++++++++++++++++----------------- extra/yassl/src/log.cpp | 4 ++-- regex/split.c | 4 ++++ 5 files changed, 78 insertions(+), 57 deletions(-) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index a564e871281..55b941e7f1a 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -213,13 +213,13 @@ static int process_selected_tables(char *db, char **table_names, int tables); static int process_all_tables_in_db(char *database); static int process_one_db(char *database); static int use_db(char *database); -static int handle_request_for_tables(char *tables, uint length); +static int handle_request_for_tables(char *tables, size_t length); static int dbConnect(char *host, char *user,char *passwd); static void dbDisconnect(char *host); static void DBerror(MYSQL *mysql, const char *when); static void safe_exit(int error); static void print_result(); -static uint fixed_name_length(const char *name); +static size_t fixed_name_length(const char *name); static char *fix_table_name(char *dest, char *src); int what_to_do = 0; @@ -486,7 +486,7 @@ static int process_selected_tables(char *db, char **table_names, int tables) *end++= ','; } *--end = 0; - handle_request_for_tables(table_names_comma_sep + 1, (uint) (tot_length - 1)); + handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1); my_free(table_names_comma_sep); } else @@ -496,10 +496,10 @@ static int process_selected_tables(char *db, char **table_names, int tables) } /* process_selected_tables */ -static uint fixed_name_length(const char *name) +static size_t fixed_name_length(const char *name) { const char *p; - uint extra_length= 2; /* count the first/last backticks */ + size_t extra_length= 2; /* count the first/last backticks */ for (p= name; *p; p++) { @@ -508,7 +508,7 @@ static uint fixed_name_length(const char *name) else if (*p == '.') extra_length+= 2; } - return (uint) ((p - name) + extra_length); + return (size_t) ((p - name) + extra_length); } @@ -564,7 +564,7 @@ static int process_all_tables_in_db(char *database) */ char *tables, *end; - uint tot_length = 0; + size_t tot_length = 0; while ((row = mysql_fetch_row(res))) tot_length+= fixed_name_length(row[0]) + 2; @@ -622,7 +622,9 @@ static int fix_table_storage_name(const char *name) int rc= 0; if (strncmp(name, "#mysql50#", 9)) return 1; - sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9); + my_snprintf(qbuf, sizeof(qbuf), "RENAME TABLE `%s` TO `%s`", + name, name + 9); + rc= run_query(qbuf); if (verbose) printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); @@ -635,7 +637,8 @@ static int fix_database_storage_name(const char *name) int rc= 0; if (strncmp(name, "#mysql50#", 9)) return 1; - sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name); + my_snprintf(qbuf, sizeof(qbuf), "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY " + "NAME", name); rc= run_query(qbuf); if (verbose) printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); @@ -653,7 +656,7 @@ static int rebuild_table(char *name) ptr= strmov(query, "ALTER TABLE "); ptr= fix_table_name(ptr, name); ptr= strxmov(ptr, " FORCE", NullS); - if (mysql_real_query(sock, query, (uint)(ptr - query))) + if (mysql_real_query(sock, query, (ulong)(ptr - query))) { fprintf(stderr, "Failed to %s\n", query); fprintf(stderr, "Error: %s\n", mysql_error(sock)); @@ -702,10 +705,10 @@ static int disable_binlog() return run_query(stmt); } -static int handle_request_for_tables(char *tables, uint length) +static int handle_request_for_tables(char *tables, size_t length) { char *query, *end, options[100], message[100]; - uint query_length= 0; + size_t query_length= 0, query_size= sizeof(char)*(length+110); const char *op = 0; options[0] = 0; @@ -736,10 +739,14 @@ static int handle_request_for_tables(char *tables, uint length) return fix_table_storage_name(tables); } - if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME)))) + if (!(query =(char *) my_malloc(query_size, MYF(MY_WME)))) + { return 1; + } if (opt_all_in_1) { + DBUG_ASSERT(strlen(op)+strlen(tables)+strlen(options)+8+1 <= query_size); + /* No backticks here as we added them before */ query_length= sprintf(query, "%s TABLE %s %s", op, tables, options); } @@ -750,7 +757,7 @@ static int handle_request_for_tables(char *tables, uint length) ptr= strmov(strmov(query, op), " TABLE "); ptr= fix_table_name(ptr, tables); ptr= strxmov(ptr, " ", options, NullS); - query_length= (uint) (ptr - query); + query_length= (size_t) (ptr - query); } if (mysql_real_query(sock, query, query_length)) { @@ -834,7 +841,10 @@ static void print_result() prev_alter[0]= 0; } else - strcpy(prev_alter, alter_txt); + { + strncpy(prev_alter, alter_txt, MAX_ALTER_STR_SIZE-1); + prev_alter[MAX_ALTER_STR_SIZE-1]= 0; + } } } } @@ -978,7 +988,7 @@ int main(int argc, char **argv) process_databases(argv); if (opt_auto_repair) { - uint i; + size_t i; if (!opt_silent && (tables4repair.elements || tables4rebuild.elements)) puts("\nRepairing tables"); diff --git a/client/mysqldump.c b/client/mysqldump.c index 6c4fec313c5..00265def489 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -86,7 +86,7 @@ static void add_load_option(DYNAMIC_STRING *str, const char *option, const char *option_value); -static ulong find_set(TYPELIB *lib, const char *x, uint length, +static ulong find_set(TYPELIB *lib, const char *x, size_t length, char **err_pos, uint *err_len); static char *alloc_query_str(ulong size); @@ -852,7 +852,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_set_charset= 0; opt_compatible_mode_str= argument; opt_compatible_mode= find_set(&compatible_mode_typelib, - argument, (uint) strlen(argument), + argument, strlen(argument), &err_ptr, &err_len); if (err_len) { @@ -862,7 +862,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } #if !defined(DBUG_OFF) { - uint size_for_sql_mode= 0; + size_t size_for_sql_mode= 0; const char **ptr; for (ptr= compatible_mode_names; *ptr; ptr++) size_for_sql_mode+= strlen(*ptr); @@ -1138,8 +1138,8 @@ static int fetch_db_collation(const char *db_name, break; } - strncpy(db_cl_name, db_cl_row[0], db_cl_size); - db_cl_name[db_cl_size - 1]= 0; /* just in case. */ + strncpy(db_cl_name, db_cl_row[0], db_cl_size-1); + db_cl_name[db_cl_size - 1]= 0; } while (FALSE); @@ -1150,7 +1150,7 @@ static int fetch_db_collation(const char *db_name, static char *my_case_str(const char *str, - uint str_len, + size_t str_len, const char *token, uint token_len) { @@ -1366,7 +1366,7 @@ static int switch_character_set_results(MYSQL *mysql, const char *cs_name) */ static char *cover_definer_clause(const char *stmt_str, - uint stmt_length, + size_t stmt_length, const char *definer_version_str, uint definer_version_length, const char *stmt_version_str, @@ -1548,14 +1548,14 @@ static void dbDisconnect(char *host) } /* dbDisconnect */ -static void unescape(FILE *file,char *pos,uint length) +static void unescape(FILE *file,char *pos, size_t length) { char *tmp; DBUG_ENTER("unescape"); if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME)))) die(EX_MYSQLERR, "Couldn't allocate memory"); - mysql_real_escape_string(&mysql_connection, tmp, pos, length); + mysql_real_escape_string(&mysql_connection, tmp, pos, (ulong)length); fputc('\'', file); fputs(tmp, file); fputc('\'', file); @@ -1669,7 +1669,7 @@ static char *quote_for_like(const char *name, char *buff) Quote '<' '>' '&' '\"' chars and print a string to the xml_file. */ -static void print_quoted_xml(FILE *xml_file, const char *str, ulong len, +static void print_quoted_xml(FILE *xml_file, const char *str, size_t len, my_bool is_attribute_name) { const char *end; @@ -1928,7 +1928,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name, squeezed to a single hyphen. */ -static void print_xml_comment(FILE *xml_file, ulong len, +static void print_xml_comment(FILE *xml_file, size_t len, const char *comment_string) { const char* end; @@ -2045,7 +2045,7 @@ static uint dump_events_for_db(char *db) DBUG_ENTER("dump_events_for_db"); DBUG_PRINT("enter", ("db: '%s'", db)); - mysql_real_escape_string(mysql, db_name_buff, db, strlen(db)); + mysql_real_escape_string(mysql, db_name_buff, db, (ulong)strlen(db)); /* nice comments */ print_comment(sql_file, 0, @@ -2164,6 +2164,11 @@ static uint dump_events_for_db(char *db) (const char *) (query_str != NULL ? query_str : row[3]), (const char *) delimiter); + if(query_str) + { + my_free(query_str); + query_str= NULL; + } restore_time_zone(sql_file, delimiter); restore_sql_mode(sql_file, delimiter); @@ -2257,7 +2262,7 @@ static uint dump_routines_for_db(char *db) DBUG_ENTER("dump_routines_for_db"); DBUG_PRINT("enter", ("db: '%s'", db)); - mysql_real_escape_string(mysql, db_name_buff, db, strlen(db)); + mysql_real_escape_string(mysql, db_name_buff, db, (ulong)strlen(db)); /* nice comments */ print_comment(sql_file, 0, @@ -2311,9 +2316,9 @@ static uint dump_routines_for_db(char *db) if the user has EXECUTE privilege he see routine names, but NOT the routine body of other routines that are not the creator of! */ - DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d", + DBUG_PRINT("info",("length of body for %s row[2] '%s' is %zu", routine_name, row[2] ? row[2] : "(null)", - row[2] ? (int) strlen(row[2]) : 0)); + row[2] ? strlen(row[2]) : 0)); if (row[2] == NULL) { print_comment(sql_file, 1, "\n-- insufficient privileges to %s\n", @@ -3873,7 +3878,7 @@ static int dump_tablespaces_for_tables(char *db, char **table_names, int tables) int i; char name_buff[NAME_LEN*2+3]; - mysql_real_escape_string(mysql, name_buff, db, strlen(db)); + mysql_real_escape_string(mysql, name_buff, db, (ulong)strlen(db)); init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN (" "SELECT DISTINCT TABLESPACE_NAME FROM" @@ -3886,7 +3891,7 @@ static int dump_tablespaces_for_tables(char *db, char **table_names, int tables) for (i=0 ; imax_length) length=field->max_length; @@ -500,7 +501,8 @@ static int list_tables(MYSQL *mysql,const char *db,const char *table) { const char *header; - uint head_length, counter = 0; + size_t head_length; + uint counter = 0; char query[NAME_LEN + 100], rows[NAME_LEN], fields[16]; MYSQL_FIELD *field; MYSQL_RES *result; @@ -537,7 +539,7 @@ list_tables(MYSQL *mysql,const char *db,const char *table) putchar('\n'); header="Tables"; - head_length=(uint) strlen(header); + head_length= strlen(header); field=mysql_fetch_field(result); if (head_length < field->max_length) head_length=field->max_length; @@ -766,10 +768,10 @@ list_fields(MYSQL *mysql,const char *db,const char *table, *****************************************************************************/ static void -print_header(const char *header,uint head_length,...) +print_header(const char *header,size_t head_length,...) { va_list args; - uint length,i,str_length,pre_space; + size_t length,i,str_length,pre_space; const char *field; va_start(args,head_length); @@ -792,10 +794,10 @@ print_header(const char *header,uint head_length,...) putchar('|'); for (;;) { - str_length=(uint) strlen(field); + str_length= strlen(field); if (str_length > length) str_length=length+1; - pre_space=(uint) (((int) length-(int) str_length)/2)+1; + pre_space= ((length- str_length)/2)+1; for (i=0 ; i < pre_space ; i++) putchar(' '); for (i = 0 ; i < str_length ; i++) @@ -829,11 +831,11 @@ print_header(const char *header,uint head_length,...) static void -print_row(const char *header,uint head_length,...) +print_row(const char *header,size_t head_length,...) { va_list args; const char *field; - uint i,length,field_length; + size_t i,length,field_length; va_start(args,head_length); field=header; length=head_length; @@ -842,7 +844,7 @@ print_row(const char *header,uint head_length,...) putchar('|'); putchar(' '); fputs(field,stdout); - field_length=(uint) strlen(field); + field_length= strlen(field); for (i=field_length ; i <= length ; i++) putchar(' '); if (!(field=va_arg(args,char *))) @@ -856,10 +858,10 @@ print_row(const char *header,uint head_length,...) static void -print_trailer(uint head_length,...) +print_trailer(size_t head_length,...) { va_list args; - uint length,i; + size_t length,i; va_start(args,head_length); length=head_length; @@ -902,7 +904,7 @@ static void print_res_top(MYSQL_RES *result) mysql_field_seek(result,0); while((field = mysql_fetch_field(result))) { - if ((length=(uint) strlen(field->name)) > field->max_length) + if ((length= strlen(field->name)) > field->max_length) field->max_length=length; else length=field->max_length; diff --git a/extra/yassl/src/log.cpp b/extra/yassl/src/log.cpp index 13c68295747..2f112ac35f9 100644 --- a/extra/yassl/src/log.cpp +++ b/extra/yassl/src/log.cpp @@ -1,6 +1,5 @@ /* - Copyright (C) 2000-2007 MySQL AB - Use is subject to license terms + Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 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 @@ -61,6 +60,7 @@ namespace yaSSL { time_t clicks = time(0); char timeStr[32]; + memset(timeStr, 0, sizeof(timeStr)); // get rid of newline strncpy(timeStr, ctime(&clicks), sizeof(timeStr)); unsigned int len = strlen(timeStr); diff --git a/regex/split.c b/regex/split.c index bd2a53c01e3..a3a11f793ed 100644 --- a/regex/split.c +++ b/regex/split.c @@ -163,6 +163,10 @@ char *argv[]; } else if (argc > 3) for (n = atoi(argv[3]); n > 0; n--) { + if(sizeof(buf)-1 < strlen(argv[1])) + { + exit(EXIT_FAILURE); + } (void) strcpy(buf, argv[1]); (void) split(buf, fields, MNF, argv[2]); } -- cgit v1.2.1 From 90b9c957ba6380a717aaef6285b3f1498f4a29dc Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Wed, 18 May 2016 11:07:29 +0530 Subject: BUG#21142859: FUNCTION UPDATING A VIEW FAILS TO FIND TABLE THAT ACTUALLY EXISTS ANALYSIS: ========= Stored functions updating a view where the view table has a trigger defined that updates another table, fails reporting an error that the table doesn't exist. If there is a trigger defined on a table, a variable 'trg_event_map' will be set to a non-zero value after the parsed tree creation. This indicates what triggers we need to pre-load for the TABLE_LIST when opening an associated table. During the prelocking phase, the variable 'trg_event_map' will not be set for the view table. This value will be set after the processing of triggers defined on the table. During the processing of sub-statements, 'locked_tables_mode' will be set to 'LTM_PRELOCKED' which denotes that further locking of tables/functions cannot be done. This results in the other table not being locked and thus further processing results in an error getting reported. FIX: ==== During the prelocking of view, the value of 'trg_event_map' of the view is copied to 'trg_event_map' of the next table in the TABLE_LIST. This results in the locking of tables associated with the trigger as well. --- mysql-test/r/sp-prelocking.result | 20 ++++++++++++++++++++ mysql-test/t/sp-prelocking.test | 26 ++++++++++++++++++++++++++ sql/sql_base.cc | 11 ++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result index 186b2c05d34..ac48459b0f2 100644 --- a/mysql-test/r/sp-prelocking.result +++ b/mysql-test/r/sp-prelocking.result @@ -320,3 +320,23 @@ c2 DROP TRIGGER t1_ai; DROP TABLE t1, t2; End of 5.0 tests +# +# Bug#21142859: FUNCTION UPDATING A VIEW FAILS TO FIND TABLE THAT ACTUALLY EXISTS +# +CREATE TABLE t1 SELECT 1 AS fld1, 'A' AS fld2; +CREATE TABLE t2 (fld3 INT, fld4 CHAR(1)); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TRIGGER t1_au AFTER UPDATE ON t1 +FOR EACH ROW INSERT INTO t2 VALUES (new.fld1, new.fld2); +CREATE FUNCTION f1() RETURNS INT +BEGIN +UPDATE v1 SET fld2='B' WHERE fld1=1; +RETURN row_count(); +END ! +# Without the patch, an error was getting reported. +SELECT f1(); +f1() +1 +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test index 966c59a5789..c1378d59196 100644 --- a/mysql-test/t/sp-prelocking.test +++ b/mysql-test/t/sp-prelocking.test @@ -388,3 +388,29 @@ DROP TABLE t1, t2; --echo End of 5.0 tests +--echo # +--echo # Bug#21142859: FUNCTION UPDATING A VIEW FAILS TO FIND TABLE THAT ACTUALLY EXISTS +--echo # + +CREATE TABLE t1 SELECT 1 AS fld1, 'A' AS fld2; +CREATE TABLE t2 (fld3 INT, fld4 CHAR(1)); + +CREATE VIEW v1 AS SELECT * FROM t1; + +CREATE TRIGGER t1_au AFTER UPDATE ON t1 +FOR EACH ROW INSERT INTO t2 VALUES (new.fld1, new.fld2); + +DELIMITER !; +CREATE FUNCTION f1() RETURNS INT +BEGIN + UPDATE v1 SET fld2='B' WHERE fld1=1; + RETURN row_count(); +END ! +DELIMITER ;! + +--echo # Without the patch, an error was getting reported. +SELECT f1(); + +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f559974c86b..27dcbee7b8f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 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 @@ -5211,6 +5211,15 @@ handle_view(THD *thd, Query_tables_list *prelocking_ctx, &table_list->view->sroutines_list, table_list->top_table()); } + + /* + If a trigger was defined on one of the associated tables then assign the + 'trg_event_map' value of the view to the next table in table_list. When a + Stored function is invoked, all the associated tables including the tables + associated with the trigger are prelocked. + */ + if (table_list->trg_event_map && table_list->next_global) + table_list->next_global->trg_event_map= table_list->trg_event_map; return FALSE; } -- cgit v1.2.1 From 8281068f72385fb559906ca14f29bd3871b8830d Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Wed, 18 May 2016 17:23:16 +0530 Subject: BUG#21879694 - /VAR/LOG/MYSQLD.LOG HAS INCORRECT PERMISSIONS AFTER INSTALLING SERVER FROM REPO Description: This issue doesn't effect any default installation of repo rpms if user uses init scripts that are shipped as part of package but will have trouble if user tries to createdb or start server manually. After installing mysql-server from repository(yum,zypper) /var/log/mysqld.log is created with logged in user and group permissions instead of with mysql user and group permissions,due to which while creating database or starting server, it is failing Fix: Updated the user and group permissions of the /var/log/mysqld.log and /var/log/mysql/mysqld.log (for sles) files to mysql. --- packaging/rpm-oel/mysql.spec.in | 3 ++- packaging/rpm-sles/mysql.spec.in | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packaging/rpm-oel/mysql.spec.in b/packaging/rpm-oel/mysql.spec.in index 8a020b05ae6..8f92f5b84f3 100644 --- a/packaging/rpm-oel/mysql.spec.in +++ b/packaging/rpm-oel/mysql.spec.in @@ -1,4 +1,4 @@ -# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. # # 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 @@ -629,6 +629,7 @@ rm -r $(readlink var) var datadir=$(/usr/bin/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p' | tail -n 1) /bin/chmod 0755 "$datadir" /bin/touch /var/log/mysqld.log +/bin/chown mysql:mysql /var/log/mysqld.log >/dev/null 2>&1 || : %if 0%{?systemd} %systemd_post mysqld.service /sbin/service mysqld enable >/dev/null 2>&1 || : diff --git a/packaging/rpm-sles/mysql.spec.in b/packaging/rpm-sles/mysql.spec.in index 91c708a583d..47c40b00e23 100644 --- a/packaging/rpm-sles/mysql.spec.in +++ b/packaging/rpm-sles/mysql.spec.in @@ -1,4 +1,4 @@ -# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. # # 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 @@ -492,6 +492,7 @@ rm -r $(readlink var) var datadir=$(/usr/bin/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p' | tail -n 1) /bin/chmod 0755 "$datadir" /bin/touch /var/log/mysql/mysqld.log +/bin/chown mysql:mysql /var/log/mysql/mysqld.log >/dev/null 2>&1 || : %if 0%{?systemd} %systemd_post mysqld.service /sbin/service mysqld enable >/dev/null 2>&1 || : -- cgit v1.2.1 From 4de9d9c261a6f2a32e98920bbc530c473b41de07 Mon Sep 17 00:00:00 2001 From: Terje Rosten Date: Fri, 20 May 2016 11:33:18 +0200 Subject: BUG#20693338 CONFLICTS WHILE INSTALLING PACKAGES WHEN LIBMYSQLCLIENT-DEVEL INSTALLED Remove mysql_config from client package to avoid conflict (file shipped in devel package any way). --- packaging/rpm-sles/mysql.spec.in | 1 - 1 file changed, 1 deletion(-) diff --git a/packaging/rpm-sles/mysql.spec.in b/packaging/rpm-sles/mysql.spec.in index 47c40b00e23..38201428fda 100644 --- a/packaging/rpm-sles/mysql.spec.in +++ b/packaging/rpm-sles/mysql.spec.in @@ -683,7 +683,6 @@ fi %attr(755, root, root) %{_bindir}/mysqlimport %attr(755, root, root) %{_bindir}/mysqlshow %attr(755, root, root) %{_bindir}/mysqlslap -%attr(755, root, root) %{_bindir}/mysql_config %attr(644, root, root) %{_mandir}/man1/msql2mysql.1* %attr(644, root, root) %{_mandir}/man1/mysql.1* -- cgit v1.2.1 From 115f08284df1dac6a29cbca49dc7534b4a4f23f7 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Tue, 24 May 2016 07:44:21 +0530 Subject: Bug #23279858: MYSQLD GOT SIGNAL 11 ON SIMPLE SELECT NAME_CONST QUERY ISSUE: ------ Using NAME_CONST with a non-constant negated expression as value can result in incorrect behavior. SOLUTION: --------- The problem can be avoided by checking whether the argument is a constant value. The fix is a backport of Bug#12735545. --- mysql-test/r/func_misc.result | 7 +++++++ mysql-test/t/func_misc.test | 10 ++++++++++ sql/item.cc | 9 +++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index c9552d9e39f..de46f070065 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -403,3 +403,10 @@ DROP TABLE t1; # # End of tests # +SELECT NAME_CONST('a', -(1 OR 2)) OR 1; +ERROR HY000: Incorrect arguments to NAME_CONST +SELECT NAME_CONST('a', -(1 AND 2)) OR 1; +ERROR HY000: Incorrect arguments to NAME_CONST +SELECT NAME_CONST('a', -(1)) OR 1; +NAME_CONST('a', -(1)) OR 1 +1 diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 9257314013d..c13b506ad6f 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -544,3 +544,13 @@ DROP TABLE t1; --echo # --echo # End of tests --echo # + +# +# Bug#12735545 - PARSER STACK OVERFLOW WITH NAME_CONST +# CONTAINING OR EXPRESSION +# +--error ER_WRONG_ARGUMENTS +SELECT NAME_CONST('a', -(1 OR 2)) OR 1; +--error ER_WRONG_ARGUMENTS +SELECT NAME_CONST('a', -(1 AND 2)) OR 1; +SELECT NAME_CONST('a', -(1)) OR 1; diff --git a/sql/item.cc b/sql/item.cc index f4917448dda..1541314ec97 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1358,6 +1358,11 @@ bool Item_name_const::is_null() Item_name_const::Item_name_const(Item *name_arg, Item *val): value_item(val), name_item(name_arg) { + /* + The value argument to NAME_CONST can only be a literal constant. Some extra + tests are needed to support a collation specificer and to handle negative + values. + */ if (!(valid_args= name_item->basic_const_item() && (value_item->basic_const_item() || ((value_item->type() == FUNC_ITEM) && @@ -1365,8 +1370,8 @@ Item_name_const::Item_name_const(Item *name_arg, Item *val): Item_func::COLLATE_FUNC) || ((((Item_func *) value_item)->functype() == Item_func::NEG_FUNC) && - (((Item_func *) value_item)->key_item()->type() != - FUNC_ITEM))))))) + (((Item_func *) + value_item)->key_item()->basic_const_item()))))))) my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); Item::maybe_null= TRUE; } -- cgit v1.2.1 From 5dc6a77b409291140e072470673589982a6623a2 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Mon, 30 May 2016 15:20:08 +0530 Subject: Bug#23035296: MAIN.MYSQLDUMP FAILS BECUASE OF UNEXPECTED ERROR MESSAGE Description:- Mtr test, "main.mysqldump" is failing with an assert when "mysqlimport" client utility is executed with the option "--use_threads". Analysis:- "mysqlimport" uses the option, "--use_threads", to spawn worker threads to complete its job in parallel. But currently the main thread is not waiting for the worker threads to complete its cleanup, rather just wait for the worker threads to say its done doing its job. So the cleanup is done in a race between the worker threads and the main thread. This lead to an assertion failure. Fix:- "my_thread_join()" is introduced in the main thread to join all the worker threads it have spawned. This will let the main thread to wait for all the worker threads to complete its cleanup before calling "my_end()". --- client/mysqlimport.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 416159abd81..3e8f694d96d 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -592,7 +592,7 @@ error: pthread_cond_signal(&count_threshhold); pthread_mutex_unlock(&counter_mutex); mysql_thread_end(); - + pthread_exit(0); return 0; } @@ -615,15 +615,30 @@ int main(int argc, char **argv) if (opt_use_threads && !lock_tables) { - pthread_t mainthread; /* Thread descriptor */ - pthread_attr_t attr; /* Thread attributes */ + char **save_argv; + uint worker_thread_count= 0, table_count= 0, i= 0; + pthread_t *worker_threads; /* Thread descriptor */ + pthread_attr_t attr; /* Thread attributes */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, - PTHREAD_CREATE_DETACHED); + PTHREAD_CREATE_JOINABLE); pthread_mutex_init(&counter_mutex, NULL); pthread_cond_init(&count_threshhold, NULL); + /* Count the number of tables. This number denotes the total number + of threads spawn. + */ + save_argv= argv; + for (table_count= 0; *argv != NULL; argv++) + table_count++; + argv= save_argv; + + if (!(worker_threads= (pthread_t*) my_malloc(table_count * + sizeof(*worker_threads), + MYF(0)))) + return -2; + for (counter= 0; *argv != NULL; argv++) /* Loop through tables */ { pthread_mutex_lock(&counter_mutex); @@ -638,15 +653,16 @@ int main(int argc, char **argv) counter++; pthread_mutex_unlock(&counter_mutex); /* now create the thread */ - if (pthread_create(&mainthread, &attr, worker_thread, - (void *)*argv) != 0) + if (pthread_create(&worker_threads[worker_thread_count], &attr, + worker_thread, (void *)*argv) != 0) { pthread_mutex_lock(&counter_mutex); counter--; pthread_mutex_unlock(&counter_mutex); - fprintf(stderr,"%s: Could not create thread\n", - my_progname); + fprintf(stderr,"%s: Could not create thread\n", my_progname); + continue; } + worker_thread_count++; } /* @@ -664,6 +680,14 @@ int main(int argc, char **argv) pthread_mutex_destroy(&counter_mutex); pthread_cond_destroy(&count_threshhold); pthread_attr_destroy(&attr); + + for(i= 0; i < worker_thread_count; i++) + { + if (pthread_join(worker_threads[i], NULL)) + fprintf(stderr,"%s: Could not join worker thread.\n", my_progname); + } + + my_free(worker_threads); } else { -- cgit v1.2.1 From 96d90250c66d9159522582a541c87e3c9d8b8d08 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Thu, 2 Jun 2016 15:02:46 +0530 Subject: Bug#23035296: MAIN.MYSQLDUMP FAILS BECUASE OF UNEXPECTED ERROR MESSAGE Post push patch to fix test case failure. --- client/mysqlimport.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 3e8f694d96d..81eb5a37fde 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -30,6 +30,7 @@ /* Global Thread counter */ uint counter; +pthread_mutex_t init_mutex; pthread_mutex_t counter_mutex; pthread_cond_t count_threshhold; @@ -417,8 +418,13 @@ static MYSQL *db_connect(char *host, char *database, MYSQL *mysql; if (verbose) fprintf(stdout, "Connecting to %s\n", host ? host : "localhost"); + pthread_mutex_lock(&init_mutex); if (!(mysql= mysql_init(NULL))) + { + pthread_mutex_unlock(&init_mutex); return 0; + } + pthread_mutex_unlock(&init_mutex); if (opt_compress) mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS); if (opt_local_file) @@ -623,6 +629,7 @@ int main(int argc, char **argv) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_mutex_init(&init_mutex, NULL); pthread_mutex_init(&counter_mutex, NULL); pthread_cond_init(&count_threshhold, NULL); @@ -677,6 +684,7 @@ int main(int argc, char **argv) pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime); } pthread_mutex_unlock(&counter_mutex); + pthread_mutex_destroy(&init_mutex); pthread_mutex_destroy(&counter_mutex); pthread_cond_destroy(&count_threshhold); pthread_attr_destroy(&attr); -- cgit v1.2.1 From df0d8efaf25a69990cf422d55011c1c0eebdec51 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Fri, 3 Jun 2016 12:50:23 +0530 Subject: Bug#23035296: MAIN.MYSQLDUMP FAILS BECUASE OF UNEXPECTED ERROR MESSAGE Post push patch to fix test case failure. --- client/mysqlimport.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 81eb5a37fde..5841c0b855a 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -418,13 +418,19 @@ static MYSQL *db_connect(char *host, char *database, MYSQL *mysql; if (verbose) fprintf(stdout, "Connecting to %s\n", host ? host : "localhost"); - pthread_mutex_lock(&init_mutex); - if (!(mysql= mysql_init(NULL))) + if (opt_use_threads && !lock_tables) { + pthread_mutex_lock(&init_mutex); + if (!(mysql= mysql_init(NULL))) + { + pthread_mutex_unlock(&init_mutex); + return 0; + } pthread_mutex_unlock(&init_mutex); - return 0; } - pthread_mutex_unlock(&init_mutex); + else + if (!(mysql= mysql_init(NULL))) + return 0; if (opt_compress) mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS); if (opt_local_file) -- cgit v1.2.1 From 957aefdc8f5523a1d45775f5ce3de74c03f5ed98 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Fri, 17 Jun 2016 10:11:33 +0530 Subject: Bug#23498283 - BUFFER OVERFLOW DESCRIPTION =========== Buffer overflow is reported in Regex library. This can be triggered when the data corresponding to argv[1] is >= 512 bytes resutling in abnormal behaviour. ANALYSIS ======== Its a straight forward case of SEGFAULT where the target buffer is smaller than the source string to be copied. A simple pre-copy validation should do. FIX === A check is added before doing strcpy() to ensure that the target buffer is big enough to hold the to-be copied data. If the check fails, the program aborts. --- regex/split.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/regex/split.c b/regex/split.c index a3a11f793ed..abae74eba9c 100644 --- a/regex/split.c +++ b/regex/split.c @@ -159,6 +159,10 @@ char *argv[]; if (argc > 4) for (n = atoi(argv[3]); n > 0; n--) { + if(sizeof(buf)-1 < strlen(argv[1])) + { + exit(EXIT_FAILURE); + } (void) strcpy(buf, argv[1]); } else if (argc > 3) -- cgit v1.2.1 From 4a3f1c1f104cbfeb6d31ee02788589151b131eca Mon Sep 17 00:00:00 2001 From: Terje Rosten Date: Thu, 19 May 2016 15:58:35 +0200 Subject: BUG#17903583 MYSQL-COMMUNITY-SERVER SHOULD NOT DEPEND ON MYSQL-COMMUNITY-CLIENT (#70985) Fix is a backport of BUG#18518216/72230 to MySQL 5.5 and 5.6. Will also resolve: BUG#23605713/81384 LIBMYSQLCLIENT.SO.18 MISSING FROM MYSQL 5.7 as mysql-community-libs-5.5 or mysql-community-libs-5.6 can installed on EL6 system with libmysqlclient.16 (from MySQL 5.1) libmysqlclient.20 (from MySQL 5.7) by doing: $ rpm --oldpackage -ivh mysql-community-libs-5.5.50-2.el6.x86_64.rpm Providing a way to have several versions of libmysqlclient installed on the same system. and help: BUG#23088014/80981 LIBS-COMPAT RPMS SHOULD BE INDEPENDENT OF ALL OTHER SUBPACKAGES due to less strict coupling between -libs-compat and -common package. --- packaging/rpm-oel/mysql.spec.in | 52 +++++++++++++++++++++------------------- packaging/rpm-sles/mysql.spec.in | 42 ++++++++++++++++---------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/packaging/rpm-oel/mysql.spec.in b/packaging/rpm-oel/mysql.spec.in index 8f92f5b84f3..29957d98ed0 100644 --- a/packaging/rpm-oel/mysql.spec.in +++ b/packaging/rpm-oel/mysql.spec.in @@ -81,6 +81,8 @@ %global license_type GPLv2 %endif +%global min 5.5.8 + Name: mysql-%{product_suffix} Summary: A very fast and reliable SQL database server Group: Applications/Databases @@ -156,11 +158,11 @@ Requires: net-tools Provides: MySQL-server-advanced%{?_isa} = %{version}-%{release} Obsoletes: MySQL-server-advanced < %{version}-%{release} Obsoletes: mysql-community-server < %{version}-%{release} -Requires: mysql-commercial-client%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-client%{?_isa} >= %{min} Requires: mysql-commercial-common%{?_isa} = %{version}-%{release} %else Provides: MySQL-server%{?_isa} = %{version}-%{release} -Requires: mysql-community-client%{?_isa} = %{version}-%{release} +Requires: mysql-community-client%{?_isa} >= %{min} Requires: mysql-community-common%{?_isa} = %{version}-%{release} %endif Obsoletes: MySQL-server < %{version}-%{release} @@ -209,10 +211,10 @@ Group: Applications/Databases Provides: MySQL-client-advanced%{?_isa} = %{version}-%{release} Obsoletes: MySQL-client-advanced < %{version}-%{release} Obsoletes: mysql-community-client < %{version}-%{release} -Requires: mysql-commercial-libs%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-libs%{?_isa} >= %{min} %else Provides: MySQL-client%{?_isa} = %{version}-%{release} -Requires: mysql-community-libs%{?_isa} = %{version}-%{release} +Requires: mysql-community-libs%{?_isa} >= %{min} %endif Obsoletes: MySQL-client < %{version}-%{release} Obsoletes: mariadb @@ -234,7 +236,7 @@ Obsoletes: mysql-community-common < %{version}-%{release} %endif Provides: mysql-common = %{version}-%{release} Provides: mysql-common%{?_isa} = %{version}-%{release} -%{?el5:Requires: mysql%{?_isa} = %{version}-%{release}} +%{?el5:Requires: mysql%{?_isa} >= %{min}} %description common This packages contains common files needed by MySQL client library, @@ -248,10 +250,10 @@ Group: Applications/Databases Provides: MySQL-test-advanced%{?_isa} = %{version}-%{release} Obsoletes: MySQL-test-advanced < %{version}-%{release} Obsoletes: mysql-community-test < %{version}-%{release} -Requires: mysql-commercial-server%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-server%{?_isa} >= %{min} %else Provides: MySQL-test%{?_isa} = %{version}-%{release} -Requires: mysql-community-server%{?_isa} = %{version}-%{release} +Requires: mysql-community-server%{?_isa} >= %{min} %endif Obsoletes: MySQL-test < %{version}-%{release} Obsoletes: mysql-test < %{version}-%{release} @@ -270,9 +272,9 @@ Summary: MySQL benchmark suite Group: Applications/Databases %if 0%{?commercial} Obsoletes: mysql-community-bench < %{version}-%{release} -Requires: mysql-commercial-server%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-server%{?_isa} >= %{min} %else -Requires: mysql-community-server%{?_isa} = %{version}-%{release} +Requires: mysql-community-server%{?_isa} >= %{min} %endif Obsoletes: mariadb-bench Obsoletes: community-mysql-bench < %{version}-%{release} @@ -291,10 +293,10 @@ Group: Applications/Databases Provides: MySQL-devel-advanced%{?_isa} = %{version}-%{release} Obsoletes: MySQL-devel-advanced < %{version}-%{release} Obsoletes: mysql-community-devel < %{version}-%{release} -Requires: mysql-commercial-libs%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-libs%{?_isa} >= %{min} %else Provides: MySQL-devel%{?_isa} = %{version}-%{release} -Requires: mysql-community-libs%{?_isa} = %{version}-%{release} +Requires: mysql-community-libs%{?_isa} >= %{min} %endif Obsoletes: MySQL-devel < %{version}-%{release} Obsoletes: mysql-devel < %{version}-%{release} @@ -314,10 +316,10 @@ Group: Applications/Databases Provides: MySQL-shared-advanced%{?_isa} = %{version}-%{release} Obsoletes: MySQL-shared-advanced < %{version}-%{release} Obsoletes: mysql-community-libs < %{version}-%{release} -Requires: mysql-commercial-common%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-common%{?_isa} >= %{min} %else Provides: MySQL-shared%{?_isa} = %{version}-%{release} -Requires: mysql-community-common%{?_isa} = %{version}-%{release} +Requires: mysql-community-common%{?_isa} >= %{min} %endif Obsoletes: MySQL-shared < %{version}-%{release} Obsoletes: mysql-libs < %{version}-%{release} @@ -341,10 +343,10 @@ Provides: mysql-libs-compat%{?_isa} = %{version}-%{release} Provides: MySQL-shared-compat-advanced%{?_isa} = %{version}-%{release} Obsoletes: MySQL-shared-compat-advanced < %{version}-%{release} Obsoletes: mysql-community-libs-compat < %{version}-%{release} -Requires: mysql-commercial-libs%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-libs%{?_isa} >= %{min} %else Provides: MySQL-shared-compat%{?_isa} = %{version}-%{release} -Requires: mysql-community-libs%{?_isa} = %{version}-%{release} +Requires: mysql-community-libs%{?_isa} >= %{min} %endif Obsoletes: MySQL-shared-compat < %{version}-%{release} %if 0%{?rhel} > 5 @@ -391,11 +393,11 @@ Summary: Development header files and libraries for MySQL as an embeddabl Group: Applications/Databases %if 0%{?commercial} Obsoletes: mysql-community-embedded-devel < %{version}-%{release} -Requires: mysql-commercial-devel%{?_isa} = %{version}-%{release} -Requires: mysql-commercial-embedded%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-devel%{?_isa} >= %{min} +Requires: mysql-commercial-embedded%{?_isa} >= %{min} %else -Requires: mysql-community-devel%{?_isa} = %{version}-%{release} -Requires: mysql-community-embedded%{?_isa} = %{version}-%{release} +Requires: mysql-community-devel%{?_isa} >= %{min} +Requires: mysql-community-embedded%{?_isa} >= %{min} %endif Obsoletes: mariadb-embedded-devel Obsoletes: mysql-embedded-devel < %{version}-%{release} @@ -411,13 +413,13 @@ the embedded version of the MySQL server. Summary: Convenience package for easy upgrades of MySQL package set Group: Applications/Databases %if 0%{?commercial} -Requires: mysql-commercial-client%{?_isa} = %{version}-%{release} -Requires: mysql-commercial-libs%{?_isa} = %{version}-%{release} -Requires: mysql-commercial-libs-compat%{?_isa} = %{version}-%{release} +Requires: mysql-commercial-client%{?_isa} >= %{min} +Requires: mysql-commercial-libs%{?_isa} >= %{min} +Requires: mysql-commercial-libs-compat%{?_isa} >= %{min} %else -Requires: mysql-community-client%{?_isa} = %{version}-%{release} -Requires: mysql-community-libs%{?_isa} = %{version}-%{release} -Requires: mysql-community-libs-compat%{?_isa} = %{version}-%{release} +Requires: mysql-community-client%{?_isa} >= %{min} +Requires: mysql-community-libs%{?_isa} >= %{min} +Requires: mysql-community-libs-compat%{?_isa} >= %{min} %endif %description -n mysql diff --git a/packaging/rpm-sles/mysql.spec.in b/packaging/rpm-sles/mysql.spec.in index 38201428fda..a11dfff7b70 100644 --- a/packaging/rpm-sles/mysql.spec.in +++ b/packaging/rpm-sles/mysql.spec.in @@ -57,6 +57,8 @@ %global sles11 1 %endif +%global min 5.5.8 + Name: mysql-%{product_suffix} Summary: A very fast and reliable SQL database server Group: Applications/Databases @@ -125,12 +127,12 @@ Requires: perl-base Provides: MySQL-server-advanced = %{version}-%{release} Obsoletes: MySQL-server-advanced < %{version}-%{release} Obsoletes: mysql-community-server < %{version}-%{release} -Requires: mysql-commercial-client = %{version}-%{release} -Requires: mysql-commercial-common = %{version}-%{release} +Requires: mysql-commercial-client >= %{min} +Requires: mysql-commercial-common >= %{min} %else Provides: MySQL-server = %{version}-%{release} -Requires: mysql-community-client = %{version}-%{release} -Requires: mysql-community-common = %{version}-%{release} +Requires: mysql-community-client >= %{min} +Requires: mysql-community-common >= %{min} %endif Obsoletes: MySQL-server < %{version}-%{release} Obsoletes: mysql < %{version}-%{release} @@ -180,10 +182,10 @@ Group: Applications/Databases Provides: MySQL-client-advanced = %{version}-%{release} Obsoletes: MySQL-client-advanced < %{version}-%{release} Obsoletes: mysql-community-client < %{version}-%{release} -Requires: mysql-commercial-libs = %{version}-%{release} +Requires: mysql-commercial-libs >= %{min} %else Provides: MySQL-client = %{version}-%{release} -Requires: mysql-community-libs = %{version}-%{release} +Requires: mysql-community-libs >= %{min} %endif Obsoletes: MySQL-client < %{version}-%{release} Provides: mysql-client = %{version}-%{release} @@ -215,10 +217,10 @@ Group: Applications/Databases Provides: MySQL-test-advanced = %{version}-%{release} Obsoletes: MySQL-test-advanced < %{version}-%{release} Obsoletes: mysql-community-test < %{version}-%{release} -Requires: mysql-commercial-server = %{version}-%{release} +Requires: mysql-commercial-server >= %{min} %else Provides: MySQL-test = %{version}-%{release} -Requires: mysql-community-server = %{version}-%{release} +Requires: mysql-community-server >= %{min} %endif Obsoletes: MySQL-test < %{version}-%{release} Obsoletes: mysql-test < %{version}-%{release} @@ -236,9 +238,9 @@ Summary: MySQL benchmark suite Group: Applications/Databases %if 0%{?commercial} Obsoletes: mysql-community-bench < %{version}-%{release} -Requires: mysql-commercial-server = %{version}-%{release} +Requires: mysql-commercial-server >= %{min} %else -Requires: mysql-community-server = %{version}-%{release} +Requires: mysql-community-server >= %{min} %endif Obsoletes: mariadb-bench Obsoletes: community-mysql-bench < %{version}-%{release} @@ -257,10 +259,10 @@ Group: Applications/Databases Provides: MySQL-devel-advanced = %{version}-%{release} Obsoletes: MySQL-devel-advanced < %{version}-%{release} Obsoletes: mysql-community-devel < %{version}-%{release} -Requires: mysql-commercial-libs = %{version}-%{release} +Requires: mysql-commercial-libs >= %{min} %else Provides: MySQL-devel = %{version}-%{release} -Requires: mysql-community-libs = %{version}-%{release} +Requires: mysql-community-libs >= %{min} %endif Obsoletes: MySQL-devel < %{version}-%{release} Obsoletes: mysql-devel < %{version}-%{release} @@ -281,10 +283,10 @@ Group: Applications/Databases Provides: MySQL-shared-advanced = %{version}-%{release} Obsoletes: MySQL-shared-advanced < %{version}-%{release} Obsoletes: mysql-community-libs < %{version}-%{release} -Requires: mysql-commercial-common = %{version}-%{release} +Requires: mysql-commercial-common >= %{min} %else Provides: MySQL-shared = %{version}-%{release} -Requires: mysql-community-common = %{version}-%{release} +Requires: mysql-community-common >= %{min} %endif Obsoletes: MySQL-shared < %{version}-%{release} Obsoletes: mysql-libs < %{version}-%{release} @@ -307,10 +309,10 @@ Group: Applications/Databases Provides: MySQL-embedded-advanced = %{version}-%{release} Obsoletes: MySQL-embedded-advanced < %{version}-%{release} Obsoletes: mysql-community-embedded < %{version}-%{release} -Requires: mysql-commercial-common = %{version}-%{release} +Requires: mysql-commercial-common >= %{min} %else Provides: MySQL-embedded = %{version}-%{release} -Requires: mysql-community-common = %{version}-%{release} +Requires: mysql-community-common >= %{min} %endif Obsoletes: mariadb-embedded Obsoletes: MySQL-embedded < %{version}-%{release} @@ -334,11 +336,11 @@ Summary: Development header files and libraries for MySQL as an embeddabl Group: Applications/Databases %if 0%{?commercial} Obsoletes: mysql-community-embedded-devel < %{version}-%{release} -Requires: mysql-commercial-devel = %{version}-%{release} -Requires: mysql-commercial-embedded = %{version}-%{release} +Requires: mysql-commercial-devel >= %{min} +Requires: mysql-commercial-embedded >= %{min} %else -Requires: mysql-community-devel = %{version}-%{release} -Requires: mysql-community-embedded = %{version}-%{release} +Requires: mysql-community-devel >= %{min} +Requires: mysql-community-embedded >= %{min} %endif Obsoletes: mariadb-embedded-devel Obsoletes: mysql-embedded-devel < %{version}-%{release} -- cgit v1.2.1 From 9f7288e2e0179db478d20c74f57b5c7d6c95f793 Mon Sep 17 00:00:00 2001 From: Thayumanavar S Date: Mon, 20 Jun 2016 11:35:43 +0530 Subject: BUG#23080148 - BACKPORT BUG 14653594 AND BUG 20683959 TO MYSQL-5.5 The bug asks for a backport of bug#1463594 and bug#20682959. This is required because of the fact that if replication is enabled, master transaction can commit whereas slave can't commit due to not exact 'enviroment'. This manifestation is seen in bug#22024200. --- mysql-test/r/loaddata.result | 26 +++++++++- mysql-test/std_data/bug20683959loaddata.txt | 1 + mysql-test/t/loaddata.test | 25 +++++++++- sql/sql_load.cc | 77 ++++++++++++++++++----------- 4 files changed, 99 insertions(+), 30 deletions(-) create mode 100644 mysql-test/std_data/bug20683959loaddata.txt diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 2d67d24bedd..2f2a3579eec 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -507,7 +507,7 @@ DROP TABLE t1; # Bug#11765139 58069: LOAD DATA INFILE: VALGRIND REPORTS INVALID MEMORY READS AND WRITES WITH U # CREATE TABLE t1(f1 INT); -SELECT 0xE1BB30 INTO OUTFILE 't1.dat'; +SELECT 0xE1C330 INTO OUTFILE 't1.dat'; LOAD DATA INFILE 't1.dat' IGNORE INTO TABLE t1 CHARACTER SET utf8; DROP TABLE t1; # @@ -532,3 +532,27 @@ FIELDS TERMINATED BY 't' LINES TERMINATED BY ''; Got one of the listed errors SET @@sql_mode= @old_mode; DROP TABLE t1; + +# +# Bug#23080148 - Backport of Bug#20683959. +# Bug#20683959 LOAD DATA INFILE IGNORES A SPECIFIC ROW SILENTLY +# UNDER DB CHARSET IS UTF8. +# +CREATE DATABASE d1 CHARSET latin1; +USE d1; +CREATE TABLE t1 (val TEXT); +LOAD DATA INFILE '../../std_data/bug20683959loaddata.txt' INTO TABLE t1; +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT HEX(val) FROM t1; +HEX(val) +C38322525420406E696F757A656368756E3A20E98198E2889AF58081AEE7B99DE4B88AE383A3E7B99DE69690F58087B3E7B9A7EFBDA8E7B99DEFBDB3E7B99DE78999E880B3E7B8BAEFBDAAE7B9A7E89699E296A1E7B8BAE4BBA3EFBD8CE7B8BAEFBDA9E7B8B2E2889AE38184E7B99DEFBDB3E7B99DE4B88AE383A3E7B99DE69690F58087B3E7B9A7EFBDA8E7B99DEFBDB3E7B99DE5B3A8EFBD84E8ABA0EFBDA8E89C89F580948EE599AAE7B8BAEFBDAAE7B8BAE9A198EFBDA9EFBDB1E7B9A7E581B5E289A0E7B8BAEFBDBEE7B9A7E9A194EFBDA9E882B4EFBDA5EFBDB5E980A7F5808B96E28693E99EABE38287E58F99E7B8BAE58AB1E28691E7B8BAF5808B9AE7828AE98095EFBDB1E7B8BAEFBDAFE7B8B2E288ABE6A89FE89EB3E6BA98F58081ADE88EA0EFBDBAE98095E6BA98F58081AEE89D93EFBDBAE8AD9BEFBDACE980A7F5808B96E28693E7B8BAF580918EE288AAE7B8BAE4B88AEFBC9EE7B8BAE4B99DE28691E7B8BAF5808B96EFBCA0E88DB3E6A68AEFBDB9EFBDB3E981B2E5B3A8E296A1E7B8BAE7A4BCE7828AE88DB3E6A68AEFBDB0EFBDBDE7B8BAA0E7B8BAE88B93EFBDBEE5B899EFBC9E +CREATE DATABASE d2 CHARSET utf8; +USE d2; +CREATE TABLE t1 (val TEXT); +LOAD DATA INFILE '../../std_data/bug20683959loaddata.txt' INTO TABLE t1; +ERROR HY000: Invalid utf8 character string: '"RT @niouzechun: \9058\221A' +DROP TABLE d1.t1, d2.t1; +DROP DATABASE d1; +DROP DATABASE d2; diff --git a/mysql-test/std_data/bug20683959loaddata.txt b/mysql-test/std_data/bug20683959loaddata.txt new file mode 100644 index 00000000000..1878cc78879 --- /dev/null +++ b/mysql-test/std_data/bug20683959loaddata.txt @@ -0,0 +1 @@ +Ã"RT @niouzechun: 遘√繝上ャ繝斐繧ィ繝ウ繝牙耳縺ェ繧薙□縺代l縺ゥ縲√い繝ウ繝上ャ繝斐繧ィ繝ウ繝峨d諠ィ蜉噪縺ェ縺願ゥア繧偵≠縺セ繧顔ゥ肴・オ逧↓鞫ょ叙縺励↑縺炊逕ア縺ッ縲∫樟螳溘莠コ逕溘蝓コ譛ャ逧↓縺∪縺上>縺九↑縺@荳榊ケウ遲峨□縺礼炊荳榊ース縺縺苓セ帙> diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index aa7be52484e..9a664b84843 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -610,7 +610,7 @@ disconnect con1; --echo # CREATE TABLE t1(f1 INT); -EVAL SELECT 0xE1BB30 INTO OUTFILE 't1.dat'; +EVAL SELECT 0xE1C330 INTO OUTFILE 't1.dat'; --disable_warnings LOAD DATA INFILE 't1.dat' IGNORE INTO TABLE t1 CHARACTER SET utf8; --enable_warnings @@ -656,3 +656,26 @@ SET @@sql_mode= @old_mode; --remove_file $MYSQLTEST_VARDIR/mysql DROP TABLE t1; +--echo +--echo # +--echo # Bug#23080148 - Backport of Bug#20683959. +--echo # Bug#20683959 LOAD DATA INFILE IGNORES A SPECIFIC ROW SILENTLY +--echo # UNDER DB CHARSET IS UTF8. +--echo # + +CREATE DATABASE d1 CHARSET latin1; +USE d1; +CREATE TABLE t1 (val TEXT); +LOAD DATA INFILE '../../std_data/bug20683959loaddata.txt' INTO TABLE t1; +SELECT COUNT(*) FROM t1; +SELECT HEX(val) FROM t1; + +CREATE DATABASE d2 CHARSET utf8; +USE d2; +CREATE TABLE t1 (val TEXT); +--error ER_INVALID_CHARACTER_STRING +LOAD DATA INFILE '../../std_data/bug20683959loaddata.txt' INTO TABLE t1; + +DROP TABLE d1.t1, d2.t1; +DROP DATABASE d1; +DROP DATABASE d2; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index c084e5e3839..a46967a24a8 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1363,8 +1363,8 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, set_if_bigger(length,line_start.length()); stack=stack_pos=(int*) sql_alloc(sizeof(int)*length); - if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(0)))) - error=1; /* purecov: inspected */ + if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(MY_WME)))) + error= true; /* purecov: inspected */ else { end_of_buff=buffer+buff_length; @@ -1556,37 +1556,50 @@ int READ_INFO::read_field() } } #ifdef USE_MB - if (my_mbcharlen(read_charset, chr) > 1 && - to + my_mbcharlen(read_charset, chr) <= end_of_buff) - { - uchar* p= to; - int ml, i; - *to++ = chr; - - ml= my_mbcharlen(read_charset, chr); + uint ml= my_mbcharlen(read_charset, chr); + if (ml == 0) + { + *to= '\0'; + my_error(ER_INVALID_CHARACTER_STRING, MYF(0), + read_charset->csname, buffer); + error= true; + return 1; + } - for (i= 1; i < ml; i++) + if (ml > 1 && + to + ml <= end_of_buff) { - chr= GET; - if (chr == my_b_EOF) + uchar* p= to; + *to++ = chr; + + for (uint i= 1; i < ml; i++) { - /* - Need to back up the bytes already ready from illformed - multi-byte char - */ - to-= i; - goto found_eof; + chr= GET; + if (chr == my_b_EOF) + { + /* + Need to back up the bytes already ready from illformed + multi-byte char + */ + to-= i; + goto found_eof; + } + *to++ = chr; } - *to++ = chr; - } - if (my_ismbchar(read_charset, + if (my_ismbchar(read_charset, (const char *)p, (const char *)to)) - continue; - for (i= 0; i < ml; i++) - PUSH(*--to); - chr= GET; - } + continue; + for (uint i= 0; i < ml; i++) + PUSH(*--to); + chr= GET; + } + else if (ml > 1) + { + // Buffer is too small, exit while loop, and reallocate. + PUSH(chr); + break; + } #endif *to++ = (uchar) chr; } @@ -1830,7 +1843,15 @@ int READ_INFO::read_value(int delim, String *val) for (chr= GET; my_tospace(chr) != delim && chr != my_b_EOF;) { #ifdef USE_MB - if (my_mbcharlen(read_charset, chr) > 1) + uint ml= my_mbcharlen(read_charset, chr); + if (ml == 0) + { + chr= my_b_EOF; + val->length(0); + return chr; + } + + if (ml > 1) { DBUG_PRINT("read_xml",("multi byte")); int i, ml= my_mbcharlen(read_charset, chr); -- cgit v1.2.1 From 7d57772f47e0d69b2e2a7bcd62da59e54f8c8343 Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Tue, 5 Jul 2016 17:08:37 +0530 Subject: Bug#23736787 - YUM UPDATE FAIL FROM 5.5.51(COMUNITY/COMMERCIAL) TO 5.6.32(COMUNITY/COMMERCIAL) Remove mysql_config from client sub-package (cherry picked from commit 45c4bfa0f3f1c70756591f48710bb3e76ffde9bc) --- packaging/rpm-oel/mysql.spec.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packaging/rpm-oel/mysql.spec.in b/packaging/rpm-oel/mysql.spec.in index 29957d98ed0..409c325b675 100644 --- a/packaging/rpm-oel/mysql.spec.in +++ b/packaging/rpm-oel/mysql.spec.in @@ -835,8 +835,6 @@ fi %attr(755, root, root) %{_bindir}/mysqlimport %attr(755, root, root) %{_bindir}/mysqlshow %attr(755, root, root) %{_bindir}/mysqlslap -%attr(755, root, root) %{_bindir}/mysql_config -%attr(755, root, root) %{_bindir}/mysql_config-%{__isa_bits} %attr(644, root, root) %{_mandir}/man1/msql2mysql.1* %attr(644, root, root) %{_mandir}/man1/mysql.1* @@ -918,6 +916,9 @@ fi %endif %changelog +* Tue Jul 05 2016 Balasubramanian Kandasamy - 5.5.51-1 +- Remove mysql_config from client subpackage + * Tue Sep 29 2015 Balasubramanian Kandasamy - 5.5.47-1 - Added conflicts to mysql-connector-c-shared dependencies -- cgit v1.2.1