From da0089a11da921fe1acec2de97c64f2ac6bda288 Mon Sep 17 00:00:00 2001 From: Murthy Narkedimilli Date: Tue, 23 Jun 2015 06:06:07 +0200 Subject: [PATCH 01/37] Raise version number after cloning 5.5.45 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 904aeda33ab..45f770d8f07 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=45 +MYSQL_VERSION_PATCH=46 MYSQL_VERSION_EXTRA= From 8f87d6cd41042fe931305a60718d6aa1015a9ccc Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Tue, 23 Jun 2015 13:56:39 +0200 Subject: [PATCH 02/37] Raise version number after tagging 5.1.76 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 84ffbb7ac74..be169e073bd 100644 --- a/configure.in +++ b/configure.in @@ -29,7 +29,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MySQL Server], [5.1.76], [], [mysql]) +AC_INIT([MySQL Server], [5.1.77], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From 0eadadad25d9e44232e1567897cf9dcb957ccdcd Mon Sep 17 00:00:00 2001 From: Debarun Banerjee Date: Wed, 24 Jun 2015 10:27:12 +0530 Subject: [PATCH 03/37] BUG#20310212 PARTITION DDL- CRASH AFTER THD::NOCHECK_REGISTER_ITEM_ Problem : --------- Issue-1: The root cause for the issues is that (col1 > 1) is not a valid partition function and we should have thrown error at much early stage [partition_info::check_partition_info]. We are not checking sub-partition expression when partition expression is NULL. Issue-2: Potential issue for future if any partition function needs to change item tree during open/fix_fields. We should release changed items, if any, before doing closefrm when we open the partitioned table during creation in create_table_impl. Solution : ---------- 1.check_partition_info() - Check for sub-partition expression even if no partition expression. [partition by ... columns(...) subpartition by hash()] 2.create_table_impl() - Assert that the change list is empty before doing closefrm for partitioned table. Currently no supported partition function seems to be changing item tree during open. Reviewed-by: Mattias Jonsson RB: 9345 --- mysql-test/r/partition_error.result | 2 +- mysql-test/t/partition_error.test | 2 +- sql/partition_info.cc | 15 +++++++++++---- sql/sql_table.cc | 6 ++++++ 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 0e4f89b70db..1e0f2cbea10 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1089,7 +1089,7 @@ partition by key (a) subpartition by hash (sin(a+b)) (partition x1 (subpartition x11, subpartition x12), partition x2 (subpartition x21, subpartition x22)); -ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning +ERROR HY000: This partition function is not allowed select load_file('$MYSQLD_DATADIR/test/t1.par'); load_file('$MYSQLD_DATADIR/test/t1.par') NULL diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index c0f49a4d414..9a6939032a3 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -1145,7 +1145,7 @@ subpartition by hash (rand(a+b)); # # Subpartition by hash, wrong subpartition function # ---error ER_SUBPARTITION_ERROR +--error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED CREATE TABLE t1 ( a int not null, b int not null, diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 958f77f5bd0..336010cc7dd 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2015, 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 @@ -1109,15 +1109,22 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, { int err= 0; + /* Check for partition expression. */ if (!list_of_part_fields) { DBUG_ASSERT(part_expr); err= part_expr->walk(&Item::check_partition_func_processor, 0, NULL); - if (!err && is_sub_partitioned() && !list_of_subpart_fields) - err= subpart_expr->walk(&Item::check_partition_func_processor, 0, - NULL); } + + /* Check for sub partition expression. */ + if (!err && is_sub_partitioned() && !list_of_subpart_fields) + { + DBUG_ASSERT(subpart_expr); + err= subpart_expr->walk(&Item::check_partition_func_processor, 0, + NULL); + } + if (err) { my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b8858cffce6..2951d921e15 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3913,6 +3913,12 @@ static bool check_if_created_table_can_be_opened(THD *thd, result= (open_table_def(thd, &share, 0) || open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table, TRUE)); + /* + Assert that the change list is empty as no partition function currently + needs to modify item tree. May need call THD::rollback_item_tree_changes + later before calling closefrm if the change list is not empty. + */ + DBUG_ASSERT(thd->change_list.is_empty()); if (! result) (void) closefrm(&table, 0); From 9068238b1984100dc2251f742a994b18fafaa841 Mon Sep 17 00:00:00 2001 From: Yashwant Sahu Date: Wed, 24 Jun 2015 17:48:46 +0530 Subject: [PATCH 04/37] Bug# 20376760: STACK-BUFFER-OVERFLOW WITH LONG PATHS TO CERTAIN VARIABLES --- mysys/mf_loadpath.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/mf_loadpath.c b/mysys/mf_loadpath.c index 776435e0e75..812c3895bec 100644 --- a/mysys/mf_loadpath.c +++ b/mysys/mf_loadpath.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2015, 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 @@ -47,7 +47,7 @@ char * my_load_path(char * to, const char *path, (void) strnmov(buff, path, FN_REFLEN); /* Return org file name */ } else - (void) strxnmov(buff, FN_REFLEN, own_path_prefix, path, NullS); + (void) strxnmov(buff, sizeof(buff)-1, own_path_prefix, path, NullS); strnmov(to, buff, FN_REFLEN); to[FN_REFLEN-1]= '\0'; DBUG_PRINT("exit",("to: %s",to)); From 7c5d18e2271ce4fcd9294511860841dbb4fec31a Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Tue, 30 Jun 2015 10:27:12 +0530 Subject: [PATCH 05/37] Bug #20772273 : MYSQLIMPORT --USE-THREADS DOESN'T USE MULTIPLE THREADS Description:- The utility "mysqlimport" does not use multiple threads for the execution with option "--use-threads". "mysqlimport" while importing multiple files and multiple tables, uses a single thread even if the number of threads are specified with "--use-threads" option. Analysis:- This utility uses ifdef HAVE_LIBPTHREAD to check for libpthread library and if defined uses libpthread library for mutlithreaing. Since HAVE_LIBPTHREAD is not defined anywhere in the source, "--use-threads" option is silently ignored. Fix:- "-DTHREADS" is set to the COMPILE_FLAGS which will enable pthreads. HAVE_LIBPTHREAD macro is removed. --- client/CMakeLists.txt | 3 ++- client/mysqlimport.c | 11 +---------- mysql-test/r/mysqldump.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 29 +++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 0d67cf2e0d4..21b1e084409 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2015, 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 @@ -51,6 +51,7 @@ MYSQL_ADD_EXECUTABLE(mysqldump mysqldump.c ../sql-common/my_user.c) TARGET_LINK_LIBRARIES(mysqldump mysqlclient) MYSQL_ADD_EXECUTABLE(mysqlimport mysqlimport.c) +SET_SOURCE_FILES_PROPERTIES(mysqlimport.c PROPERTIES COMPILE_FLAGS "-DTHREADS") TARGET_LINK_LIBRARIES(mysqlimport mysqlclient) MYSQL_ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 2045c94619b..813c1baf793 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -24,19 +24,14 @@ #include "client_priv.h" #include "mysql_version.h" -#ifdef HAVE_LIBPTHREAD -#include -#endif #include /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ /* Global Thread counter */ uint counter; -#ifdef HAVE_LIBPTHREAD pthread_mutex_t counter_mutex; pthread_cond_t count_threshhold; -#endif static void db_error_with_table(MYSQL *mysql, char *table); static void db_error(MYSQL *mysql); @@ -548,7 +543,6 @@ static char *field_escape(char *to,const char *from,uint length) int exitcode= 0; -#ifdef HAVE_LIBPTHREAD pthread_handler_t worker_thread(void *arg) { int error; @@ -588,7 +582,6 @@ error: return 0; } -#endif int main(int argc, char **argv) @@ -607,7 +600,6 @@ int main(int argc, char **argv) return(1); } -#ifdef HAVE_LIBPTHREAD if (opt_use_threads && !lock_tables) { pthread_t mainthread; /* Thread descriptor */ @@ -661,7 +653,6 @@ int main(int argc, char **argv) pthread_attr_destroy(&attr); } else -#endif { MYSQL *mysql= 0; if (!(mysql= db_connect(current_host,current_db,current_user,opt_password))) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index a31516d10d2..c578f9e8df6 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -5255,3 +5255,31 @@ SET @@global.general_log= @old_general_log_state; # # End of 5.1 tests # +# +# Bug #20772273 : MYSQLIMPORT --USE-THREADS DOESN'T USE MULTIPLE THREADS +# +CREATE DATABASE db_20772273; +USE db_20772273; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2); +CREATE TABLE t2(a INT); +INSERT INTO t2 VALUES (3), (4); +SELECT * FROM t1; +a +1 +2 +SELECT * FROM t2; +a +3 +4 +SELECT * FROM t1; +a +1 +2 +SELECT * FROM t2; +a +3 +4 +DROP TABLE t1; +DROP TABLE t2; +DROP DATABASE db_20772273; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 478d8fb2863..54780b95627 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -2401,3 +2401,32 @@ SET @@global.general_log= @old_general_log_state; --echo # --echo # End of 5.1 tests --echo # + +--echo # +--echo # Bug #20772273 : MYSQLIMPORT --USE-THREADS DOESN'T USE MULTIPLE THREADS +--echo # + +CREATE DATABASE db_20772273; +USE db_20772273; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2); +CREATE TABLE t2(a INT); +INSERT INTO t2 VALUES (3), (4); + +SELECT * FROM t1; +SELECT * FROM t2; + +--exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ db_20772273 +--exec $MYSQL db_20772273 < $MYSQLTEST_VARDIR/tmp/t1.sql +--exec $MYSQL db_20772273 < $MYSQLTEST_VARDIR/tmp/t2.sql + +# Test mysqlimport with multiple threads +--exec $MYSQL_IMPORT --silent --use-threads=2 db_20772273 $MYSQLTEST_VARDIR/tmp/t1.txt $MYSQLTEST_VARDIR/tmp/t2.txt + +SELECT * FROM t1; +SELECT * FROM t2; + +#Cleanup +DROP TABLE t1; +DROP TABLE t2; +DROP DATABASE db_20772273; From 7ce304dff0e268304c8c13708ff9a3f034cce50a Mon Sep 17 00:00:00 2001 From: Praveenkumar Hulakund Date: Thu, 2 Jul 2015 15:31:55 +0530 Subject: [PATCH 06/37] Bug#18487951 - QUERY_CACHE_MIN_RES_UNIT SET TO ZERO, CRASHES IN QUERY_CACHE::FIND_BIN Valid min value for query_cache_min_res_unit is 512. But attempt to set value greater than or equal to the ULONG_MAX(max value) is resulting query_cache_min_res_unit value to 0. This result in crash while searching for memory block lesser than the valid min value to store query results. Free memory blocks in query cache are stored in bins according to their size. The bins are stored in size descending order. For the memory block request the appropriate bin is searched using binary search algorithm. The minimum free memory block request expected is 512 bytes. And the appropriate bin is searched for block greater than or equals to 512 bytes. Because of the bug the query_cache_min_res_unit is set to 0. Due to which there is a chance of request for memory blocks lesser than the minimum size in free memory block bins. Search for bin for this invalid input size fails and returns garbage index. Accessing bins array element with this index is causing the issue reported. The valid value range for the query_cache_min_res_unit is 512 to ULONG_MAX(when value is greater than the max allowed value, max allowed value is used i.e ULONG_MAX). While setting result unit block size (query_cache_min_res_unit), size is memory aligned by using a macro ALIGN_SIZE. The ALIGN_SIZE logic is as below, (input_size + sizeof(double) - 1) & ~(sizeof(double) - 1) For unsigned long type variable when input_size is greater than equal to ULONG_MAX-(sizeof(double)-1), above expression is resulting in value 0. Fix: ----- Comparing value set for query_cache_min_res_unit with max aligned value which can be stored in ulong type variable. If it is greater then setting it to the max aligned value for ulong type variable. --- sql/sql_cache.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index ca3db3b48c0..e1f9e68ff83 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2013, 2015, 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 @@ -399,6 +400,9 @@ TODO list: #define QC_DEBUG_SYNC(name) #endif +// Max aligned size for ulong type query_cache_min_res_unit. +static const ulong max_aligned_min_res_unit_size= ((ULONG_MAX) & + (~(sizeof(double) - 1))); /** Thread state to be used when the query cache lock needs to be acquired. @@ -1158,6 +1162,9 @@ ulong Query_cache::set_min_res_unit(ulong size) { if (size < min_allocation_unit) size= min_allocation_unit; + else if (size > max_aligned_min_res_unit_size) + size= max_aligned_min_res_unit_size; + return (min_result_data_size= ALIGN_SIZE(size)); } From 2ac01ca6606a300dc7c043affccb9f850284a5e7 Mon Sep 17 00:00:00 2001 From: Praveenkumar Hulakund Date: Fri, 3 Jul 2015 16:56:13 +0530 Subject: [PATCH 07/37] Bug#18487951 - QUERY_CACHE_MIN_RES_UNIT SET TO ZERO, CRASHES IN QUERY_CACHE::FIND_BIN Follow up patch to fix sys_vars.query_cache_min_res_unit_basic_32 test failure. --- .../r/query_cache_min_res_unit_basic_32.result | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic_32.result b/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic_32.result index c408a39fdc0..9dc4a0d5062 100644 --- a/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic_32.result +++ b/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic_32.result @@ -50,7 +50,7 @@ Warnings: Warning 1292 Truncated incorrect query_cache_min_res_unit value: '4294967296' SELECT @@global.query_cache_min_res_unit; @@global.query_cache_min_res_unit -0 +4294967288 SET @@global.query_cache_min_res_unit = 511; SELECT @@global.query_cache_min_res_unit; @@global.query_cache_min_res_unit @@ -71,23 +71,23 @@ Warnings: Warning 1292 Truncated incorrect query_cache_min_res_unit value: '42949672950' SELECT @@global.query_cache_min_res_unit; @@global.query_cache_min_res_unit -0 +4294967288 SET @@global.query_cache_min_res_unit = ON; ERROR 42000: Incorrect argument type to variable 'query_cache_min_res_unit' SELECT @@global.query_cache_min_res_unit; @@global.query_cache_min_res_unit -0 +4294967288 SET @@global.query_cache_min_res_unit = 'test'; ERROR 42000: Incorrect argument type to variable 'query_cache_min_res_unit' SELECT @@global.query_cache_min_res_unit; @@global.query_cache_min_res_unit -0 +4294967288 '#-------------------FN_DYNVARS_132_05----------------------------#' SET @@session.query_cache_min_res_unit = 0; ERROR HY000: Variable 'query_cache_min_res_unit' is a GLOBAL variable and should be set with SET GLOBAL SELECT @@query_cache_min_res_unit; @@query_cache_min_res_unit -0 +4294967288 '#----------------------FN_DYNVARS_132_06------------------------#' SELECT @@global.query_cache_min_res_unit = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES From 359f102ad157adaacc904a1c81f5ddcb9ce3662b Mon Sep 17 00:00:00 2001 From: Debarun Banerjee Date: Wed, 8 Jul 2015 10:00:53 +0530 Subject: [PATCH 08/37] BUG#16613004 PARTITIONING DDL, CRASH IN FIELD_VARSTRING::CMP_MAX Problem : --------- The specific issue reported in this bug is with range/list column value that is allocated and initialized by evaluating partition expression(item tree) during execution. After evaluation the range list value is marked fixed [part_column_list_val]. During next execution, we don't re-evaluate the expression and use the old value since it is marked fixed. Solution : ---------- One way to solve the issue is to mark all column values as not fixed during clone so that the expression is always re-evaluated once we attempt partition_info::fix_column_value_functions() after cloning the part_info object during execution of DDL on partitioned table. Reviewed-by: Jimmy Yang Reviewed-by: Mattias Jonsson RB: 9424 --- sql/partition_info.cc | 22 +++++++++++++++++++++- sql/partition_info.h | 4 ++-- sql/sql_parse.cc | 4 ++-- sql/sql_partition.cc | 4 ++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 336010cc7dd..a0d09557b81 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -31,7 +31,7 @@ #include "ha_partition.h" -partition_info *partition_info::get_clone() +partition_info *partition_info::get_clone(bool reset /* = false */) { if (!this) return 0; @@ -57,6 +57,26 @@ partition_info *partition_info::get_clone() return NULL; } memcpy(part_clone, part, sizeof(partition_element)); + + /* + Mark that RANGE and LIST values needs to be fixed so that we don't + use old values. fix_column_value_functions would evaluate the values + from Item expression. + */ + if (reset) + { + clone->defined_max_value = false; + List_iterator list_it(part_clone->list_val_list); + while (part_elem_value *list_value= list_it++) + { + part_column_list_val *col_val= list_value->col_val_array; + for (uint i= 0; i < num_columns; col_val++, i++) + { + col_val->fixed= 0; + } + } + } + part_clone->subpartitions.empty(); while ((subpart= (subpart_it++))) { diff --git a/sql/partition_info.h b/sql/partition_info.h index 806b15da1ea..7bfbf8a1b1a 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -1,7 +1,7 @@ #ifndef PARTITION_INFO_INCLUDED #define PARTITION_INFO_INCLUDED -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2015, 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 @@ -265,7 +265,7 @@ public: } ~partition_info() {} - partition_info *get_clone(); + partition_info *get_clone(bool reset = false); /* Answers the question if subpartitioning is used for a certain table */ bool is_sub_partitioned() { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f52f56447f4..e1fc26775a4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2015, 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 @@ -2428,7 +2428,7 @@ case SQLCOM_PREPARE: #ifdef WITH_PARTITION_STORAGE_ENGINE { partition_info *part_info= thd->lex->part_info; - if (part_info && !(part_info= thd->lex->part_info->get_clone())) + if (part_info && !(part_info= thd->lex->part_info->get_clone(true))) { res= -1; goto end_with_restore_list; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index c615ee96d03..5358535e9f9 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2015, 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 @@ -4718,7 +4718,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, thd->work_part_info= thd->lex->part_info; if (thd->work_part_info && - !(thd->work_part_info= thd->lex->part_info->get_clone())) + !(thd->work_part_info= thd->lex->part_info->get_clone(true))) DBUG_RETURN(TRUE); /* ALTER_ADMIN_PARTITION is handled in mysql_admin_table */ From bf681d6bb341411a8b17abeda8e723368545d48d Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Wed, 8 Jul 2015 11:53:54 +0530 Subject: [PATCH 09/37] Bug #20802751 - SEGMENTATION FAILURE WHEN RUNNING MYSQLADMIN -U ROOT -P DESCRIPTION =========== Crash occurs when no command is given while executing mysqladmin utility. ANALYSIS ======== In mask_password() the final write to array 'temp_argv' is done without checking if corresponding index 'argc' is valid (non-negative) or not. In case its negative (would happen when this function is called with 'argc'=0), it may cause a SEGFAULT. Logically in such a case, mask_password() should not have been called as it would do no valid thing. FIX === mask_password() is now called after checking 'argc'. This function is now called only when 'argc' is positive otherwise the process terminates --- client/mysqladmin.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 2a1f8b521f0..e8bb4a1a27c 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -319,8 +319,6 @@ int main(int argc,char *argv[]) free_defaults(save_argv); exit(ho_error); } - temp_argv= mask_password(argc, &argv); - temp_argc= argc; if (debug_info_flag) my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO; @@ -332,6 +330,10 @@ int main(int argc,char *argv[]) usage(); exit(1); } + + temp_argv= mask_password(argc, &argv); + temp_argc= argc; + commands = temp_argv; if (tty_password) opt_password = get_tty_password(NullS); From c9685a78c3960f5822e42e0dc847c72a46528af5 Mon Sep 17 00:00:00 2001 From: Robert Golebiowski Date: Fri, 20 Mar 2015 15:05:59 +0100 Subject: [PATCH 10/37] Bug #20168526 YASSL: CORRUPT SSL-KEY CRASHES CLIENT Affects at least 5.6 and 5.7. In customer case, the "client" happened to be a replication slave, therefore his server crashed. Bug-fix: The bug was in yassl. Todd Ouska has provided us with the patch. (cherry picked from commit 42ffa91aad898b02f0793b669ffd04f5c178ce39) --- extra/yassl/README | 4 ++++ extra/yassl/include/openssl/ssl.h | 2 +- extra/yassl/src/ssl.cpp | 29 +++++++++++++++++++++++++++- extra/yassl/taocrypt/src/rsa.cpp | 4 ++++ extra/yassl/testsuite/cipher-test.sh | 1 + 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/extra/yassl/README b/extra/yassl/README index da399c3d141..d245d20ce5f 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -12,6 +12,10 @@ before calling SSL_new(); *** end Note *** +yaSSL Patch notes, version 2.3.7b (3/18/2015) + This release of yaSSL fixes a potential crash with corrupted private keys. + Also detects bad keys earlier for user. + yaSSL Release notes, version 2.3.7 (12/10/2014) This release of yaSSL fixes the potential to process duplicate handshake messages by explicitly marking/checking received handshake messages. diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 24acc7e86b9..e10fb5299f7 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -35,7 +35,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.3.7" +#define YASSL_VERSION "2.3.7b" #if defined(__cplusplus) diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index a47b175e635..845b35bac8b 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -37,6 +37,8 @@ #include "file.hpp" // for TaoCrypt Source #include "coding.hpp" // HexDecoder #include "helpers.hpp" // for placement new hack +#include "rsa.hpp" // for TaoCrypt RSA key decode +#include "dsa.hpp" // for TaoCrypt DSA key decode #include #ifdef _WIN32 @@ -54,6 +56,8 @@ namespace yaSSL { int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) { + int ret = SSL_SUCCESS; + if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM) return SSL_BAD_FILETYPE; @@ -141,8 +145,31 @@ int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) } } } + + if (type == PrivateKey && ctx->privateKey_) { + // see if key is valid early + TaoCrypt::Source rsaSource(ctx->privateKey_->get_buffer(), + ctx->privateKey_->get_length()); + TaoCrypt::RSA_PrivateKey rsaKey; + rsaKey.Initialize(rsaSource); + + if (rsaSource.GetError().What()) { + // rsa failed see if DSA works + + TaoCrypt::Source dsaSource(ctx->privateKey_->get_buffer(), + ctx->privateKey_->get_length()); + TaoCrypt::DSA_PrivateKey dsaKey; + dsaKey.Initialize(dsaSource); + + if (rsaSource.GetError().What()) { + // neither worked + ret = SSL_FAILURE; + } + } + } + fclose(input); - return SSL_SUCCESS; + return ret; } diff --git a/extra/yassl/taocrypt/src/rsa.cpp b/extra/yassl/taocrypt/src/rsa.cpp index 79a8a8f1c4f..73f678e2674 100644 --- a/extra/yassl/taocrypt/src/rsa.cpp +++ b/extra/yassl/taocrypt/src/rsa.cpp @@ -140,6 +140,10 @@ word32 RSA_BlockType2::UnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, void RSA_BlockType1::Pad(const byte* input, word32 inputLen, byte* pkcsBlock, word32 pkcsBlockLen, RandomNumberGenerator&) const { + // sanity checks + if (input == NULL || pkcsBlock == NULL) + return; + // convert from bit length to byte length if (pkcsBlockLen % 8 != 0) { diff --git a/extra/yassl/testsuite/cipher-test.sh b/extra/yassl/testsuite/cipher-test.sh index 5ce29459d07..d3e69146097 100644 --- a/extra/yassl/testsuite/cipher-test.sh +++ b/extra/yassl/testsuite/cipher-test.sh @@ -4,6 +4,7 @@ # +no_pid=-1 server_pid=$no_pid From e7ff2040d7af2dec681bbfab5bc2a8232e53c50d Mon Sep 17 00:00:00 2001 From: Robert Golebiowski Date: Wed, 8 Jul 2015 12:21:51 +0200 Subject: [PATCH 11/37] Bug #21025377 CAN'T CONNECT TO SSL ENABLED SERVER FIRST 30 SEC AFTER INITIAL STARTUP Description: By using mysql_ssl_rsa_setup to get SSL enabled server (after running mysqld --initialize) server don't answer properly to "mysqladmin ping" first 30 secs after startup. Bug-fix: YASSL validated certificate date to the minute but should have to the second. This is why the ssl on the server side was not up right away after new certs were created with mysql_ssl_rsa_setup. The fix for that was submitted by Todd. YASSL was updated to 2.3.7c. --- extra/yassl/README | 5 +++++ extra/yassl/include/openssl/ssl.h | 2 +- extra/yassl/taocrypt/src/asn.cpp | 7 ++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/extra/yassl/README b/extra/yassl/README index d245d20ce5f..61326bc079a 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -12,6 +12,11 @@ before calling SSL_new(); *** end Note *** +yaSSL Patch notes, version 2.3.7c (6/12/2015) + This release of yaSSL does certificate DATE comparisons to the second + instead of to the minute, helpful when using freshly generated certs. + Though keep in mind that time sync differences could still show up. + yaSSL Patch notes, version 2.3.7b (3/18/2015) This release of yaSSL fixes a potential crash with corrupted private keys. Also detects bad keys earlier for user. diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index e10fb5299f7..5818a3b2cfc 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -35,7 +35,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.3.7b" +#define YASSL_VERSION "2.3.7c" #if defined(__cplusplus) diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index d521088d74a..342255c91b8 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -39,7 +39,7 @@ namespace TaoCrypt { namespace { // locals -// to the minute +// to the second bool operator>(tm& a, tm& b) { if (a.tm_year > b.tm_year) @@ -60,6 +60,11 @@ bool operator>(tm& a, tm& b) a.tm_min > b.tm_min) return true; + if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && + a.tm_mday == b.tm_mday && a.tm_hour == b.tm_hour && + a.tm_min == b.tm_min && a.tm_sec > b.tm_sec) + return true; + return false; } From 7255ae6ceb20c67d09fd153558d9a14372142f8b Mon Sep 17 00:00:00 2001 From: Robert Golebiowski Date: Wed, 8 Jul 2015 13:51:06 +0200 Subject: [PATCH 12/37] Bug #20774956: THREAD_POOL.THREAD_POOL_CONNECT HANGS WHEN RUN ON A YASSL-COMPILED SERVER/CLIENT Description: thread_pool.thread_pool_connect hangs when the server and client are compiled with yaSSL. Bug-fix: Test thread_pool.thread_pool_connect was temporary disabled for yaSSL. However, now that yaSSL is fixed it runs OK. The bug was introduced by one of the yaSSL updates. set_current was not working for i == 0. Now this is fixed. YASSL is updated to 2.3.7d --- extra/yassl/README | 5 +++++ extra/yassl/include/openssl/ssl.h | 2 +- extra/yassl/src/buffer.cpp | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/extra/yassl/README b/extra/yassl/README index 61326bc079a..2560c09addd 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -12,6 +12,11 @@ before calling SSL_new(); *** end Note *** +yaSSL Patch notes, version 2.3.7d (6/22/2015) + This release of yaSSL includes a fix for input_buffer set_current with + index 0. SSL_peek() at front of waiting data could trigger. Robert + Golebiowski of Oracle identified and suggested a fix, thanks! + yaSSL Patch notes, version 2.3.7c (6/12/2015) This release of yaSSL does certificate DATE comparisons to the second instead of to the minute, helpful when using freshly generated certs. diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 5818a3b2cfc..692d8b270d2 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -35,7 +35,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.3.7c" +#define YASSL_VERSION "2.3.7d" #if defined(__cplusplus) diff --git a/extra/yassl/src/buffer.cpp b/extra/yassl/src/buffer.cpp index aa7224bf64e..ce00a474e49 100644 --- a/extra/yassl/src/buffer.cpp +++ b/extra/yassl/src/buffer.cpp @@ -162,7 +162,7 @@ void input_buffer::set_error() void input_buffer::set_current(uint i) { - if (error_ == 0 && i && check(i - 1, size_) == 0) + if (error_ == 0 && check(i ? i - 1 : 0, size_) == 0) current_ = i; else error_ = -1; From 33a2e5abd86727155b629246445d508bb2cd02c0 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Fri, 10 Jul 2015 07:52:00 +0530 Subject: [PATCH 13/37] Bug #20238729: ILLEGALLY CRAFTED UTF8 SELECT PROVIDES NO WARNINGS Backporting to 5.1 and 5.5 --- .../r/strings_charsets_update_delete.result | Bin 112951 -> 113476 bytes .../r/character_set_connection_func.result | 6 ++ sql/item.cc | 63 ++++++++++------ sql/item.h | 9 ++- sql/item_strfunc.cc | 10 ++- sql/sql_class.cc | 38 +++++----- sql/sql_string.cc | 68 +++++++++++++++++- sql/sql_string.h | 6 +- sql/sql_yacc.yy | 10 ++- 9 files changed, 164 insertions(+), 46 deletions(-) diff --git a/mysql-test/suite/engines/iuds/r/strings_charsets_update_delete.result b/mysql-test/suite/engines/iuds/r/strings_charsets_update_delete.result index 08eecb1c17d52648b61184c98cfc97174e7be5cb..b862e23e3d3db65ab2a2b4cf3a614cc4a7698581 100644 GIT binary patch delta 594 zcmdn~iS5WYwhf!DvcnUL@-p+%i>charset(); - int well_formed_error; - uint wlen= cs->cset->well_formed_len(cs, - str->ptr(), str->ptr() + str->length(), - str->length(), &well_formed_error); - if (wlen < str->length()) + + size_t valid_length; + bool length_error; + + if (validate_string(cs, str->ptr(), str->length(), + &valid_length, &length_error)) { + const char *str_end= str->ptr() + str->length(); + const char *print_byte= str->ptr() + valid_length; THD *thd= current_thd; char hexbuf[7]; - enum MYSQL_ERROR::enum_warning_level level; - uint diff= str->length() - wlen; + enum MYSQL_ERROR::enum_warning_level level= MYSQL_ERROR::WARN_LEVEL_WARN; + uint diff= str_end - print_byte; set_if_smaller(diff, 3); - octet2hex(hexbuf, str->ptr() + wlen, diff); - if (send_error) + octet2hex(hexbuf, print_byte, diff); + if (send_error && length_error) { my_error(ER_INVALID_CHARACTER_STRING, MYF(0), cs->csname, hexbuf); return 0; } - if ((thd->variables.sql_mode & - (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + if (truncate && length_error) { - level= MYSQL_ERROR::WARN_LEVEL_ERROR; - null_value= 1; - str= 0; - } - else - { - level= MYSQL_ERROR::WARN_LEVEL_WARN; - str->length(wlen); + if ((thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + level= MYSQL_ERROR::WARN_LEVEL_ERROR; + null_value= 1; + str= 0; + } + else + { + str->length(valid_length); + } } push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); diff --git a/sql/item.h b/sql/item.h index c82d23b6d5a..15fe7ce5afa 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1052,7 +1052,9 @@ public: bool is_datetime(); virtual Field::geometry_type get_geometry_type() const { return Field::GEOM_GEOMETRY; }; - String *check_well_formed_result(String *str, bool send_error= 0); + String *check_well_formed_result(String *str, + bool send_error, + bool truncate); bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs); /** @@ -1929,6 +1931,11 @@ public: decimals=NOT_FIXED_DEC; // it is constant => can be used without fix_fields (and frequently used) fixed= 1; + /* + Check if the string has any character that can't be + interpreted using the relevant charset. + */ + check_well_formed_result(&str_value, false, false); } /* Just create an item and do not fill string representation */ Item_string(CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 25473815b9c..5e6da3b1300 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -2373,7 +2373,9 @@ String *Item_func_char::val_str(String *str) } } str->realloc(str->length()); // Add end 0 (for Purify) - return check_well_formed_result(str); + return check_well_formed_result(str, + false, // send warning + true); // truncate } @@ -2773,7 +2775,9 @@ String *Item_func_conv_charset::val_str(String *str) } null_value= tmp_value.copy(arg->ptr(), arg->length(), arg->charset(), conv_charset, &dummy_errors); - return null_value ? 0 : check_well_formed_result(&tmp_value); + return null_value ? 0 : check_well_formed_result(&tmp_value, + false, // send warning + true); // truncate } void Item_func_conv_charset::fix_length_and_dec() diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d71da6403ae..39d6316a512 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -1313,21 +1313,17 @@ LEX_STRING *THD::make_lex_string(LEX_STRING *lex_str, /* Convert a string to another character set - SYNOPSIS - convert_string() - to Store new allocated string here - to_cs New character set for allocated string - from String to convert - from_length Length of string to convert - from_cs Original character set + @param to Store new allocated string here + @param to_cs New character set for allocated string + @param from String to convert + @param from_length Length of string to convert + @param from_cs Original character set - NOTES - to will be 0-terminated to make it easy to pass to system funcs + @note to will be 0-terminated to make it easy to pass to system funcs - RETURN - 0 ok - 1 End of memory. - In this case to->str will point to 0 and to->length will be 0. + @retval false ok + @retval true End of memory. + In this case to->str will point to 0 and to->length will be 0. */ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs, @@ -1336,15 +1332,25 @@ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs, { DBUG_ENTER("convert_string"); size_t new_length= to_cs->mbmaxlen * from_length; - uint dummy_errors; + uint errors= 0; if (!(to->str= (char*) alloc(new_length+1))) { to->length= 0; // Safety fix DBUG_RETURN(1); // EOM } to->length= copy_and_convert((char*) to->str, new_length, to_cs, - from, from_length, from_cs, &dummy_errors); + from, from_length, from_cs, &errors); to->str[to->length]=0; // Safety + if (errors != 0) + { + char printable_buff[32]; + convert_to_printable(printable_buff, sizeof(printable_buff), + from, from_length, from_cs, 6); + push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "Can't convert the character string from %s to %s: '%.64s'", + from_cs->csname, to_cs->csname, printable_buff); + } + DBUG_RETURN(0); } diff --git a/sql/sql_string.cc b/sql/sql_string.cc index f692014011c..511bf3c9547 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -1231,3 +1231,69 @@ uint convert_to_printable(char *to, size_t to_len, *t= '\0'; return t - to; } + +/** + Check if an input byte sequence is a valid character string of a given charset + + @param cs The input character set. + @param str The input byte sequence to validate. + @param length A byte length of the str. + @param [out] valid_length A byte length of a valid prefix of the str. + @param [out] length_error True in the case of a character length error: + some byte[s] in the input is not a valid + prefix for a character, i.e. the byte length + of that invalid character is undefined. + + @retval true if the whole input byte sequence is a valid character string. + The length_error output parameter is undefined. + + @return + if the whole input byte sequence is a valid character string + then + return false + else + if the length of some character in the input is undefined (MY_CS_ILSEQ) + or the last character is truncated (MY_CS_TOOSMALL) + then + *length_error= true; // fatal error! + else + *length_error= false; // non-fatal error: there is no wide character + // encoding for some input character + return true +*/ +bool validate_string(CHARSET_INFO *cs, const char *str, uint32 length, + size_t *valid_length, bool *length_error) +{ + if (cs->mbmaxlen > 1) + { + int well_formed_error; + *valid_length= cs->cset->well_formed_len(cs, str, str + length, + length, &well_formed_error); + *length_error= well_formed_error; + return well_formed_error; + } + + /* + well_formed_len() is not functional on single-byte character sets, + so use mb_wc() instead: + */ + *length_error= false; + + const uchar *from= reinterpret_cast(str); + const uchar *from_end= from + length; + my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc; + + while (from < from_end) + { + my_wc_t wc; + int cnvres= (*mb_wc)(cs, &wc, (uchar*) from, from_end); + if (cnvres <= 0) + { + *valid_length= from - reinterpret_cast(str); + return true; + } + from+= cnvres; + } + *valid_length= length; + return false; +} diff --git a/sql/sql_string.h b/sql/sql_string.h index c65560dd1d1..e06180b108f 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -413,3 +413,7 @@ static inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str, { return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end; } + +bool +validate_string(CHARSET_INFO *cs, const char *str, uint32 length, + size_t *valid_length, bool *length_error); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 29516d34855..d9a32f2dd35 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -11070,7 +11070,9 @@ literal: str ? str->length() : 0, $1); if (!item_str || - !item_str->check_well_formed_result(&item_str->str_value, TRUE)) + !item_str->check_well_formed_result(&item_str->str_value, + true, //send error + true)) //truncate { MYSQL_YYABORT; } @@ -11099,7 +11101,9 @@ literal: str ? str->length() : 0, $1); if (!item_str || - !item_str->check_well_formed_result(&item_str->str_value, TRUE)) + !item_str->check_well_formed_result(&item_str->str_value, + true, //send error + true)) //truncate { MYSQL_YYABORT; } From 49667f044197cefdb7c90b8beab3e78ec23deecd Mon Sep 17 00:00:00 2001 From: Christopher Powers Date: Fri, 10 Jul 2015 20:42:33 +0200 Subject: [PATCH 14/37] Bug#21374104 SETUP_TIMERS INITIALIZATION ASSUMES CYCLE TIMER IS ALWAYS AVAILABLE For WAIT events, fall back to other timers if CYCLE is not available. --- .../suite/perfschema/r/query_cache.result | 4 +- .../suite/perfschema/t/query_cache.test | 2 + storage/perfschema/pfs_timer.cc | 43 ++++++++++++++++++- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/perfschema/r/query_cache.result b/mysql-test/suite/perfschema/r/query_cache.result index 8786cd055ca..837c2573a72 100644 --- a/mysql-test/suite/perfschema/r/query_cache.result +++ b/mysql-test/suite/perfschema/r/query_cache.result @@ -38,7 +38,7 @@ spins NULL select * from performance_schema.setup_timers where name='wait'; NAME TIMER_NAME -wait CYCLE +wait {CYCLE_OR_NANOSECOND} show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 1 @@ -53,7 +53,7 @@ spins NULL select * from performance_schema.setup_timers where name='wait'; NAME TIMER_NAME -wait CYCLE +wait {CYCLE_OR_NANOSECOND} show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 1 diff --git a/mysql-test/suite/perfschema/t/query_cache.test b/mysql-test/suite/perfschema/t/query_cache.test index 60d4a648222..802e574f89b 100644 --- a/mysql-test/suite/perfschema/t/query_cache.test +++ b/mysql-test/suite/perfschema/t/query_cache.test @@ -34,6 +34,7 @@ show status like "Qcache_hits"; select spins from performance_schema.events_waits_current order by event_name limit 1; +--replace_result CYCLE {CYCLE_OR_NANOSECOND} NANOSECOND {CYCLE_OR_NANOSECOND} select * from performance_schema.setup_timers where name='wait'; show status like "Qcache_queries_in_cache"; @@ -42,6 +43,7 @@ show status like "Qcache_hits"; select spins from performance_schema.events_waits_current order by event_name limit 1; +--replace_result CYCLE {CYCLE_OR_NANOSECOND} NANOSECOND {CYCLE_OR_NANOSECOND} select * from performance_schema.setup_timers where name='wait'; show status like "Qcache_queries_in_cache"; diff --git a/storage/perfschema/pfs_timer.cc b/storage/perfschema/pfs_timer.cc index 302548c97c2..3191a0514e7 100644 --- a/storage/perfschema/pfs_timer.cc +++ b/storage/perfschema/pfs_timer.cc @@ -1,5 +1,4 @@ -/* Copyright (c) 2008 MySQL AB, 2010 Sun Microsystems, Inc. - Use is subject to license terms. +/* Copyright (c) 2008, 2015, 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 @@ -89,6 +88,46 @@ void init_timers(void) (double)pfs_timer_info.ticks.frequency); else tick_to_pico= 0; + + /* + Depending on the platform and build options, some timers may not be + available. Pick best replacements. + */ + + /* + For WAIT, the cycle timer is used by default. However, it is not available + on all architectures. Fall back to the nanosecond timer in this case. It is + unlikely that neither cycle nor nanosecond are available, but we continue + probing less resolution timers anyway for consistency with other events. + */ + if (cycle_to_pico != 0) + { + /* Normal case. */ + wait_timer= TIMER_NAME_CYCLE; + } + else if (nanosec_to_pico != 0) + { + /* Robustness, no known cases. */ + wait_timer= TIMER_NAME_NANOSEC; + } + else if (microsec_to_pico != 0) + { + /* Robustness, no known cases. */ + wait_timer= TIMER_NAME_MICROSEC; + } + else if (millisec_to_pico != 0) + { + /* Robustness, no known cases. */ + wait_timer= TIMER_NAME_MILLISEC; + } + else + { + /* + Will never be reached on any architecture, but must provide a default if + no other timers are available. + */ + wait_timer= TIMER_NAME_TICK; + } } ulonglong get_timer_value(enum_timer_name timer_name) From 6fb2cdbc74c85f266d5d60a8e6194dec1f9c36a3 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Mon, 13 Jul 2015 07:51:23 +0530 Subject: [PATCH 15/37] Bug #20777016: DELETE CHECKS PRIVILEGES ON THE WRONG DATABASE WHEN USING TABLE ALIASES Issue: ----- When using table aliases for deleting, MySQL checks privileges against the current database and not the privileges on the actual table or database the table resides. SOLUTION: --------- While checking privileges for multi-deletes, correspondent_table should be used since it points to the correct table and database. --- sql/sql_acl.cc | 43 +++++++++++++++++++++++-------------------- sql/sql_parse.cc | 29 ++++++++++++++++------------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e8edd790f39..fea1a209c20 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -4612,16 +4612,19 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, tl && number-- && tl != first_not_own_table; tl= tl->next_global) { - sctx = test(tl->security_ctx) ? tl->security_ctx : thd->security_ctx; + TABLE_LIST *const t_ref= + tl->correspondent_table ? tl->correspondent_table : tl; + sctx = test(t_ref->security_ctx) ? t_ref->security_ctx : + thd->security_ctx; const ACL_internal_table_access *access= - get_cached_table_access(&tl->grant.m_internal, - tl->get_db_name(), - tl->get_table_name()); + get_cached_table_access(&t_ref->grant.m_internal, + t_ref->get_db_name(), + t_ref->get_table_name()); if (access) { - switch(access->check(orig_want_access, &tl->grant.privilege)) + switch(access->check(orig_want_access, &t_ref->grant.privilege)) { case ACL_INTERNAL_ACCESS_GRANTED: /* @@ -4645,34 +4648,34 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, if (!want_access) continue; // ok - if (!(~tl->grant.privilege & want_access) || - tl->is_anonymous_derived_table() || tl->schema_table) + if (!(~t_ref->grant.privilege & want_access) || + t_ref->is_anonymous_derived_table() || t_ref->schema_table) { /* - It is subquery in the FROM clause. VIEW set tl->derived after + It is subquery in the FROM clause. VIEW set t_ref->derived after table opening, but this function always called before table opening. */ - if (!tl->referencing_view) + if (!t_ref->referencing_view) { /* If it's a temporary table created for a subquery in the FROM clause, or an INFORMATION_SCHEMA table, drop the request for a privilege. */ - tl->grant.want_privilege= 0; + t_ref->grant.want_privilege= 0; } continue; } GRANT_TABLE *grant_table= table_hash_search(sctx->get_host()->ptr(), sctx->get_ip()->ptr(), - tl->get_db_name(), + t_ref->get_db_name(), sctx->priv_user, - tl->get_table_name(), + t_ref->get_table_name(), FALSE); if (!grant_table) { - want_access &= ~tl->grant.privilege; + want_access &= ~t_ref->grant.privilege; goto err; // No grants } @@ -4683,17 +4686,17 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, if (any_combination_will_do) continue; - tl->grant.grant_table= grant_table; // Remember for column test - tl->grant.version= grant_version; - tl->grant.privilege|= grant_table->privs; - tl->grant.want_privilege= ((want_access & COL_ACLS) & ~tl->grant.privilege); + t_ref->grant.grant_table= grant_table; // Remember for column test + t_ref->grant.version= grant_version; + t_ref->grant.privilege|= grant_table->privs; + t_ref->grant.want_privilege= ((want_access & COL_ACLS) & ~t_ref->grant.privilege); - if (!(~tl->grant.privilege & want_access)) + if (!(~t_ref->grant.privilege & want_access)) continue; - if (want_access & ~(grant_table->cols | tl->grant.privilege)) + if (want_access & ~(grant_table->cols | t_ref->grant.privilege)) { - want_access &= ~(grant_table->cols | tl->grant.privilege); + want_access &= ~(grant_table->cols | t_ref->grant.privilege); goto err; // impossible } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e1fc26775a4..fd3623c6148 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5069,9 +5069,12 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, for (; i < number && tables != first_not_own_table && tables; tables= tables->next_global, i++) { + TABLE_LIST *const table_ref= tables->correspondent_table ? + tables->correspondent_table : tables; + ulong want_access= requirements; - if (tables->security_ctx) - sctx= tables->security_ctx; + if (table_ref->security_ctx) + sctx= table_ref->security_ctx; else sctx= backup_ctx; @@ -5079,26 +5082,26 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, Register access for view underlying table. Remove SHOW_VIEW_ACL, because it will be checked during making view */ - tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); + table_ref->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); - if (tables->schema_table_reformed) + if (table_ref->schema_table_reformed) { - if (check_show_access(thd, tables)) + if (check_show_access(thd, table_ref)) goto deny; continue; } - DBUG_PRINT("info", ("derived: %d view: %d", tables->derived != 0, - tables->view != 0)); - if (tables->is_anonymous_derived_table() || - (tables->table && tables->table->s && - (int)tables->table->s->tmp_table)) + DBUG_PRINT("info", ("derived: %d view: %d", table_ref->derived != 0, + table_ref->view != 0)); + if (table_ref->is_anonymous_derived_table() || + (table_ref->table && table_ref->table->s && + (int)table_ref->table->s->tmp_table)) continue; thd->security_ctx= sctx; - if (check_access(thd, want_access, tables->get_db_name(), - &tables->grant.privilege, - &tables->grant.m_internal, + if (check_access(thd, want_access, table_ref->get_db_name(), + &table_ref->grant.privilege, + &table_ref->grant.m_internal, 0, no_errors)) goto deny; } From 067ae38c0aea426219edb11bd188c0798e6a8395 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Mon, 13 Jul 2015 10:10:12 +0200 Subject: [PATCH 16/37] Bug #20168526 YASSL: CORRUPT SSL-KEY CRASHES CLIENT Post-push fix: broken build on windows. The problem is min/max macros from windows.h which interfere with a template function callex max. Solution: ADD_DEFINITIONS(-DNOMINMAX) --- cmake/os/Windows.cmake | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake index 54ea3cf95f9..98158ca806b 100644 --- a/cmake/os/Windows.cmake +++ b/cmake/os/Windows.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2015, 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 @@ -50,10 +50,12 @@ IF(CMAKE_C_COMPILER MATCHES "icl") SET(MSVC TRUE) ENDIF() -ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE") -ADD_DEFINITIONS("-D_WIN32_WINNT=0x0501") +ADD_DEFINITIONS(-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE) +ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) +# We do not want the windows.h macros min/max +ADD_DEFINITIONS(-DNOMINMAX) # Speed up build process excluding unused header files -ADD_DEFINITIONS("-DWIN32_LEAN_AND_MEAN") +ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN) # Adjust compiler and linker flags IF(MINGW AND CMAKE_SIZEOF_VOID_P EQUAL 4) From e57e1b235ea0d0cc2e43017ebdccac34db369200 Mon Sep 17 00:00:00 2001 From: "mysql-builder@oracle.com" <> Date: Tue, 14 Jul 2015 07:37:37 +0530 Subject: [PATCH 17/37] From 888fabd6909237f55ed9b9cf7a0c852c2e5f0beb Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Thu, 16 Jul 2015 07:56:39 +0530 Subject: [PATCH 18/37] Bug #21143080: UPDATE ON VARCHAR AND TEXT COLUMNS PRODUCE INCORRECT RESULTS Issue: ----- Updating varchar and text fields in the same update statement can produce incorrect results. When a varchar field is assigned to the text field and the varchar field is then set to a different value, the text field's result contains the varchar field's new value. SOLUTION: --------- Currently the blob type does not allocate space for the string to be stored. Instead it contains a pointer to the varchar string. So when the varchar field is changed as part of the update statement, the value contained in the blob also changes. The fix would be to actually store the value by allocating space for the blob's string. We can avoid allocating this space when the varchar field is not being written into. --- mysql-test/r/update.result | 13 +++++++++++++ mysql-test/t/update.test | 13 +++++++++++++ sql/field.h | 18 +++++++++++++++++- sql/field_conv.cc | 13 ++++--------- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 54170ae3dad..d15130d1254 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -551,3 +551,16 @@ ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function DROP VIEW v1; DROP FUNCTION f1; DROP TABLE t1; +# Bug #21143080: UPDATE ON VARCHAR AND TEXT COLUMNS PRODUCE INCORRECT +# RESULTS +CREATE TABLE t1 (a VARCHAR(50), b TEXT, c CHAR(50)) ENGINE=INNODB; +INSERT INTO t1 (a, b, c) VALUES ('start trail', '', 'even longer string'); +UPDATE t1 SET b = a, a = 'inject'; +SELECT a, b FROM t1; +a b +inject start trail +UPDATE t1 SET b = c, c = 'inject'; +SELECT c, b FROM t1; +c b +inject even longer string +DROP TABLE t1; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index c515f8873d8..14e08bd9b8b 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -503,3 +503,16 @@ UPDATE v1 SET pk = 7 WHERE pk > 0; DROP VIEW v1; DROP FUNCTION f1; DROP TABLE t1; + +--echo # Bug #21143080: UPDATE ON VARCHAR AND TEXT COLUMNS PRODUCE INCORRECT +--echo # RESULTS + +CREATE TABLE t1 (a VARCHAR(50), b TEXT, c CHAR(50)) ENGINE=INNODB; + +INSERT INTO t1 (a, b, c) VALUES ('start trail', '', 'even longer string'); +UPDATE t1 SET b = a, a = 'inject'; +SELECT a, b FROM t1; +UPDATE t1 SET b = c, c = 'inject'; +SELECT c, b FROM t1; + +DROP TABLE t1; diff --git a/sql/field.h b/sql/field.h index 6a181b7ae91..73922460037 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1,7 +1,7 @@ #ifndef FIELD_INCLUDED #define FIELD_INCLUDED -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2015, 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 @@ -511,6 +511,17 @@ public: } /* Hash value */ virtual void hash(ulong *nr, ulong *nr2); + +/** + Checks whether a string field is part of write_set. + + @return + FALSE - If field is not char/varchar/.... + - If field is char/varchar/.. and is not part of write set. + TRUE - If field is char/varchar/.. and is part of write set. +*/ + virtual bool is_updatable() const { return FALSE; } + friend int cre_myisam(char * name, register TABLE *form, uint options, ulonglong auto_increment_value); friend class Copy_field; @@ -798,6 +809,11 @@ public: int store_decimal(const my_decimal *d); uint32 max_data_length() const; + bool is_updatable() const + { + DBUG_ASSERT(table && table->write_set); + return bitmap_is_set(table->write_set, field_index); + } }; /* base class for float and double and decimal (old one) */ diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 17b0d34557a..14c4fd257fe 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2015, 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 @@ -800,15 +800,10 @@ int field_conv(Field *to,Field *from) { // Be sure the value is stored Field_blob *blob=(Field_blob*) to; from->val_str(&blob->value); - /* - Copy value if copy_blobs is set, or source is not a string and - we have a pointer to its internal string conversion buffer. - */ - if (to->table->copy_blobs || - (!blob->value.is_alloced() && - from->real_type() != MYSQL_TYPE_STRING && - from->real_type() != MYSQL_TYPE_VARCHAR)) + + if (!blob->value.is_alloced() && from->is_updatable()) blob->value.copy(); + return blob->store(blob->value.ptr(),blob->value.length(),from->charset()); } if (from->real_type() == MYSQL_TYPE_ENUM && From b5380e092c1cac3050a711c308136eee15c51826 Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Thu, 23 Jul 2015 10:47:58 +0530 Subject: [PATCH 19/37] BUG#19886430: VIEW CREATION WITH NAMED COLUMNS, OVER UNION, IS REJECTED. Analysis ======== View creation with named columns over UNION is rejected. Consider the following view definition: CREATE VIEW v1 (fld1, fld2) AS SELECT 1 AS a, 2 AS b UNION ALL SELECT 1 AS a, 1 AS a; A 'duplicate column' error was reported due to the duplicate alias name in the secondary SELECT. The VIEW column names are either explicitly specified or determined from the first SELECT (which can be auto generated if not specified). Since a duplicate column name check was performed even for the secondary SELECTs, an error was reported. Fix ==== Check for duplicate column names only for the named columns if specified or only for the first SELECT. --- mysql-test/r/view.result | 35 ++++++++++++++++++++++++++++++ mysql-test/t/view.test | 44 +++++++++++++++++++++++++++++++++++++ sql/sql_view.cc | 47 +++++++++------------------------------- 3 files changed, 89 insertions(+), 37 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index c31b4f5216b..a3adf80c096 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -4146,3 +4146,38 @@ SHOW CREATE VIEW v4; View Create View character_set_client collation_connection v4 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS (select 'BUG#14117018' AS `col1`) union all (select '' AS `col2`) union all (select '' AS `Name_exp_3`) latin1 latin1_swedish_ci DROP VIEW v1, v2, v3, v4; +# +# BUG#19886430: VIEW CREATION WITH NAMED COLUMNS, OVER UNION, +# IS REJECTED +# Without the patch, reports an error. +CREATE VIEW v1 (fld1, fld2) AS +SELECT 1 AS a, 2 AS b +UNION ALL +SELECT 1 AS a, 1 AS a; +# The column names are explicitly specified and not duplicates, hence +# succeeds. +CREATE VIEW v2 (fld1, fld2) AS +SELECT 1 AS a, 2 AS a +UNION ALL +SELECT 1 AS a, 1 AS a; +# The column name in the first SELECT are not duplicates, hence succeeds. +CREATE VIEW v3 AS +SELECT 1 AS a, 2 AS b +UNION ALL +SELECT 1 AS a, 1 AS a; +# Should report an error, since the explicitly specified column names are +# duplicates. +CREATE VIEW v4 (fld1, fld1) AS +SELECT 1 AS a, 2 AS b +UNION ALL +SELECT 1 AS a, 1 AS a; +ERROR 42S21: Duplicate column name 'fld1' +# Should report an error, since duplicate column name is specified in the +# First SELECT. +CREATE VIEW v4 AS +SELECT 1 AS a, 2 AS a +UNION ALL +SELECT 1 AS a, 1 AS a; +ERROR 42S21: Duplicate column name 'a' +# Cleanup +DROP VIEW v1, v2, v3; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 959153ee851..f9c305831c2 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -4184,6 +4184,50 @@ SHOW CREATE VIEW v4; DROP VIEW v1, v2, v3, v4; + +--echo # +--echo # BUG#19886430: VIEW CREATION WITH NAMED COLUMNS, OVER UNION, +--echo # IS REJECTED + +--echo # Without the patch, reports an error. +CREATE VIEW v1 (fld1, fld2) AS + SELECT 1 AS a, 2 AS b + UNION ALL + SELECT 1 AS a, 1 AS a; + +--echo # The column names are explicitly specified and not duplicates, hence +--echo # succeeds. +CREATE VIEW v2 (fld1, fld2) AS + SELECT 1 AS a, 2 AS a + UNION ALL + SELECT 1 AS a, 1 AS a; + +--echo # The column name in the first SELECT are not duplicates, hence succeeds. +CREATE VIEW v3 AS + SELECT 1 AS a, 2 AS b + UNION ALL + SELECT 1 AS a, 1 AS a; + +--echo # Should report an error, since the explicitly specified column names are +--echo # duplicates. +--error ER_DUP_FIELDNAME +CREATE VIEW v4 (fld1, fld1) AS + SELECT 1 AS a, 2 AS b + UNION ALL + SELECT 1 AS a, 1 AS a; + +--echo # Should report an error, since duplicate column name is specified in the +--echo # First SELECT. +--error ER_DUP_FIELDNAME +CREATE VIEW v4 AS + SELECT 1 AS a, 2 AS a + UNION ALL + SELECT 1 AS a, 1 AS a; + +--echo # Cleanup +DROP VIEW v1, v2, v3; + + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 6bbc475565b..18eb03da866 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2004, 2015, 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 @@ -164,18 +164,14 @@ err: possibly generate a conforming name for them if not. @param lex Lex for this thread. - - @retval false Operation was a success. - @retval true An error occurred. */ -static bool make_valid_column_names(LEX *lex) +static void make_valid_column_names(LEX *lex) { Item *item; uint name_len; char buff[NAME_LEN]; uint column_no= 1; - DBUG_ENTER("make_valid_column_names"); for (SELECT_LEX *sl= &lex->select_lex; sl; sl= sl->next_select()) { @@ -187,37 +183,7 @@ static bool make_valid_column_names(LEX *lex) item->orig_name= item->name; item->set_name(buff, name_len, system_charset_info); } - - /* - There is a possibility of generating same name for column in more than - one SELECT_LEX. For Example: - - CREATE TABLE t1 (Name_exp_1 INT, Name_exp_2 INT, Name_exp_3 INT); - CREATE TABLE t2 (Name_exp_1 INT, Name_exp_2 INT, Name_exp_3 INT); - - CREATE VIEW v1 AS SELECT '', t1.Name_exp_2 AS Name_exp_2 FROM t1 - UNION - SELECT '', t2.Name_exp_1 AS Name_exp_1 from t2; - - But, column names of the first SELECT_LEX is considered - for the output. - - mysql> SELECT * FROM v1; - +------------+------------+ - | Name_exp_1 | Name_exp_2 | - +------------+------------+ - | | 2 | - | | 3 | - +------------+------------+ - - So, checking for duplicate names in only "sl", current - SELECT_LEX. - */ - if (check_duplicate_names(sl->item_list, 1)) - DBUG_RETURN(true); } - - DBUG_RETURN(false); } @@ -624,7 +590,14 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, } /* Check if the auto generated column names are conforming. */ - if (make_valid_column_names(lex)) + make_valid_column_names(lex); + + /* + Only column names of the first select_lex should be checked for + duplication; any further UNION-ed part isn't used for determining + names of the view's columns. + */ + if (check_duplicate_names(select_lex->item_list, 1)) { res= TRUE; goto err; From 641ab6f36813516255738ba25d3c6b721189832e Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 29 Jul 2015 18:24:20 +0530 Subject: [PATCH 20/37] Bug #20796566 ERROR: INSERT BUFFER INSERT FAIL CANNOT INSERT INDEX RECORD Problem: ======= IBUF_BITMAP_FREE bit in ibuf bitmap array is used to indicate the free space available in leaf page. IBUF_BITMAP_FREE bit indicates free space more than actual existing free space for the leaf page. Solution: ========= Ibuf_bitmap_array is not updated for the secondary index leaf page when insert operation is done by updating a delete marked existing record in the index. Reviewed-by: Jimmy Yang RB: 9544 --- storage/innodb_plugin/btr/btr0cur.c | 31 ++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c index 93b150341b0..3dfab4cb8da 100644 --- a/storage/innodb_plugin/btr/btr0cur.c +++ b/storage/innodb_plugin/btr/btr0cur.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -1894,6 +1894,7 @@ btr_cur_optimistic_update( ulint max_size; ulint new_rec_size; ulint old_rec_size; + ulint max_ins_size = 0; dtuple_t* new_entry; roll_ptr_t roll_ptr; mem_heap_t* heap; @@ -2004,6 +2005,11 @@ any_extern: : (old_rec_size + page_get_max_insert_size_after_reorganize(page, 1)); + if (!page_zip) { + max_ins_size = page_get_max_insert_size_after_reorganize( + page, 1); + } + if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT) && (max_size >= new_rec_size)) || (page_get_n_recs(page) <= 1))) { @@ -2053,10 +2059,14 @@ any_extern: rec = btr_cur_insert_if_possible(cursor, new_entry, 0/*n_ext*/, mtr); ut_a(rec); /* <- We calculated above the insert would fit */ - if (page_zip && !dict_index_is_clust(index) + if (!dict_index_is_clust(index) && page_is_leaf(page)) { /* Update the free bits in the insert buffer. */ - ibuf_update_free_bits_zip(block, mtr); + if (page_zip) { + ibuf_update_free_bits_zip(block, mtr); + } else { + ibuf_update_free_bits_low(block, max_ins_size, mtr); + } } /* Restore the old explicit lock state on the record */ @@ -2165,6 +2175,7 @@ btr_cur_pessimistic_update( ulint n_reserved; ulint n_ext; ulint* offsets = NULL; + ulint max_ins_size = 0; *big_rec = NULL; @@ -2302,6 +2313,11 @@ make_external: ut_ad(flags & BTR_KEEP_POS_FLAG); } + if (!page_zip) { + max_ins_size = page_get_max_insert_size_after_reorganize( + page, 1); + } + /* Store state of explicit locks on rec on the page infimum record, before deleting rec. The page infimum acts as a dummy carrier of the locks, taking care also of lock releases, before we can move the locks @@ -2347,10 +2363,15 @@ make_external: big_rec_vec != NULL && (flags & BTR_KEEP_POS_FLAG), mtr); - if (page_zip && !dict_index_is_clust(index) + if (!dict_index_is_clust(index) && page_is_leaf(page)) { /* Update the free bits in the insert buffer. */ - ibuf_update_free_bits_zip(block, mtr); + if (page_zip) { + ibuf_update_free_bits_zip(block, mtr); + } else { + ibuf_update_free_bits_low(block, max_ins_size, + mtr); + } } err = DB_SUCCESS; From 8006ad8053672cbaa07f7f0a3561e2c5044ff6b7 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Mon, 3 Aug 2015 08:15:59 +0530 Subject: [PATCH 21/37] Bug #20909518: HANDLE_FATAL_SIGNAL (SIG=11) IN FIND_USED_PARTITIONS | SQL/OPT_RANGE.CC:3884 Issue: ----- During partition pruning, first we identify the partition in which row can reside and then identify the subpartition. If we find a partition but not the subpartion then we hit a debug assert. While finding the subpartition we check the current thread's error status in part_val_int() function after some operation. In this case the thread's error status is already set to an error (multiple rows returned) so the function returns no partition found and results in incorrect behavior. SOLUTION: --------- Currently any error encountered in part_val_int is considered a "partition not found" type error. Instead of an assert, a check needs to be done and a valid error returned. --- sql/opt_range.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3adf27539a5..795f662f256 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2015, 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 @@ -3088,6 +3088,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) int partno= (int)key_tree->part; bool pushed= FALSE; bool set_full_part_if_bad_ret= FALSE; + RANGE_OPT_PARAM *range_par= &(ppar->range_param); if (key_tree->left != &null_element) { @@ -3142,10 +3143,19 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) key_tree->max_value, key_tree->min_flag | key_tree->max_flag, &subpart_iter); - DBUG_ASSERT(res); /* We can't get "no satisfying subpartitions" */ + if (res == 0) + { + /* + The only case where we can get "no satisfying subpartitions" + returned from the above call is when an error has occurred. + */ + DBUG_ASSERT(range_par->thd->is_error()); + return 0; + } + if (res == -1) return -1; /* all subpartitions satisfy */ - + uint32 subpart_id; bitmap_clear_all(&ppar->subparts_bitmap); while ((subpart_id= subpart_iter.get_next(&subpart_iter)) != From 9372c9ebd2d63f27bec2e203a4a9bda37ac4e2df Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Mon, 3 Aug 2015 10:08:46 +0530 Subject: [PATCH 22/37] Bug #20909518: HANDLE_FATAL_SIGNAL (SIG=11) IN FIND_USED_PARTITIONS | SQL/OPT_RANGE.CC:3884 Post-push fix. --- sql/opt_range.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 795f662f256..4b76fbd20a9 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3088,7 +3088,6 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) int partno= (int)key_tree->part; bool pushed= FALSE; bool set_full_part_if_bad_ret= FALSE; - RANGE_OPT_PARAM *range_par= &(ppar->range_param); if (key_tree->left != &null_element) { @@ -3149,7 +3148,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) The only case where we can get "no satisfying subpartitions" returned from the above call is when an error has occurred. */ - DBUG_ASSERT(range_par->thd->is_error()); + DBUG_ASSERT(ppar->range_param.thd->is_error()); return 0; } From c28626d0af640dddfb2c4d970f0ce4f6ec1776cc Mon Sep 17 00:00:00 2001 From: Mithun C Y Date: Tue, 4 Aug 2015 11:45:02 +0530 Subject: [PATCH 23/37] Bug #21096444: MYSQL IS TRYING TO PERFORM A CONSISTENT READ BUT THE READ VIEW IS NOT ASSIGNED! Issue: A select for update subquery in having clause resulted deadlock and its transaction was rolled back by innodb. val_XXX interfaces do not handle errors and it do not propogate errors to its caller. sub_select did not see this error when it called evaluate_join_record and later made a call to innodb. As transaction is rolled back innodb asserted. Fix: Now evaluate_join_record checks if there is any error reported and then return the same to its caller. --- sql/sql_select.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 21b84cbca54..8a83b907b2e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11598,6 +11598,11 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, rc= (*join_tab->next_select)(join, join_tab+1, 0); if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS) return rc; + + /* check for errors evaluating the condition */ + if (join->thd->is_error()) + return NESTED_LOOP_ERROR; + if (join->return_tab < join_tab) return NESTED_LOOP_OK; /* From 67be190c0b7a803684eaffca53063f31fa8e1ddc Mon Sep 17 00:00:00 2001 From: sayantan dutta Date: Tue, 18 Feb 2014 17:57:54 +0530 Subject: [PATCH 24/37] Follow up Fix: Bug #18145121 - DEPRECATED PERL SYNTAX IN MTR (cherry picked from commit 3eb933e0eb55f962404a04741767177e12a9885f) Conflicts: mysql-test/mysql-test-run.pl --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 02ff577c7bf..684d262f410 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -490,7 +490,7 @@ sub main { } } - if ( not defined @$completed ) { + if ( not $completed ) { mtr_error("Test suite aborted"); } From 1d317440d6be293f1a6f38bf72951eccac38be55 Mon Sep 17 00:00:00 2001 From: sayantan dutta Date: Mon, 24 Feb 2014 18:44:37 +0530 Subject: [PATCH 25/37] Follow-up fix : Bug #18145121 - DEPRECATED PERL SYNTAX IN MTR (cherry picked from commit 1bfe5f724bc4c24da635f632247e7d263aa53970) Conflicts: mysql-test/lib/mtr_cases.pm --- mysql-test/lib/mtr_cases.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index b3bc2a83b92..e8d24eb399f 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -1,5 +1,5 @@ # -*- cperl -*- -# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, 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 @@ -336,7 +336,7 @@ sub collect_one_suite($) # Build a hash of disabled testcases for this suite # ---------------------------------------------------------------------- my %disabled; - my @disabled_collection= @{$opt_skip_test_list} if defined @{$opt_skip_test_list}; + my @disabled_collection= @{$opt_skip_test_list} if $opt_skip_test_list; unshift (@disabled_collection, "$testdir/disabled.def"); for my $skip (@disabled_collection) { From f3dce250f45b3a02a30743b2c0928f8aaf132e88 Mon Sep 17 00:00:00 2001 From: Ajo Robert Date: Fri, 7 Aug 2015 16:26:10 +0530 Subject: [PATCH 26/37] Bug #20760261 mysqld crashed in materialized_cursor:: send_result_set_metadata Analysis -------- Cursor inside trigger accessing NEW/OLD row leads server exit. The reason for the bug was that implementation of function create_tmp_table() was not considering Item::TRIGGER_FIELD_ITEM as possible alternative for type of class being instantiated. This was resulting in a mismatch between a number of columns in result list and temp table definition. This mismatch leads to the failure of assertion DBUG_ASSERT(send_result_set_metadata.elements == item_list.elements) in the method Materialized_cursor::send_result_set_metadata in debug mode. Fix: --- Added code to consider Item::TRIGGER_FIELD_ITEM as valid type while creating fields. --- sql/sql_insert.cc | 55 ++++++++++++++++++++++++++++++++++------------- sql/sql_select.cc | 1 + 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a59e3fd14e9..1237521e68e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -3531,7 +3531,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, /* Add selected items to field list */ List_iterator_fast it(*items); Item *item; - Field *tmp_field; bool not_used; DBUG_ENTER("create_table_from_items"); @@ -3549,22 +3548,48 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, while ((item=it++)) { - Create_field *cr_field; - Field *field, *def_field; + Field *tmp_table_field; if (item->type() == Item::FUNC_ITEM) + { if (item->result_type() != STRING_RESULT) - field= item->tmp_table_field(&tmp_table); + tmp_table_field= item->tmp_table_field(&tmp_table); else - field= item->tmp_table_field_from_field_type(&tmp_table, 0); + tmp_table_field= item->tmp_table_field_from_field_type(&tmp_table, 0); + } else - field= create_tmp_field(thd, &tmp_table, item, item->type(), - (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0, - 0); - if (!field || - !(cr_field=new Create_field(field,(item->type() == Item::FIELD_ITEM ? - ((Item_field *)item)->field : - (Field*) 0)))) - DBUG_RETURN(0); + { + Field *from_field, *default_field; + tmp_table_field= create_tmp_field(thd, &tmp_table, item, item->type(), + (Item ***) 0, &from_field, &default_field, + 0, 0, 0, 0, 0); + } + + if (!tmp_table_field) + DBUG_RETURN(NULL); + + Field *table_field; + + switch (item->type()) + { + /* + We have to take into account both the real table's fields and + pseudo-fields used in trigger's body. These fields are used + to copy defaults values later inside constructor of + the class Create_field. + */ + case Item::FIELD_ITEM: + case Item::TRIGGER_FIELD_ITEM: + table_field= ((Item_field *) item)->field; + break; + default: + table_field= NULL; + } + + Create_field *cr_field= new Create_field(tmp_table_field, table_field); + + if (!cr_field) + DBUG_RETURN(NULL); + if (item->maybe_null) cr_field->flags &= ~NOT_NULL_FLAG; alter_info->create_list.push_back(cr_field); @@ -3639,7 +3664,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, } reenable_binlog(thd); if (!table) // open failed - DBUG_RETURN(0); + DBUG_RETURN(NULL); } DBUG_EXECUTE_IF("sleep_create_select_before_lock", my_sleep(6000000);); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8a83b907b2e..acf6efa5a13 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9820,6 +9820,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, } case Item::FIELD_ITEM: case Item::DEFAULT_VALUE_ITEM: + case Item::TRIGGER_FIELD_ITEM: { Item_field *field= (Item_field*) item; bool orig_modify= modify_item; From f59d68eeae37338d7b25f2571407e763fa897e15 Mon Sep 17 00:00:00 2001 From: Shaohua Wang Date: Mon, 10 Aug 2015 16:31:05 +0800 Subject: [PATCH 27/37] BUG#21102971 data corruption on arm64 The root cause is that x86 has a stronger memory model than the ARM processors. And the GCC builtins didn't issue the correct fences when setting/unsetting the lock word. In particular during the mutex release. The solution is rewriting atomic TAS operations: replace '__sync_' by '__atomic_' if possible. Reviewed-by: Sunny Bains Reviewed-by: Bin Su Reviewed-by: Debarun Banerjee Reviewed-by: Krunal Bauskar RB: 9782 RB: 9665 RB: 9783 --- storage/innobase/CMakeLists.txt | 18 +++- storage/innobase/include/os0sync.h | 122 ++++++++++++++++++++++---- storage/innobase/include/sync0sync.h | 9 +- storage/innobase/include/sync0sync.ic | 9 +- 4 files changed, 128 insertions(+), 30 deletions(-) diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 4f000434eb9..a5fffac7ce1 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2015, 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 @@ -85,12 +85,28 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_BUILTINS ) + CHECK_C_SOURCE_RUNS( + "#include + int main() + { + unsigned char c; + + __atomic_test_and_set(&c, __ATOMIC_ACQUIRE); + __atomic_clear(&c, __ATOMIC_RELEASE); + return(0); + }" + HAVE_IB_GCC_ATOMIC_TEST_AND_SET + ) ENDIF() IF(HAVE_IB_GCC_ATOMIC_BUILTINS) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS=1) ENDIF() +IF(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) + ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_TEST_AND_SET=1) +ENDIF() + # either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not IF(NOT CMAKE_CROSSCOMPILING) CHECK_C_SOURCE_RUNS( diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index c6672aa73b6..07628409192 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -37,6 +37,20 @@ Created 9/6/1995 Heikki Tuuri #include "univ.i" #include "ut0lst.h" +#if defined __i386__ || defined __x86_64__ || defined _M_IX86 \ + || defined _M_X64 || defined __WIN__ + +#define IB_STRONG_MEMORY_MODEL + +#endif /* __i386__ || __x86_64__ || _M_IX86 || M_X64 || __WIN__ */ + +#ifdef HAVE_WINDOWS_ATOMICS +typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates + on LONG variable */ +#else +typedef byte lock_word_t; +#endif + #ifdef __WIN__ /** Native event (slow)*/ typedef HANDLE os_native_event_t; @@ -304,11 +318,61 @@ amount of increment. */ # define os_atomic_increment_ulint(ptr, amount) \ os_atomic_increment(ptr, amount) -/**********************************************************//** -Returns the old value of *ptr, atomically sets *ptr to new_val */ +# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) -# define os_atomic_test_and_set_byte(ptr, new_val) \ - __sync_lock_test_and_set(ptr, (byte) new_val) +/** Do an atomic test-and-set. +@param[in,out] ptr Memory location to set to non-zero +@return the previous value */ +static inline +lock_word_t +os_atomic_test_and_set(volatile lock_word_t* ptr) +{ + return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); +} + +/** Do an atomic clear. +@param[in,out] ptr Memory location to set to zero */ +static inline +void +os_atomic_clear(volatile lock_word_t* ptr) +{ + __atomic_clear(ptr, __ATOMIC_RELEASE); +} + +# elif defined(IB_STRONG_MEMORY_MODEL) + +/** Do an atomic test and set. +@param[in,out] ptr Memory location to set to non-zero +@return the previous value */ +static inline +lock_word_t +os_atomic_test_and_set(volatile lock_word_t* ptr) +{ + return(__sync_lock_test_and_set(ptr, 1)); +} + +/** Do an atomic release. + +In theory __sync_lock_release should be used to release the lock. +Unfortunately, it does not work properly alone. The workaround is +that more conservative __sync_lock_test_and_set is used instead. + +Performance regression was observed at some conditions for Intel +architecture. Disable release barrier on Intel architecture for now. +@param[in,out] ptr Memory location to write to +@return the previous value */ +static inline +lock_word_t +os_atomic_clear(volatile lock_word_t* ptr) +{ + return(__sync_lock_test_and_set(ptr, 0)); +} + +# else + +# error "Unsupported platform" + +# endif /* HAVE_IB_GCC_ATOMIC_TEST_AND_SET */ #elif defined(HAVE_IB_SOLARIS_ATOMICS) @@ -357,11 +421,25 @@ amount of increment. */ # define os_atomic_increment_ulint(ptr, amount) \ atomic_add_long_nv(ptr, amount) -/**********************************************************//** -Returns the old value of *ptr, atomically sets *ptr to new_val */ +/** Do an atomic xchg and set to non-zero. +@param[in,out] ptr Memory location to set to non-zero +@return the previous value */ +static inline +lock_word_t +os_atomic_test_and_set(volatile lock_word_t* ptr) +{ + return(atomic_swap_uchar(ptr, 1)); +} -# define os_atomic_test_and_set_byte(ptr, new_val) \ - atomic_swap_uchar(ptr, new_val) +/** Do an atomic xchg and set to zero. +@param[in,out] ptr Memory location to set to zero +@return the previous value */ +static inline +lock_word_t +os_atomic_clear(volatile lock_word_t* ptr) +{ + return(atomic_swap_uchar(ptr, 0)); +} #elif defined(HAVE_WINDOWS_ATOMICS) @@ -403,13 +481,27 @@ amount of increment. */ # define os_atomic_increment_ulint(ptr, amount) \ ((ulint) (win_xchg_and_add(ptr, amount) + amount)) -/**********************************************************//** -Returns the old value of *ptr, atomically sets *ptr to new_val. -InterlockedExchange() operates on LONG, and the LONG will be -clobbered */ +/** Do an atomic test and set. +InterlockedExchange() operates on LONG, and the LONG will be clobbered +@param[in,out] ptr Memory location to set to non-zero +@return the previous value */ +static inline +lock_word_t +os_atomic_test_and_set(volatile lock_word_t* ptr) +{ + return(InterlockedExchange(ptr, 1)); +} -# define os_atomic_test_and_set_byte(ptr, new_val) \ - ((byte) InterlockedExchange(ptr, new_val)) +/** Do an atomic release. +InterlockedExchange() operates on LONG, and the LONG will be clobbered +@param[in,out] ptr Memory location to set to zero +@return the previous value */ +static inline +lock_word_t +os_atomic_clear(volatile lock_word_t* ptr) +{ + return(InterlockedExchange(ptr, 0)); +} #else # define IB_ATOMICS_STARTUP_MSG \ diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index 9b07c4758c9..b50735f4ad0 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -45,13 +45,6 @@ Created 9/5/1995 Heikki Tuuri extern my_bool timed_mutexes; #endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ -#ifdef HAVE_WINDOWS_ATOMICS -typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates - on LONG variable */ -#else -typedef byte lock_word_t; -#endif - #if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK /* There are mutexes/rwlocks that we want to exclude from instrumentation even if their corresponding performance schema diff --git a/storage/innobase/include/sync0sync.ic b/storage/innobase/include/sync0sync.ic index 6958faa5c6f..bd2df4488b4 100644 --- a/storage/innobase/include/sync0sync.ic +++ b/storage/innobase/include/sync0sync.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -80,7 +80,7 @@ mutex_test_and_set( mutex_t* mutex) /*!< in: mutex */ { #if defined(HAVE_ATOMIC_BUILTINS) - return(os_atomic_test_and_set_byte(&mutex->lock_word, 1)); + return(os_atomic_test_and_set(&mutex->lock_word)); #else ibool ret; @@ -108,10 +108,7 @@ mutex_reset_lock_word( mutex_t* mutex) /*!< in: mutex */ { #if defined(HAVE_ATOMIC_BUILTINS) - /* In theory __sync_lock_release should be used to release the lock. - Unfortunately, it does not work properly alone. The workaround is - that more conservative __sync_lock_test_and_set is used instead. */ - os_atomic_test_and_set_byte(&mutex->lock_word, 0); + os_atomic_clear(&mutex->lock_word); #else mutex->lock_word = 0; From 608efca4c4e4afa1ffea251abda675fcc06efc69 Mon Sep 17 00:00:00 2001 From: Aditya A Date: Wed, 12 Aug 2015 19:17:26 +0530 Subject: [PATCH 28/37] Bug #21025880 DUPLICATE UK VALUES IN READ-COMMITTED (AGAIN) PROBLEM Whenever we insert in unique secondary index we take shared locks on all possible duplicate record present in the table. But while during a replace on the unique secondary index , we take exclusive and locks on the all duplicate record. When the records are deleted, they are first delete marked and later purged by the purge thread. While purging the record we call the lock_update_delete() which in turn calls lock_rec_inherit_to_gap() to inherit locks of the deleted records. In repeatable read mode we inherit all the locks from the record to the next record but in the read commited mode we skip inherting them as gap type locks. We make a exception here if the lock on the records is in shared mode ,we assume that it is set during insert for unique secondary index and needs to be inherited to stop constraint violation. We didnt handle the case when exclusive locks are set during replace, we skip inheriting locks of these records and hence causing constraint violation. FIX While inheriting the locks,check whether the transaction is allowed to do TRX_DUP_REPLACE/TRX_DUP_IGNORE, if true inherit the locks. [ Revewied by Jimmy #rb9709] --- storage/innobase/lock/lock0lock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index e6ce07428e8..559b3687b79 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, 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 the Free Software @@ -2457,16 +2457,16 @@ lock_rec_inherit_to_gap( /* If srv_locks_unsafe_for_binlog is TRUE or session is using READ COMMITTED isolation level, we do not want locks set by an UPDATE or a DELETE to be inherited as gap type locks. But we - DO want S-locks set by a consistency constraint to be inherited also - then. */ + DO want S-locks/X-locks (taken for replace) set by a consistency + constraint to be inherited also then. */ while (lock != NULL) { if (!lock_rec_get_insert_intention(lock) && !((srv_locks_unsafe_for_binlog || lock->trx->isolation_level <= TRX_ISO_READ_COMMITTED) - && lock_get_mode(lock) == LOCK_X)) { - + && lock_get_mode(lock) == + (lock->trx->duplicates ? LOCK_S : LOCK_X))) { lock_rec_add_to_queue(LOCK_REC | LOCK_GAP | lock_get_mode(lock), heir_block, heir_heap_no, From 557a57f3a23c486fbe12b66306ab7adffd609677 Mon Sep 17 00:00:00 2001 From: Mithun C Y Date: Mon, 17 Aug 2015 15:23:47 +0530 Subject: [PATCH 29/37] Bug #21350175: SUBQUERIES IN PROCEDURE CLAUSE OF SELECT STATEMENT CAUSES SERVER FAILURES. Analysis : ========== During JOIN::prepare of sub-query which creates the derived tables we call setup_procedure. Here we call fix_fields for parameters of procedure clause. Calling setup_procedure at this point may cause issue. If sub-query is one of parameter being fixed it might lead to complicated dependencies on derived tables being prepared. SOLUTION : ========== In 5.6 with WL#6242, we have made procedure clause parameters can only be NUM, so sub-queries are not allowed as parameters. So in 5.5 we can block sub-queries in procedure clause parameters. This eliminates above conflicting dependencies. --- mysql-test/r/subselect.result | 2 +- mysql-test/t/subselect.test | 2 +- sql/sql_yacc.yy | 12 ++++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 49cf73677b1..aec8e07e071 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -75,7 +75,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); ERROR HY000: Incorrect usage of PROCEDURE and subquery SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -ERROR HY000: Incorrect parameters to procedure 'ANALYSE' +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1))' at line 1 SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; ERROR 42S22: Unknown column 'a' in 'field list' SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index aec0db59843..a5a4b2b5c32 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -30,7 +30,7 @@ SELECT 1 IN (SELECT 1); SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); -- error ER_WRONG_USAGE select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); --- error ER_WRONG_PARAMETERS_TO_PROCEDURE +-- error ER_PARSE_ERROR SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -- error ER_BAD_FIELD_ERROR SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d9a32f2dd35..991fa390e22 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9373,8 +9373,20 @@ procedure_clause: if (add_proc_to_list(lex->thd, item)) MYSQL_YYABORT; Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + + /* + PROCEDURE CLAUSE cannot handle subquery as one of its parameter, + so set expr_allows_subselect as false to disallow any subqueries + further. Reset expr_allows_subselect back to true once the + parameters are reduced. + */ + Lex->expr_allows_subselect= false; } '(' procedure_list ')' + { + /* Subqueries are allowed from now.*/ + Lex->expr_allows_subselect= true; + } ; procedure_list: From 93ac0eb1c46a708529b290fd072c9d1e3e3526e8 Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Tue, 18 Aug 2015 10:38:06 +0530 Subject: [PATCH 30/37] BUG#11754258: INCORRECT ERROR MESSAGE WHEN CREATING UNSAFE VIEW It appears that the code refactoring done as part of the patch for the MySQL BUG#11749859 fixed this issue. This issue is not reproducible on MySQL 5.5+ versions now. As part of this patch, the test file "mysqldump.test" has been updated to remove the comment which was referring to the bug and also the line which suppresses the warning. --- mysql-test/t/mysqldump.test | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 54780b95627..11d766c3293 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -875,13 +875,8 @@ select * from t1; create view v1 as select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); -# Disable warnings since LIMIT warning for unsafe statement if -# binlog_format = STATEMENT. Note: after BUG#45832, the warning should -# not be issued. ---disable_warnings create view v2 as select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; ---enable_warnings --exec $MYSQL_DUMP --skip-comments test From ee02650bac49b66a38c7c485ea2f81edd4403ffc Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Tue, 18 Aug 2015 12:24:27 +0530 Subject: [PATCH 31/37] Bug #16171518 - LOAD XML DOES NOT HANDLE EMPTY ELEMENTS DESCRIPTION =========== Inability of mysql LOAD XML command to handle empty XML tags i.e. . Also the behaviour is wrong and (different than above) when there is a space in empty tag i.e. ANALYSIS ======== In read_xml() the case where we encounter a close tag ('/') we're decreasing the 'level' blindly which is wrong. Actually when its an without-space-empty-tag (succeeding char is '>'), we need to skip the decrement. In other words whenever we hit a close tag ('/'), decrease the 'level' only when (i) It's not an (without space) empty tag i.e. or, (ii) It is of format FIX === The switch case for '/' is modified. We've removed the blind decrement of 'level'. We do it only when its not an without-space-empty-tag. Also we are setting 'in_tag' to false to let program know that we're done reading current tag (required in the case of format ) --- mysql-test/r/loadxml.result | 27 ++++++++++++ mysql-test/std_data/bug16171518_1.dat | 59 +++++++++++++++++++++++++++ mysql-test/std_data/bug16171518_2.dat | 12 ++++++ mysql-test/t/loadxml.test | 14 +++++++ sql/sql_load.cc | 11 ++++- 5 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 mysql-test/std_data/bug16171518_1.dat create mode 100644 mysql-test/std_data/bug16171518_2.dat diff --git a/mysql-test/r/loadxml.result b/mysql-test/r/loadxml.result index 7742f456252..1128caf9122 100644 --- a/mysql-test/r/loadxml.result +++ b/mysql-test/r/loadxml.result @@ -93,3 +93,30 @@ a b 216 !&bb b; 3 !b3 DROP TABLE t1; +# +# Bug#16171518 LOAD XML DOES NOT HANDLE EMPTY ELEMENTS +# +CREATE TABLE t1 (col1 VARCHAR(3), col2 VARCHAR(3), col3 VARCHAR(3), col4 VARCHAR(4)); +LOAD XML INFILE '../../std_data/bug16171518_1.dat' INTO TABLE t1; +SELECT * FROM t1 ORDER BY col1, col2, col3, col4; +col1 col2 col3 col4 +0bc def ghi jkl +1no NULL pqr stu +2BC DEF GHI JKL +3NO NULL PQR STU +4bc def ghi jkl +5no pqr stu vwx +6BC DEF NULL JKL +7NO PQR STU VWX +8bc def ghi NULL +9kl NULL mno pqr +ABC DEF NULL JKL +MNO NULL STU VWX +DROP TABLE t1; +CREATE TABLE t1 (col1 VARCHAR(3), col2 VARCHAR(3), col3 INTEGER); +LOAD XML INFILE '../../std_data/bug16171518_2.dat' INTO TABLE t1; +SELECT * FROM t1 ORDER BY col1, col2, col3; +col1 col2 col3 +ABC DEF NULL +GHI NULL 123 +DROP TABLE t1; diff --git a/mysql-test/std_data/bug16171518_1.dat b/mysql-test/std_data/bug16171518_1.dat new file mode 100644 index 00000000000..b65b9359ce1 --- /dev/null +++ b/mysql-test/std_data/bug16171518_1.dat @@ -0,0 +1,59 @@ + + + 0bc + def + ghi + jkl + + + 1no + + pqr + stu + + + + 2BC + DEF + GHI + JKL + + + 3NO + + PQR + STU + + + + + + + 6BC + DEF + + JKL + + + 7NO + PQR + STU + VWX + + + + 8bc + def + ghi + + + + 9kl + + mno + pqr + + + + + diff --git a/mysql-test/std_data/bug16171518_2.dat b/mysql-test/std_data/bug16171518_2.dat new file mode 100644 index 00000000000..8a483337a0f --- /dev/null +++ b/mysql-test/std_data/bug16171518_2.dat @@ -0,0 +1,12 @@ + + + ABC + DEF + + + + GHI + + 123 + + diff --git a/mysql-test/t/loadxml.test b/mysql-test/t/loadxml.test index 6faf712b6ce..93e6e82189f 100644 --- a/mysql-test/t/loadxml.test +++ b/mysql-test/t/loadxml.test @@ -116,3 +116,17 @@ LOAD XML INFILE '../../std_data/loadxml.dat' INTO TABLE t1 ROWS IDENTIFIED BY '' (a,@b) SET b=concat('!',@b); SELECT * FROM t1 ORDER BY a; DROP TABLE t1; + + +--echo # +--echo # Bug#16171518 LOAD XML DOES NOT HANDLE EMPTY ELEMENTS +--echo # +CREATE TABLE t1 (col1 VARCHAR(3), col2 VARCHAR(3), col3 VARCHAR(3), col4 VARCHAR(4)); +LOAD XML INFILE '../../std_data/bug16171518_1.dat' INTO TABLE t1; +SELECT * FROM t1 ORDER BY col1, col2, col3, col4; +DROP TABLE t1; + +CREATE TABLE t1 (col1 VARCHAR(3), col2 VARCHAR(3), col3 INTEGER); +LOAD XML INFILE '../../std_data/bug16171518_2.dat' INTO TABLE t1; +SELECT * FROM t1 ORDER BY col1, col2, col3; +DROP TABLE t1; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 05571d49cc8..5f72d3ce520 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, 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 @@ -1987,8 +1987,15 @@ int READ_INFO::read_xml() break; case '/': /* close tag */ - level--; chr= my_tospace(GET); + /* Decrease the 'level' only when (i) It's not an */ + /* (without space) empty tag i.e. or, (ii) */ + /* It is of format */ + if(chr != '>' || in_tag) + { + level--; + in_tag= false; + } if(chr != '>') /* if this is an empty tag */ tag.length(0); /* we should keep tag value */ while(chr != '>' && chr != my_b_EOF) From 75f43c5f6a5332894cf2d90ab2c04cc62c5ad18b Mon Sep 17 00:00:00 2001 From: Lars Tangvald Date: Wed, 19 Aug 2015 14:17:50 +0200 Subject: [PATCH 32/37] Small change to default config for Docker-specific rpm package Syncs "official" and our own Docker images --- packaging/rpm-docker/my.cnf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packaging/rpm-docker/my.cnf b/packaging/rpm-docker/my.cnf index 8951b27d776..c1c03c1c668 100644 --- a/packaging/rpm-docker/my.cnf +++ b/packaging/rpm-docker/my.cnf @@ -17,6 +17,8 @@ # join_buffer_size = 128M # sort_buffer_size = 2M # read_rnd_buffer_size = 2M +skip-host-cache +skip-name-resolve datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock secure-file-priv=/var/lib/mysql-files From f4ff086abea975222572fcfd232bf296018f5d85 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Fri, 21 Aug 2015 08:35:42 +0530 Subject: [PATCH 33/37] Bug#20198490 : LOWER_CASE_TABLE_NAMES=0 ON WINDOWS LEADS TO PROBLEMS Description:- Server variable "--lower_case_tables_names" when set to "0" on windows platform which does not support case sensitive file operations leads to problems. A warning message is printed in the error log while starting the server with "--lower_case_tables_names=0". Also according to the documentation, seting "lower_case_tables_names" to "0" on a case-insensitive filesystem might lead to index corruption. Analysis:- The problem reported in the bug is:- Creating an INNODB table 'a' and executing a query, "INSERT INTO a SELECT a FROM A;" on a server started with "--lower_case_tables_names=0" and running on a case-insensitive filesystem leads innodb to flat spin. Optimizer thinks that "a" and "A" are two different tables as the variable "lower_case_table_names" is set to "0". As a result, optimizer comes up with a plan which does not need a temporary table. If the same table is used in select and insert, a temporary table is needed. This incorrect optimizer plan leads to infinite insertions. Fix:- If the server is started with "--lower_case_tables_names" set to 0 on a case-insensitive filesystem, an error, "The server option 'lower_case_table_names'is configured to use case sensitive table names but the data directory is on a case-insensitive file system which is an unsupported combination. Please consider either using a case sensitive file system for your data directory or switching to a case-insensitive table name mode.", is printed in the server error log and the server exits. --- mysql-test/r/lowercase_fs_on.result | 3 ++ mysql-test/r/lowercase_table3.result | 11 ------ .../suite/innodb/t/innodb_bug60229-master.opt | 1 - .../suite/innodb/t/innodb_bug60229.test | 4 ++ mysql-test/suite/jp/t/jp_enum_sjis-master.opt | 1 - mysql-test/suite/jp/t/jp_enum_sjis.test | 4 ++ mysql-test/suite/jp/t/jp_enum_ucs2-master.opt | 1 - mysql-test/suite/jp/t/jp_enum_ucs2.test | 4 ++ mysql-test/suite/jp/t/jp_enum_ujis-master.opt | 1 - mysql-test/suite/jp/t/jp_enum_ujis.test | 4 ++ mysql-test/suite/jp/t/jp_enum_utf8-master.opt | 1 - mysql-test/suite/jp/t/jp_enum_utf8.test | 4 ++ mysql-test/t/lowercase_fs_on.test | 38 +++++++++++++++++++ mysql-test/t/lowercase_table3-master.opt | 1 - mysql-test/t/lowercase_table3.test | 37 ------------------ sql/mysqld.cc | 15 ++++---- 16 files changed, 69 insertions(+), 61 deletions(-) create mode 100644 mysql-test/r/lowercase_fs_on.result delete mode 100644 mysql-test/r/lowercase_table3.result delete mode 100644 mysql-test/suite/innodb/t/innodb_bug60229-master.opt delete mode 100644 mysql-test/suite/jp/t/jp_enum_sjis-master.opt delete mode 100644 mysql-test/suite/jp/t/jp_enum_ucs2-master.opt delete mode 100644 mysql-test/suite/jp/t/jp_enum_ujis-master.opt delete mode 100644 mysql-test/suite/jp/t/jp_enum_utf8-master.opt create mode 100644 mysql-test/t/lowercase_fs_on.test delete mode 100644 mysql-test/t/lowercase_table3-master.opt delete mode 100644 mysql-test/t/lowercase_table3.test diff --git a/mysql-test/r/lowercase_fs_on.result b/mysql-test/r/lowercase_fs_on.result new file mode 100644 index 00000000000..a090f46cfbf --- /dev/null +++ b/mysql-test/r/lowercase_fs_on.result @@ -0,0 +1,3 @@ +# +# Bug#20198490 : LOWER_CASE_TABLE_NAMES=0 ON WINDOWS LEADS TO PROBLEMS +# diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result deleted file mode 100644 index 22e80aaeb26..00000000000 --- a/mysql-test/r/lowercase_table3.result +++ /dev/null @@ -1,11 +0,0 @@ -call mtr.add_suppression("Cannot find or open table test/BUG29839 from"); -DROP TABLE IF EXISTS t1,T1; -CREATE TABLE t1 (a INT); -SELECT * FROM T1; -a -FLUSH TABLES; -DROP TABLE t1; -CREATE TABLE bug29839 (a INT) ENGINE=INNODB; -SELECT * FROM BUG29839; -ERROR 42S02: Table 'test.BUG29839' doesn't exist -DROP TABLE bug29839; diff --git a/mysql-test/suite/innodb/t/innodb_bug60229-master.opt b/mysql-test/suite/innodb/t/innodb_bug60229-master.opt deleted file mode 100644 index 9b27aef9bf8..00000000000 --- a/mysql-test/suite/innodb/t/innodb_bug60229-master.opt +++ /dev/null @@ -1 +0,0 @@ ---lower_case_table_names=0 diff --git a/mysql-test/suite/innodb/t/innodb_bug60229.test b/mysql-test/suite/innodb/t/innodb_bug60229.test index 8dcf15157d6..aee0b96a942 100644 --- a/mysql-test/suite/innodb/t/innodb_bug60229.test +++ b/mysql-test/suite/innodb/t/innodb_bug60229.test @@ -2,6 +2,10 @@ # Bug #13083023 - 60229: BROKEN COMPATIBILITY: ERROR WHILE CREATE TABLE # WITH FOREIGN KEY CONSTRAINT. +#Server variable option 'lower_case_table_names' sets '0' as default value +#in case sensitive filesystem. Using 'lower_case_table_names=0' in case of +#insensitive filsystem is not allowed. +-- source include/have_case_sensitive_file_system.inc -- source include/have_innodb.inc CREATE TABLE PERSON ( diff --git a/mysql-test/suite/jp/t/jp_enum_sjis-master.opt b/mysql-test/suite/jp/t/jp_enum_sjis-master.opt deleted file mode 100644 index 9b27aef9bf8..00000000000 --- a/mysql-test/suite/jp/t/jp_enum_sjis-master.opt +++ /dev/null @@ -1 +0,0 @@ ---lower_case_table_names=0 diff --git a/mysql-test/suite/jp/t/jp_enum_sjis.test b/mysql-test/suite/jp/t/jp_enum_sjis.test index e1f22f6fe27..1060f83ec06 100644 --- a/mysql-test/suite/jp/t/jp_enum_sjis.test +++ b/mysql-test/suite/jp/t/jp_enum_sjis.test @@ -1,3 +1,7 @@ +#Server variable option 'lower_case_table_names' sets '0' as default value +#in case sensitive filesystem. Using 'lower_case_table_names=0' in case of +#insensitive filsystem is not allowed. +-- source include/have_case_sensitive_file_system.inc --source include/have_sjis.inc --source include/have_innodb.inc --character_set sjis diff --git a/mysql-test/suite/jp/t/jp_enum_ucs2-master.opt b/mysql-test/suite/jp/t/jp_enum_ucs2-master.opt deleted file mode 100644 index 9b27aef9bf8..00000000000 --- a/mysql-test/suite/jp/t/jp_enum_ucs2-master.opt +++ /dev/null @@ -1 +0,0 @@ ---lower_case_table_names=0 diff --git a/mysql-test/suite/jp/t/jp_enum_ucs2.test b/mysql-test/suite/jp/t/jp_enum_ucs2.test index a3d7c47705d..321f8952148 100644 --- a/mysql-test/suite/jp/t/jp_enum_ucs2.test +++ b/mysql-test/suite/jp/t/jp_enum_ucs2.test @@ -1,3 +1,7 @@ +#Server variable option 'lower_case_table_names' sets '0' as default value +#in case sensitive filesystem. Using 'lower_case_table_names=0' in case of +#insensitive filsystem is not allowed. +-- source include/have_case_sensitive_file_system.inc --source include/have_ucs2.inc --source include/have_innodb.inc diff --git a/mysql-test/suite/jp/t/jp_enum_ujis-master.opt b/mysql-test/suite/jp/t/jp_enum_ujis-master.opt deleted file mode 100644 index 9b27aef9bf8..00000000000 --- a/mysql-test/suite/jp/t/jp_enum_ujis-master.opt +++ /dev/null @@ -1 +0,0 @@ ---lower_case_table_names=0 diff --git a/mysql-test/suite/jp/t/jp_enum_ujis.test b/mysql-test/suite/jp/t/jp_enum_ujis.test index 17e41e0691e..10e8ad55a3c 100644 --- a/mysql-test/suite/jp/t/jp_enum_ujis.test +++ b/mysql-test/suite/jp/t/jp_enum_ujis.test @@ -1,3 +1,7 @@ +#Server variable option 'lower_case_table_names' sets '0' as default value +#in case sensitive filesystem. Using 'lower_case_table_names=0' in case of +#insensitive filsystem is not allowed. +-- source include/have_case_sensitive_file_system.inc --source include/have_ujis.inc --source include/have_innodb.inc diff --git a/mysql-test/suite/jp/t/jp_enum_utf8-master.opt b/mysql-test/suite/jp/t/jp_enum_utf8-master.opt deleted file mode 100644 index 9b27aef9bf8..00000000000 --- a/mysql-test/suite/jp/t/jp_enum_utf8-master.opt +++ /dev/null @@ -1 +0,0 @@ ---lower_case_table_names=0 diff --git a/mysql-test/suite/jp/t/jp_enum_utf8.test b/mysql-test/suite/jp/t/jp_enum_utf8.test index ff5978da69c..f67939bd02b 100644 --- a/mysql-test/suite/jp/t/jp_enum_utf8.test +++ b/mysql-test/suite/jp/t/jp_enum_utf8.test @@ -1,3 +1,7 @@ +#Server variable option 'lower_case_table_names' sets '0' as default value +#in case sensitive filesystem. Using 'lower_case_table_names=0' in case of +#insensitive filsystem is not allowed. +-- source include/have_case_sensitive_file_system.inc --source include/have_utf8.inc --source include/have_innodb.inc --disable_warnings diff --git a/mysql-test/t/lowercase_fs_on.test b/mysql-test/t/lowercase_fs_on.test new file mode 100644 index 00000000000..6da3ef32a0b --- /dev/null +++ b/mysql-test/t/lowercase_fs_on.test @@ -0,0 +1,38 @@ +# +# Specific tests for case-insensitive file systems +# i.e. lower_case_filesystem=ON +# +-- source include/have_case_insensitive_file_system.inc +# Embedded server does not support restarting. +--source include/not_embedded.inc + +--echo # +--echo # Bug#20198490 : LOWER_CASE_TABLE_NAMES=0 ON WINDOWS LEADS TO PROBLEMS +--echo # + +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; + +--error 0,1 +--remove_file $SEARCH_FILE + +#Shutdown the server +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +#Start the server with --lower_case_table_names=0 in Windows. +--enable_reconnect +--error 1 +--exec $MYSQLD_CMD --lower_case_table_names=0 > $SEARCH_FILE 2>&1 + +#Search for the error messege in the server error log. +let SEARCH_PATTERN= \[ERROR\] The server option \'lower_case_table_names\' is configured to use case sensitive table names but the data directory is on a case-insensitive file system which is an unsupported combination\. Please consider either using a case sensitive file system for your data directory or switching to a case-insensitive table name mode\.; +--source include/search_pattern_in_file.inc + +#Restart the server +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--source include/wait_until_connected_again.inc + +#Cleanup +--error 0,1 +--remove_file $SEARCH_FILE diff --git a/mysql-test/t/lowercase_table3-master.opt b/mysql-test/t/lowercase_table3-master.opt deleted file mode 100644 index 9b27aef9bf8..00000000000 --- a/mysql-test/t/lowercase_table3-master.opt +++ /dev/null @@ -1 +0,0 @@ ---lower_case_table_names=0 diff --git a/mysql-test/t/lowercase_table3.test b/mysql-test/t/lowercase_table3.test deleted file mode 100644 index f7ca8211288..00000000000 --- a/mysql-test/t/lowercase_table3.test +++ /dev/null @@ -1,37 +0,0 @@ -# -# Test of force of lower-case-table-names=0 -# (User has case insensitive file system and wants to preserve case of -# table names) -# - ---source include/have_innodb.inc ---source include/have_lowercase0.inc ---source include/have_case_insensitive_file_system.inc ---source include/not_windows.inc - -call mtr.add_suppression("Cannot find or open table test/BUG29839 from"); - ---disable_warnings -DROP TABLE IF EXISTS t1,T1; ---enable_warnings - -# -# This is actually an error, but ok as the user has forced this -# by using --lower-case-table-names=0 -CREATE TABLE t1 (a INT); -SELECT * FROM T1; -FLUSH TABLES; -DROP TABLE t1; - -# -# InnoDB should in this case be case sensitive -# Note that this is not true on windows as no this OS, InnoDB is always -# storing things in lower case. -# - -CREATE TABLE bug29839 (a INT) ENGINE=INNODB; ---error ER_NO_SUCH_TABLE -SELECT * FROM BUG29839; -DROP TABLE bug29839; - -# End of 4.1 tests diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c999e0c5a0f..a2532ceddd3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3551,13 +3551,14 @@ static int init_common_variables() { if (lower_case_table_names_used) { - if (global_system_variables.log_warnings) - sql_print_warning("\ -You have forced lower_case_table_names to 0 through a command-line \ -option, even though your file system '%s' is case insensitive. This means \ -that you can corrupt a MyISAM table by accessing it with different cases. \ -You should consider changing lower_case_table_names to 1 or 2", - mysql_real_data_home); + sql_print_error("The server option 'lower_case_table_names' is " + "configured to use case sensitive table names but the " + "data directory is on a case-insensitive file system " + "which is an unsupported combination. Please consider " + "either using a case sensitive file system for your data " + "directory or switching to a case-insensitive table name " + "mode."); + return 1; } else { From e414cbffad0e095c545cf2aa3f646c8a36c9b398 Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Tue, 25 Aug 2015 14:25:46 +0530 Subject: [PATCH 34/37] BUG#20449914: HANDLE_FATAL_SIGNAL (SIG=11) IN FIELD_ITERATOR_TABLE::END_OF_FIELDS Note: This a backport of the patch for bug#19894987 to MySQL-5.5 --- sql/sql_base.cc | 14 +++++++++++--- sql/sql_handler.cc | 48 +++++++++++++++++++++++++++++++++++++++++++++- sql/sql_handler.h | 3 ++- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0b256974258..61a0d1ae909 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1648,13 +1648,20 @@ bool close_temporary_tables(THD *thd) if (!thd->temporary_tables) DBUG_RETURN(FALSE); + /* + Ensure we don't have open HANDLERs for tables we are about to close. + This is necessary when close_temporary_tables() is called as part + of execution of BINLOG statement (e.g. for format description event). + */ + mysql_ha_rm_temporary_tables(thd); if (!mysql_bin_log.is_open()) { TABLE *tmp_next; - for (table= thd->temporary_tables; table; table= tmp_next) + for (TABLE *t= thd->temporary_tables; t; t= tmp_next) { - tmp_next= table->next; - close_temporary(table, 1, 1); + tmp_next= t->next; + mysql_lock_remove(thd, thd->lock, t); + close_temporary(t, 1, 1); } thd->temporary_tables= 0; DBUG_RETURN(FALSE); @@ -1744,6 +1751,7 @@ bool close_temporary_tables(THD *thd) strlen(table->s->table_name.str)); s_query.append(','); next= table->next; + mysql_lock_remove(thd, thd->lock, table); close_temporary(table, 1, 1); } thd->clear_error(); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index b179d54eadf..2d8877db37a 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2001, 2015, 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 @@ -1002,3 +1002,49 @@ void mysql_ha_set_explicit_lock_duration(THD *thd) DBUG_VOID_RETURN; } + +/** + Remove temporary tables from the HANDLER's hash table. The reason + for having a separate function, rather than calling + mysql_ha_rm_tables() is that it is not always feasible (e.g. in + close_temporary_tables) to obtain a TABLE_LIST containing the + temporary tables. + + @See close_temporary_tables + @param thd Thread identifier. +*/ +void mysql_ha_rm_temporary_tables(THD *thd) +{ + DBUG_ENTER("mysql_ha_rm_temporary_tables"); + + TABLE_LIST *tmp_handler_tables= NULL; + for (uint i= 0; i < thd->handler_tables_hash.records; i++) + { + TABLE_LIST *handler_table= reinterpret_cast + (my_hash_element(&thd->handler_tables_hash, i)); + + if (handler_table->table && handler_table->table->s->tmp_table) + { + handler_table->next_local= tmp_handler_tables; + tmp_handler_tables= handler_table; + } + } + + while (tmp_handler_tables) + { + TABLE_LIST *nl= tmp_handler_tables->next_local; + mysql_ha_close_table(thd, tmp_handler_tables); + my_hash_delete(&thd->handler_tables_hash, (uchar*) tmp_handler_tables); + tmp_handler_tables= nl; + } + + /* + Mark MDL_context as no longer breaking protocol if we have + closed last HANDLER. + */ + if (thd->handler_tables_hash.records == 0) + { + thd->mdl_context.set_needs_thr_lock_abort(FALSE); + } + DBUG_VOID_RETURN; +} diff --git a/sql/sql_handler.h b/sql/sql_handler.h index b21d4595fce..c6d8c5ed0c0 100644 --- a/sql/sql_handler.h +++ b/sql/sql_handler.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2015, 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 @@ -32,5 +32,6 @@ void mysql_ha_flush_tables(THD *thd, TABLE_LIST *all_tables); void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables); void mysql_ha_cleanup(THD *thd); void mysql_ha_set_explicit_lock_duration(THD *thd); +void mysql_ha_rm_temporary_tables(THD *thd); #endif /* SQL_HANDLER_INCLUDED */ From b1895fb8c924e7152b73765cfd02b686362ca76c Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Wed, 26 Aug 2015 19:29:00 +0200 Subject: [PATCH 35/37] Bug#21527467 - RPM SCRIPTS FAIL WITH MULTIPLE DATADIR --- support-files/mysql.spec.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index aaeed444e2f..5af4783f919 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -635,7 +635,7 @@ install -m 644 "%{malloc_lib_source}" \ # Check local settings to support them. if [ -x %{_bindir}/my_print_defaults ] then - mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p'` + mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | tail -1 | sed -n 's/--datadir=//p'` PID_FILE_PATT=`%{_bindir}/my_print_defaults server mysqld | grep '^--pid-file=' | sed -n 's/--pid-file=//p'` fi if [ -z "$mysql_datadir" ] @@ -740,7 +740,7 @@ esac STATUS_FILE=$mysql_datadir/RPM_UPGRADE_MARKER -if [ -f $STATUS_FILE ]; then +if [ -f "$STATUS_FILE" ]; then echo "Some previous upgrade was not finished:" ls -ld $STATUS_FILE echo "Please check its status, then do" @@ -811,7 +811,7 @@ fi # Check local settings to support them. if [ -x %{_bindir}/my_print_defaults ] then - mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p'` + mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | tail -1 | sed -n 's/--datadir=//p'` fi if [ -z "$mysql_datadir" ] then @@ -824,8 +824,8 @@ STATUS_FILE=$mysql_datadir/RPM_UPGRADE_MARKER # ---------------------------------------------------------------------- # Create data directory if needed, check whether upgrade or install # ---------------------------------------------------------------------- -if [ ! -d $mysql_datadir ] ; then mkdir -m 755 $mysql_datadir; fi -if [ -f $STATUS_FILE ] ; then +if [ ! -d "$mysql_datadir" ] ; then mkdir -m 755 "$mysql_datadir" ; fi +if [ -f "$STATUS_FILE" ] ; then SERVER_TO_START=`grep '^SERVER_TO_START=' $STATUS_FILE | cut -c17-` else SERVER_TO_START='' @@ -1003,7 +1003,7 @@ fi # Check local settings to support them. if [ -x %{_bindir}/my_print_defaults ] then - mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p'` + mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | tail -1 | sed -n 's/--datadir=//p'` fi if [ -z "$mysql_datadir" ] then @@ -1014,7 +1014,7 @@ NEW_VERSION=%{mysql_version}-%{release} STATUS_FILE=$mysql_datadir/RPM_UPGRADE_MARKER-LAST # Note the difference! STATUS_HISTORY=$mysql_datadir/RPM_UPGRADE_HISTORY -if [ -f $STATUS_FILE ] ; then +if [ -f "$STATUS_FILE" ] ; then SERVER_TO_START=`grep '^SERVER_TO_START=' $STATUS_FILE | cut -c17-` else # This should never happen, but let's be prepared From 0243a2d432abb609af890aea5a417862aa4514cb Mon Sep 17 00:00:00 2001 From: Robert Golebiowski Date: Fri, 18 Sep 2015 10:35:09 +0200 Subject: [PATCH 36/37] Bug #21025377 CAN'T CONNECT TO SSL ENABLED SERVER FIRST 30 SEC AFTER INITIAL STARTUP Updated yassl to yassl-2.3.7e (cherry picked from commit 6e21c8c04b922bdb60b6a7c174709d2e1bdd3618) --- extra/yassl/README | 7 +++++++ extra/yassl/include/openssl/ssl.h | 2 +- extra/yassl/taocrypt/src/asn.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/extra/yassl/README b/extra/yassl/README index 2560c09addd..47ec1a66ea3 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -12,6 +12,13 @@ before calling SSL_new(); *** end Note *** +yaSSL Patch notes, version 2.3.7e (6/26/2015) + This release of yaSSL includes a fix for Date less than comparison. + Previously yaSSL would return true on less than comparisons if the Dates + were equal. Reported by Oracle. No security problem, but if a cert was + generated right now, a server started using it in the same second, and a + client tried to verify it in the same second it would report not yet valid. + yaSSL Patch notes, version 2.3.7d (6/22/2015) This release of yaSSL includes a fix for input_buffer set_current with index 0. SSL_peek() at front of waiting data could trigger. Robert diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 692d8b270d2..9e16f9278a7 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -35,7 +35,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.3.7d" +#define YASSL_VERSION "2.3.7e" #if defined(__cplusplus) diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 342255c91b8..c419ec0a992 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -71,7 +71,7 @@ bool operator>(tm& a, tm& b) bool operator<(tm& a, tm&b) { - return !(a>b); + return (b>a); } From b9768521bdeb1a8069c7b871f4536792b65fd79b Mon Sep 17 00:00:00 2001 From: Robert Golebiowski Date: Fri, 18 Sep 2015 11:18:25 +0200 Subject: [PATCH 37/37] Updated yassl to yassl-2.3.8 (cherry picked from commit 7f9941eab55ed672bfcccd382dafbdbcfdc75aaa) --- extra/yassl/README | 8 ++++++++ extra/yassl/include/openssl/ssl.h | 2 +- extra/yassl/include/yassl_error.hpp | 3 ++- extra/yassl/src/handshake.cpp | 2 ++ extra/yassl/src/yassl_error.cpp | 4 ++++ extra/yassl/src/yassl_imp.cpp | 15 ++++++++++++++- 6 files changed, 31 insertions(+), 3 deletions(-) diff --git a/extra/yassl/README b/extra/yassl/README index 47ec1a66ea3..bf0e1c9f40f 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -12,6 +12,14 @@ before calling SSL_new(); *** end Note *** +yaSSL Release notes, version 2.3.8 (9/17/2015) + This release of yaSSL fixes a high security vulnerability. All users + SHOULD update. If using yaSSL for TLS on the server side with private + RSA keys allowing ephemeral key exchange you MUST update and regenerate + the RSA private keys. This report is detailed in: + https://people.redhat.com/~fweimer/rsa-crt-leaks.pdf + yaSSL now detects RSA signature faults and returns an error. + yaSSL Patch notes, version 2.3.7e (6/26/2015) This release of yaSSL includes a fix for Date less than comparison. Previously yaSSL would return true on less than comparisons if the Dates diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 9e16f9278a7..b0a7592f870 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -35,7 +35,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.3.7e" +#define YASSL_VERSION "2.3.8" #if defined(__cplusplus) diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp index beba7b0b5dd..d63244dca90 100644 --- a/extra/yassl/include/yassl_error.hpp +++ b/extra/yassl/include/yassl_error.hpp @@ -53,7 +53,8 @@ enum YasslError { compress_error = 118, decompress_error = 119, pms_version_error = 120, - sanityCipher_error = 121 + sanityCipher_error = 121, + rsaSignFault_error = 122 // !!!! add error message to .cpp !!!! diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 33303b1106d..aa2de39333c 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -1172,6 +1172,8 @@ void sendCertificateVerify(SSL& ssl, BufferOutput buffer) CertificateVerify verify; verify.Build(ssl); + if (ssl.GetError()) return; + RecordLayerHeader rlHeader; HandShakeHeader hsHeader; mySTL::auto_ptr out(NEW_YS output_buffer); diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index e5d69367339..5169b7dd5d0 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -148,6 +148,10 @@ void SetErrorString(YasslError error, char* buffer) strncpy(buffer, "sanity check on cipher text size error", max); break; + case rsaSignFault_error: + strncpy(buffer, "rsa signature fault error", max); + break; + // openssl errors case SSL_ERROR_WANT_READ : strncpy(buffer, "the read operation would block", max); diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 69ba469b928..1baa5adedf8 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -196,9 +196,16 @@ void DH_Server::build(SSL& ssl) sha.update(tmp.get_buffer(), tmp.get_size()); sha.get_digest(&hash[MD5_LEN]); - if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) + if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) { auth->sign(signature_, hash, sizeof(hash), ssl.getCrypto().get_random()); + // check for rsa signautre fault + if (!auth->verify(hash, sizeof(hash), signature_, + auth->get_signatureLength())) { + ssl.SetError(rsaSignFault_error); + return; + } + } else { auth->sign(signature_, &hash[MD5_LEN], SHA_LEN, ssl.getCrypto().get_random()); @@ -2159,6 +2166,12 @@ void CertificateVerify::Build(SSL& ssl) memcpy(sig.get(), len, VERIFY_HEADER); rsa.sign(sig.get() + VERIFY_HEADER, hashes_.md5_, sizeof(Hashes), ssl.getCrypto().get_random()); + // check for rsa signautre fault + if (!rsa.verify(hashes_.md5_, sizeof(Hashes), sig.get() + VERIFY_HEADER, + rsa.get_cipherLength())) { + ssl.SetError(rsaSignFault_error); + return; + } } else { // DSA DSS dss(cert.get_privateKey(), cert.get_privateKeyLength(), false);