From 6d30383e78c8b9aba56f645421f437af63706efe Mon Sep 17 00:00:00 2001 From: Murthy Narkedimilli Date: Mon, 31 Aug 2015 20:36:03 +0200 Subject: [PATCH 01/29] Raise version number after cloning 5.5.46 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 45f770d8f07..b85da230659 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=46 +MYSQL_VERSION_PATCH=47 MYSQL_VERSION_EXTRA= From 97ea06e807628b6d079ae5f72f5ee0c0ea391caf Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Tue, 1 Sep 2015 08:53:15 +0200 Subject: [PATCH 02/29] Raise version number after tagging 5.1.77 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index be169e073bd..cf433796fea 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.77], [], [mysql]) +AC_INIT([MySQL Server], [5.1.78], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From ddcad361d6ff2c3336221f27c4e31bfc8d1913b1 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Fri, 4 Sep 2015 11:10:57 +0530 Subject: [PATCH 03/29] Bug #21503595 : --QUERY-ALLOC-BLOCK-SIZE=-1125899906842624 + PID_FILE CHECK LEADS TO OOM SIG 11 Description:- A server started with 'query_alloc_block_size' option set to a certain range of negative values on a machine without enough memory may lead to OOM. Analysis:- Server uses 'strtoull()' to convert server variable values of type 'GET_UINT', 'GET_ULONG' or 'GET_ULL' from string to unsigned long long. According to the man page, 'strtoull()' function returns either the result of the conversion or, if there was a leading minus sign, the negation of the result of the conversion represented as an unsigned value, unless the original(nonnegated) value would overflow; in the latter case, strtoull() returns ULLONG_MAX and sets errno to ERANGE. So 'strtoull()' converts a small negative value to a larger postive value. For example string '-1125899906842624' will be converted to an unsigned value, '18445618173802708992' (ulonglong typecast of '-1125899906842624'). So a server started with 'query_alloc_block_size' set to "-1125899906842624" on a machine without enough memory will lead to OOM since server allocates '18445618173802708992' bytes(17178820608 GB) for query allocation block. Fix:- When server is started with any server variable, of type "GET_UINT", "GET_ULONG" or "GET_ULL", set to a negative value, a warning, "option xxx: value -yyy adjusted to zzz" is thrown and the value is adjusted to the lowest possible value for that variable. The dynamic server variable which is configured through the client exhibit the same behavior as fix made for variables configured during the server start up. --- mysys/my_getopt.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 03469589173..6d27c9a9e73 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2002, 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 @@ -1005,6 +1005,14 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, return num; } +static inline my_bool is_negative_num(char* num) +{ + while (my_isspace(&my_charset_latin1, *num)) + num++; + + return (*num == '-'); +} + /* function: getopt_ull @@ -1014,7 +1022,20 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err) { - ulonglong num= eval_num_suffix(arg, err, (char*) optp->name); + char buf[255]; + ulonglong num; + + /* If a negative number is specified as a value for the option. */ + if (arg == NULL || is_negative_num(arg) == TRUE) + { + num= (ulonglong) optp->min_value; + my_getopt_error_reporter(WARNING_LEVEL, + "option '%s': value %s adjusted to %s", + optp->name, arg, ullstr(num, buf)); + } + else + num= eval_num_suffix(arg, err, (char*) optp->name); + return getopt_ull_limit_value(num, optp, NULL); } From adf12e6e1704dbf4f5e06fa45f40ab5b71514cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 11 Sep 2015 10:32:10 +0300 Subject: [PATCH 04/29] Adapt to WL#8845 Implement an InnoDB redo log format version identifier recv_find_max_checkpoint(): Amend the error message to give advice about downgrading. The 5.7.9 redo log format was intentionally changed so that older MySQL versions will not find a valid redo log checkpoint. --- storage/innobase/log/log0recv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index 5dfb0c9defd..ae3912da552 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1997, 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 @@ -736,6 +736,10 @@ not_consistent: fprintf(stderr, "InnoDB: No valid checkpoint found.\n" + "InnoDB: If you are attempting downgrade" + " from MySQL 5.7.9 or later,\n" + "InnoDB: please refer to " REFMAN + "upgrading-downgrading.html\n" "InnoDB: If this error appears when you are" " creating an InnoDB database,\n" "InnoDB: the problem may be that during" From 17387bc574a4054a9aeac7ba4aa60e25588dc7bf Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Wed, 16 Sep 2015 18:58:43 +0530 Subject: [PATCH 05/29] Bug #21467458 - UNINSTALL PLUGIN DAEMON_EXAMPLE CRASHES MYSQLD. DESCRIPTION =========== Crash occurs when daemon_example plugin is uninstalled immediately after its installed. This can be reproduced by installing and uninstalling the plugin repeatedly. ANALYSIS ======== The daemon_example_plugin_deinit() function of the daemon example plugin calls pthread_cancel() but doesn't wait for the worker thread to actually complete before deallocating the data buffer and closing the file that it writes to. This is causing SEGFAULT! FIX === Added a pthread_join() to wait for the thread to complete before doing the cleanup work. Removed a stray 'x' variable from the example code. NOTE ==== Have made an entry in .opt file as given below: --plugin-dir=$DAEMONEXAMPLE_DIR This is done so that the program takes plugin directory as ..//plugin/daemon_example/ instead of ../lib/plugin/ --- plugin/daemon_example/daemon_example.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/plugin/daemon_example/daemon_example.cc b/plugin/daemon_example/daemon_example.cc index ac4841b10b2..129469405b8 100644 --- a/plugin/daemon_example/daemon_example.cc +++ b/plugin/daemon_example/daemon_example.cc @@ -1,4 +1,5 @@ -/* 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 @@ -46,7 +47,6 @@ pthread_handler_t mysql_heartbeat(void *p) DBUG_ENTER("mysql_heartbeat"); struct mysql_heartbeat_context *con= (struct mysql_heartbeat_context *)p; char buffer[HEART_STRING_BUFFER]; - unsigned int x= 0; time_t result; struct tm tm_tmp; @@ -65,7 +65,6 @@ pthread_handler_t mysql_heartbeat(void *p) tm_tmp.tm_min, tm_tmp.tm_sec); my_write(con->heartbeat_file, (uchar*) buffer, strlen(buffer), MYF(0)); - x++; } DBUG_RETURN(0); @@ -173,6 +172,13 @@ static int daemon_example_plugin_deinit(void *p) tm_tmp.tm_min, tm_tmp.tm_sec); my_write(con->heartbeat_file, (uchar*) buffer, strlen(buffer), MYF(0)); + + /* + Need to wait for the hearbeat thread to terminate before closing + the file it writes to and freeing the memory it uses. + */ + pthread_join(con->heartbeat_thread, NULL); + my_close(con->heartbeat_file, MYF(0)); my_free(con); From 4acc7615eedc167fbad6fcc14966a054de35fd75 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Fri, 18 Sep 2015 07:34:32 +0530 Subject: [PATCH 06/29] Bug #19929406: HANDLE_FATAL_SIGNAL (SIG=11) IN __MEMMOVE_SSSE3_BACK FROM STRING::COPY Issue: ----- While using row comparators, the store_value functions call val_xxx functions in the prepare phase. This can cause valgrind issues. SOLUTION: --------- Setting up of the comparators should be done by alloc_comparators in the prepare phase. Also, make sure store_value will be called only during execute phase. This is a backport of the fix for Bug#17755540. --- sql/item_cmpfunc.cc | 37 ++++++++++++++++++++++--------------- sql/item_cmpfunc.h | 4 ++-- sql/table.cc | 17 +---------------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 42e79754b95..e6cc3272ceb 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.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 @@ -3708,29 +3708,39 @@ cmp_item_row::~cmp_item_row() } -void cmp_item_row::alloc_comparators() +void cmp_item_row::alloc_comparators(Item *item) { + n= item->cols(); + DBUG_ASSERT(comparators == NULL); if (!comparators) comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n); + if (comparators) + { + for (uint i= 0; i < n; i++) + { + DBUG_ASSERT(comparators[i] == NULL); + Item *item_i= item->element_index(i); + if (!(comparators[i]= + cmp_item::get_comparator(item_i->result_type(), + item_i->collation.collation))) + break; // new failed + if (item_i->result_type() == ROW_RESULT) + static_cast(comparators[i])->alloc_comparators(item_i); + } + } } void cmp_item_row::store_value(Item *item) { DBUG_ENTER("cmp_item_row::store_value"); - n= item->cols(); - alloc_comparators(); + DBUG_ASSERT(comparators); if (comparators) { item->bring_value(); item->null_value= 0; - for (uint i=0; i < n; i++) + for (uint i= 0; i < n; i++) { - if (!comparators[i]) - if (!(comparators[i]= - cmp_item::get_comparator(item->element_index(i)->result_type(), - item->element_index(i)->collation.collation))) - break; // new failed comparators[i]->store_value(item->element_index(i)); item->null_value|= item->element_index(i)->null_value; } @@ -3991,7 +4001,7 @@ void Item_func_in::fix_length_and_dec() cmp_items[ROW_RESULT]= cmp; } cmp->n= args[0]->cols(); - cmp->alloc_comparators(); + cmp->alloc_comparators(args[0]); } /* All DATE/DATETIME fields/functions has the STRING result type. */ if (cmp_type == STRING_RESULT || cmp_type == ROW_RESULT) @@ -4102,11 +4112,8 @@ void Item_func_in::fix_length_and_dec() break; case ROW_RESULT: /* - The row comparator was created at the beginning but only DATETIME - items comparators were initialized. Call store_value() to setup - others. + The row comparator was created at the beginning. */ - ((in_row*)array)->tmp.store_value(args[0]); break; case DECIMAL_RESULT: array= new in_decimal(arg_count - 1); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 38a88d88715..115d6db300d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1,7 +1,7 @@ #ifndef ITEM_CMPFUNC_INCLUDED #define ITEM_CMPFUNC_INCLUDED -/* 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 @@ -1288,7 +1288,7 @@ public: cmp_item_row(): comparators(0), n(0) {} ~cmp_item_row(); void store_value(Item *item); - inline void alloc_comparators(); + inline void alloc_comparators(Item *item); int cmp(Item *arg); int compare(cmp_item *arg); cmp_item *make_same(); diff --git a/sql/table.cc b/sql/table.cc index c17ee39fe9e..750b870da75 100644 --- a/sql/table.cc +++ b/sql/table.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 @@ -1910,21 +1910,6 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, outparam->record[1]= outparam->record[0]; // Safety } -#ifdef HAVE_purify - /* - We need this because when we read var-length rows, we are not updating - bytes after end of varchar - */ - if (records > 1) - { - memcpy(outparam->record[0], share->default_values, share->rec_buff_length); - memcpy(outparam->record[1], share->default_values, share->null_bytes); - if (records > 2) - memcpy(outparam->record[1], share->default_values, - share->rec_buff_length); - } -#endif - if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root, (uint) ((share->fields+1)* sizeof(Field*))))) From 0632dae73fe3379cba00beeb65585f0d61f10d8c Mon Sep 17 00:00:00 2001 From: Robert Golebiowski Date: Fri, 18 Sep 2015 10:35:09 +0200 Subject: [PATCH 07/29] Bug #21025377 CAN'T CONNECT TO SSL ENABLED SERVER FIRST 30 SEC AFTER INITIAL STARTUP Updated yassl to yassl-2.3.7e --- 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 259cf3dc607dd0112d44c4647b07a3024cee268e Mon Sep 17 00:00:00 2001 From: Robert Golebiowski Date: Fri, 18 Sep 2015 11:18:25 +0200 Subject: [PATCH 08/29] Updated yassl to yassl-2.3.8 --- 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); From 8ea80ecfeb88846ee47c65011eb9ff7eddab84b3 Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Tue, 22 Sep 2015 06:21:13 +0200 Subject: [PATCH 09/29] Bug #19929435 DROP DATABASE HANGS WITH MALFORMED TABLE Note: Backporting the patch from mysql-5.6. Problem: A CREATE TABLE with an invalid table name is detected at SQL layer. So the table name is reset to an empty string. But the storage engine is called with this empty table name. The table name is specified as "database/table". So, in the given scenario we get only "database/". Solution: Within InnoDB, detect this error and report it to higher layer. rb#9274 approved by jimmy. --- mysql-test/suite/innodb/r/dropdb.result | 9 +++++++++ mysql-test/suite/innodb/t/dropdb.test | 12 ++++++++++++ storage/innobase/handler/ha_innodb.cc | 12 +++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/innodb/r/dropdb.result create mode 100644 mysql-test/suite/innodb/t/dropdb.test diff --git a/mysql-test/suite/innodb/r/dropdb.result b/mysql-test/suite/innodb/r/dropdb.result new file mode 100644 index 00000000000..f8890784bfc --- /dev/null +++ b/mysql-test/suite/innodb/r/dropdb.result @@ -0,0 +1,9 @@ +# +# Bug #19929435 DROP DATABASE HANGS WITH MALFORMED TABLE +# +set session default_storage_engine=innodb; +create database `b`; +use `b`; +create table `#mysql50#q.q` select 1; +ERROR HY000: Can't create table 'b.#mysql50#q.q' (errno: 1103) +drop database `b`; diff --git a/mysql-test/suite/innodb/t/dropdb.test b/mysql-test/suite/innodb/t/dropdb.test new file mode 100644 index 00000000000..d275b809d00 --- /dev/null +++ b/mysql-test/suite/innodb/t/dropdb.test @@ -0,0 +1,12 @@ +--source include/have_innodb.inc + +--echo # +--echo # Bug #19929435 DROP DATABASE HANGS WITH MALFORMED TABLE +--echo # + +set session default_storage_engine=innodb; +create database `b`; +use `b`; +--error ER_CANT_CREATE_TABLE +create table `#mysql50#q.q` select 1; +drop database `b`; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b8ec8f60f28..1c6763ef93a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6529,7 +6529,8 @@ create_table_def( /* MySQL does the name length check. But we do additional check on the name length here */ - if (strlen(table_name) > MAX_FULL_NAME_LEN) { + const size_t table_name_len = strlen(table_name); + if (table_name_len > MAX_FULL_NAME_LEN) { push_warning_printf( (THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TABLE_NAME, @@ -6538,6 +6539,15 @@ create_table_def( DBUG_RETURN(ER_TABLE_NAME); } + if (table_name[table_name_len - 1] == '/') { + push_warning_printf( + (THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TABLE_NAME, + "InnoDB: Table name is empty"); + + DBUG_RETURN(ER_WRONG_TABLE_NAME); + } + n_cols = form->s->fields; /* We pass 0 as the space id, and determine at a lower level the space From 86375f7fa6a428bfc405f85335685cd1dff25302 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Tue, 22 Sep 2015 14:51:48 +0530 Subject: [PATCH 10/29] Bug #21370329 : FLUSH DES_KEY_FILE MAY NOT WORK Description: The command FLUSH DES_KEY_FILE is expected to reload the DES keys from the file that was specified with the "--des-key-file" option at server startup. But it is not behaving as expected. Analysis: The des file reload is defined within a wrong conditional directive, rendering the command ineffective. Macro "OPENSSL" was used instead of "HAVE_OPENSSL" macro. Fix: "OPENSSL" macro is changed to "HAVE_OPENSSL". --- sql/mysqld.h | 3 ++- sql/sql_reload.cc | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sql/mysqld.h b/sql/mysqld.h index 655fb93df73..0253c2a0b43 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2014, 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 @@ -349,6 +349,7 @@ extern mysql_mutex_t extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_thread_count; extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_thd_remove; #ifdef HAVE_OPENSSL +extern char* des_key_file; extern mysql_mutex_t LOCK_des_key_file; #endif extern mysql_mutex_t LOCK_server_started; diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index b0665a9ea6b..40e350c4ddd 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2011, 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 @@ -25,6 +25,7 @@ #include "hostname.h" // hostname_cache_refresh #include "sql_repl.h" // reset_master, reset_slave #include "debug_sync.h" +#include "des_key_file.h" /** @@ -297,7 +298,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, } } #endif -#ifdef OPENSSL +#ifdef HAVE_OPENSSL if (options & REFRESH_DES_KEY_FILE) { if (des_key_file && load_des_key_file(des_key_file)) From ea9dbef661efdf5079b1b0e33679a863408e3166 Mon Sep 17 00:00:00 2001 From: Aditya A Date: Tue, 22 Sep 2015 16:52:18 +0530 Subject: [PATCH 11/29] Bug#20755615 CREATING INDEX ON A RENAMED COLUMN WITH CASE CRASH .FRM FILE PROBLEM In 5.5 when doing doing a rename of a column ,we ignore the case between old and new column names while comparing them,so if the change is just the case then we don't even mark the field FIELD_IS_RENAMED ,we just update the frm file ,but don't recreate the table as is the norm when alter is used.This leads to inconsistency in the innodb data dictionary which causes index creation to fail. FIX According to the documentation any innodb column rename should trigger rebuild of the table. Therefore for innodb tables we will do a strcmp() between the column names and if there is case change in column name we will trigger a rebuild. --- mysql-test/r/alter_table.result | 17 +++++++++++++++++ mysql-test/t/alter_table.test | 19 +++++++++++++++++++ sql/sql_table.cc | 20 ++++++++++++++++---- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 236d07bccbc..725f2528c29 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -1488,3 +1488,20 @@ CREATE TABLE help_topic (dummy int) ENGINE=innodb; ERROR HY000: Storage engine 'InnoDB' does not support system tables. [mysql.help_topic] use test; # End of Bug#11815557 +# +# Bug#20755615 CREATING INDEX ON A RENAMED +# COLUMN WITH CASE CRASH .FRM FILE +# +CREATE TABLE t1 (D INT) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 MODIFY COLUMN d INT; +ALTER TABLE t1 ADD INDEX (d); +DROP TABLE t1; +CREATE TABLE t1 (`é` int) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 CHANGE `é` `É` INT; +ALTER TABLE t1 ADD INDEX (`É`); +SELECT * FROM t1; +É +10 +DROP TABLE t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index f5d5538c217..8768cd4975c 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1261,3 +1261,22 @@ CREATE TABLE time_zone (dummy int) ENGINE=merge; CREATE TABLE help_topic (dummy int) ENGINE=innodb; use test; --echo # End of Bug#11815557 + +--echo # +--echo # Bug#20755615 CREATING INDEX ON A RENAMED +--echo # COLUMN WITH CASE CRASH .FRM FILE +--echo # + +CREATE TABLE t1 (D INT) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 MODIFY COLUMN d INT; +ALTER TABLE t1 ADD INDEX (d); +DROP TABLE t1; + +CREATE TABLE t1 (`é` int) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 CHANGE `é` `É` INT; +ALTER TABLE t1 ADD INDEX (`É`); +SELECT * FROM t1; +DROP TABLE t1; + diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2951d921e15..0a58d9ade5b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5048,10 +5048,22 @@ mysql_compare_tables(TABLE *table, /* Check if field was renamed */ field->flags&= ~FIELD_IS_RENAMED; - if (my_strcasecmp(system_charset_info, - field->field_name, - tmp_new_field->field_name)) - field->flags|= FIELD_IS_RENAMED; + + /* + InnoDB data dictionary is case sensitive so we should use string case + sensitive comparison between fields. Note: strcmp branch is to be + removed in future when we fix it in InnoDB. + */ + if ((table->s->db_type())->db_type == DB_TYPE_INNODB && + strcmp(field->field_name,tmp_new_field->field_name)) + field->flags|= FIELD_IS_RENAMED; + else + { + if (my_strcasecmp(system_charset_info, + field->field_name, + tmp_new_field->field_name)) + field->flags|= FIELD_IS_RENAMED; + } /* Evaluate changes bitmap and send to check_if_incompatible_data() */ if (!(tmp= field->is_equal(tmp_new_field))) From 8ea58c474fbbcd79e9716379d226b8a46062b350 Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Wed, 30 Sep 2015 10:27:26 +0530 Subject: [PATCH 12/29] BUG 21900800 - ADD OBSOLETE ON MYSQL-CONNECTOR-C-SHARED AND MYSQL-CONNECTOR-C-DEVEL As MySQL Connector C 6.1 is end of life, added conflict with mysql-connector-c-shared dependencies --- packaging/rpm-oel/mysql.spec.in | 5 +++++ packaging/rpm-sles/mysql.spec.in | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/packaging/rpm-oel/mysql.spec.in b/packaging/rpm-oel/mysql.spec.in index bb232fb404d..2d91975f56c 100644 --- a/packaging/rpm-oel/mysql.spec.in +++ b/packaging/rpm-oel/mysql.spec.in @@ -301,6 +301,7 @@ Obsoletes: mysql-devel < %{version}-%{release} Obsoletes: mariadb-devel Provides: mysql-devel = %{version}-%{release} Provides: mysql-devel%{?_isa} = %{version}-%{release} +Conflicts: mysql-connector-c-shared-devel < 6.2 %description devel This package contains the development header files and libraries necessary @@ -323,6 +324,7 @@ Obsoletes: mysql-libs < %{version}-%{release} Obsoletes: mariadb-libs Provides: mysql-libs = %{version}-%{release} Provides: mysql-libs%{?_isa} = %{version}-%{release} +Conflicts: mysql-connector-c-shared < 6.2 %description libs This package contains the shared libraries for MySQL client @@ -913,6 +915,9 @@ fi %endif %changelog +* Tue Sep 29 2015 Balasubramanian Kandasamy - 5.5.47-1 +- Added conflicts to mysql-connector-c-shared dependencies + * Tue Jul 22 2014 Balasubramanian Kandasamy - 5.5.39-5 - Provide mysql-compat-server dependencies diff --git a/packaging/rpm-sles/mysql.spec.in b/packaging/rpm-sles/mysql.spec.in index 23c076332b0..b5fb5b77642 100644 --- a/packaging/rpm-sles/mysql.spec.in +++ b/packaging/rpm-sles/mysql.spec.in @@ -268,6 +268,7 @@ Obsoletes: mariadb-devel Obsoletes: libmysqlclient-devel Provides: mysql-devel = %{version}-%{release} Provides: libmysqlclient-devel = %{version}-%{release} +Conflicts: mysql-connector-c-shared-devel < 6.2 %description devel This package contains the development header files and libraries necessary @@ -293,6 +294,7 @@ Obsoletes: libmysqlclient_r18 < %{version}-%{release} Provides: mysql-libs = %{version}-%{release} Provides: libmysqlclient18 = %{version}-%{release} Provides: libmysqlclient_r18 = %{version}-%{release} +Conflicts: mysql-connector-c-shared < 6.2 %description libs This package contains the shared libraries for MySQL client @@ -779,6 +781,9 @@ fi %attr(755, root, root) %{_libdir}/mysql/libmysqld.so %changelog +* Tue Sep 29 2015 Balasubramanian Kandasamy - 5.5.47-1 +- Added conflicts to mysql-connector-c-shared dependencies + * Mon Oct 06 2014 Balasubramanian Kandasamy - 5.5.41-1 - Backport to 5.5.41 From 415faa122b9c683661dafac82fff414fa6864151 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Thu, 1 Oct 2015 07:45:27 +0530 Subject: [PATCH 13/29] Bug #19434916: FATAL_SIGNAL IN ADD_KEY_EQUAL_FIELDS() WITH UPDATE VIEW USING OUTER SUBQUERY Issue: ----- While resolving a column which refers to a table/view in an outer query, it's respecitve item object is marked with the outer query's select_lex object. But when the column refers to a view or if the column is part of a subquery in the HAVING clause, an Item_ref object is created. While the reference to the outer query is stored by the Item_ref object, the same is not stored in it's real_item. This creates a problem with the IN-TO-EXISTS optmization. When there is an index over the column in the inner query, it will be considered since the column's real_item object will be mistaken for a local field. This will lead to a crash. SOLUTION: --------- Under the current design, the only way to fix this issue is to check the reginfo.join_tab for a NULL value. If yes, the query should not be worrying about the key use. The testcase and comments added as part of the fix for Bug#17766653 have been backported. --- sql/item_subselect.cc | 26 +++++++++++++++++++++++++- sql/sql_select.cc | 12 ++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c9c625db083..43af0b5a3f6 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2002, 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 @@ -1072,6 +1072,27 @@ Item_in_subselect::single_value_transformer(JOIN *join, runtime created Ref item which is deleted at the end of the statement. Thus one of 'substitution' arguments can be broken in case of PS. + + @todo + Why do we use real_item()/substitutional_item() instead of the plain + left_expr? + Because left_expr might be a rollbackable item, and we fail to properly + rollback all copies of left_expr at end of execution, so we want to + avoid creating copies of left_expr as much as possible, so we use + real_item() instead. + Doing a proper rollback is difficult: the change was registered for the + original item which was the left argument of IN. Then this item was + copied to left_expr, which is copied below to substitution->args[0]. To + do a proper rollback, we would have to restore the content + of both copies as well as the original item. There might be more copies, + if AND items have been constructed. + The same applies to the right expression. + However, using real_item()/substitutional_item() brings its own + problems: for example, we lose information that the item is an outer + reference; the item can thus wrongly be considered for a Keyuse (causing + bug#17766653). + When WL#6570 removes the "rolling back" system, all + real_item()/substitutional_item() in this file should be removed. */ substitution= func->create(left_expr->real_item(), subs); DBUG_RETURN(RES_OK); @@ -1157,6 +1178,9 @@ Item_in_subselect::single_value_transformer(JOIN *join, } else { + /* + Grep for "WL#6570" to see the relevant comment about real_item. + */ Item *item= (Item*) select_lex->item_list.head()->real_item(); if (select_lex->table_list.elements) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fa85f3108f2..956551a0786 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3335,6 +3335,18 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond, table_map usable_tables, SARGABLE_PARAM **sargables) { uint exists_optimize= 0; + + if (field->table->reginfo.join_tab == NULL) + { + /* + Due to a bug in IN-to-EXISTS (grep for real_item() in item_subselect.cc + for more info), an index over a field from an outer query might be + considered here, which is incorrect. Their query has been fully + optimized already so their reginfo.join_tab is NULL and we reject them. + */ + return; + } + if (!(field->flags & PART_KEY_FLAG)) { // Don't remove column IS NULL on a LEFT JOIN table From 130b5fbf91520e504194eb59c16a6ce38006ff7a Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Tue, 6 Oct 2015 07:09:36 +0530 Subject: [PATCH 14/29] Bug #19894161: FATAL SIGNAL 11 IN CONVERT_CHARSET_PARTITION_CONSTANT: SQL/SQL_PARTITION..CC:202 Issue: ----- This problem happens under the following conditions: 1) A table partitioned with a character column as the key. 2) The expressions specified in the partition definition requires a charset conversion. This can happen when the server's default collation is different from the expression's collation. 3) INSERT DELAYED is used to insert data into the table. SOLUTION: --------- While creating the delayed_insert object, initialize it with the relevant select_lex. --- sql/sql_insert.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 731aa82fe6e..7bfc7b083ac 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1887,7 +1887,7 @@ public: */ MDL_request grl_protection; - Delayed_insert() + Delayed_insert(SELECT_LEX *current_select) :locks_in_memory(0), table(0),tables_in_use(0),stacked_inserts(0), status(0), handler_thread_initialized(FALSE), group_count(0) { @@ -1898,7 +1898,7 @@ public: USERNAME_LENGTH); thd.current_tablenr=0; thd.command=COM_DELAYED_INSERT; - thd.lex->current_select= 0; // for my_message_sql + thd.lex->current_select= current_select; thd.lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() /* Prevent changes to global.lock_wait_timeout from affecting @@ -2078,7 +2078,7 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, */ if (! (di= find_handler(thd, table_list))) { - if (!(di= new Delayed_insert())) + if (!(di= new Delayed_insert(thd->lex->current_select))) goto end_create; mysql_mutex_lock(&LOCK_thread_count); thread_count++; @@ -2663,6 +2663,16 @@ pthread_handler_t handle_delayed_insert(void *arg) if (di->open_and_lock_table()) goto err; + /* + INSERT DELAYED generally expects thd->lex->current_select to be NULL, + since this is not an attribute of the current thread. This can lead to + problems if the thread that spawned the current one disconnects. + current_select will then point to freed memory. But current_select is + required to resolve the partition function. So, after fulfilling that + requirement, we set the current_select to 0. + */ + thd->lex->current_select= NULL; + /* Tell client that the thread is initialized */ mysql_cond_signal(&di->cond_client); From ecfc7c26166687d4ffb0ae13f518f44f256b9d65 Mon Sep 17 00:00:00 2001 From: "mysql-builder@oracle.com" <> Date: Thu, 8 Oct 2015 15:58:03 +0530 Subject: [PATCH 15/29] From f92dd6ae6fb8922122049957b6ab7e07b6518bc2 Mon Sep 17 00:00:00 2001 From: Mithun C Y Date: Mon, 12 Oct 2015 12:56:36 +0530 Subject: [PATCH 16/29] Bug #20007383: HANDLE_FATAL_SIGNAL (SIG=11) IN UPDATE_REF_AND_KEYS. Issue: ====== The fulltext predicate is inside a subquery and involves an outer reference; it thus cannot be used for FT index look-up, but MySQL does not see it, which causes a illegal access. Solution: ========= Solution is backported from bug#21140088. Outer reference can not be used as argument of the MATCH function. Added check for outer reference. --- mysql-test/r/fulltext.result | 2 +- sql/item_func.cc | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 7788a32ac90..28977b88f32 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -541,7 +541,7 @@ MATCH(a) AGAINST('aaa1* aaa14 aaa15 aaa16' IN BOOLEAN MODE) DROP TABLE t1; CREATE TABLE t1(a TEXT); SELECT GROUP_CONCAT(a) AS st FROM t1 HAVING MATCH(st) AGAINST('test' IN BOOLEAN MODE); -ERROR HY000: Incorrect arguments to AGAINST +ERROR HY000: Incorrect arguments to MATCH DROP TABLE t1; CREATE TABLE t1(a VARCHAR(64), FULLTEXT(a)); INSERT INTO t1 VALUES('awrd bwrd cwrd'),('awrd bwrd cwrd'),('awrd bwrd cwrd'); diff --git a/sql/item_func.cc b/sql/item_func.cc index 67fe15a7f0d..363745d7fd6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.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 @@ -5900,12 +5900,12 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref) const_item_cache=0; for (uint i=1 ; i < arg_count ; i++) { - item=args[i]; - if (item->type() == Item::REF_ITEM) - args[i]= item= *((Item_ref *)item)->ref; - if (item->type() != Item::FIELD_ITEM) + item= args[i]= args[i]->real_item(); + if (item->type() != Item::FIELD_ITEM || + /* Cannot use FTS index with outer table field */ + (item->used_tables() & OUTER_REF_TABLE_BIT)) { - my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST"); + my_error(ER_WRONG_ARGUMENTS, MYF(0), "MATCH"); return TRUE; } } From 3846b085521bce8e4600d4860dc3f2ea5f2ceb2d Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Wed, 14 Oct 2015 11:08:49 +0530 Subject: [PATCH 17/29] Bug #21602056 : CONCURRENT FLUSH PRIVILEGES + REVOKE/GRANT CRASHES IN WILD_CASE_COMPARE! Description:- Executing FLUSH PRIVILEGES and REVOKE/ GRANT concurrently crashes the server. Analysis:- Concurrent FLUSH PRIVILEGES and REVOKE/GRANT might trigger a small time frame in which REVOKE/GRANT fetches the "acl_proxy_user" information as a part of "acl_check_proxy_grant_access()". Meanwhile FLUSH PRIVILEGES deletes the old acl structures as a part of "acl_reload()". After which REVOKE/GRANT tries to access the hostname in "wild_case_compare()" which leads to a crash because of the invalid memory access. Fix:- Mutex lock on "acl_cache" is acquired before fetching "acl_proxy_user" information in "acl_check_proxy_grant_access()". --- sql/sql_acl.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index fea1a209c20..a939ae72ecb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -50,6 +50,7 @@ #include "hostname.h" #include "sql_db.h" #include "sql_array.h" +#include "debug_sync.h" bool mysql_user_table_is_in_short_password_format= false; @@ -1194,6 +1195,8 @@ my_bool acl_reload(THD *thd) mysql_mutex_unlock(&acl_cache->lock); end: close_mysql_tables(thd); + + DEBUG_SYNC(thd, "after_acl_reload"); DBUG_RETURN(return_val); } @@ -7346,11 +7349,14 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user, DBUG_RETURN(FALSE); } + mysql_mutex_lock(&acl_cache->lock); + /* check for matching WITH PROXY rights */ for (uint i=0; i < acl_proxy_users.elements; i++) { ACL_PROXY_USER *proxy= dynamic_element(&acl_proxy_users, i, ACL_PROXY_USER *); + DEBUG_SYNC(thd, "before_proxy_matches"); if (proxy->matches(thd->security_ctx->get_host()->ptr(), thd->security_ctx->user, thd->security_ctx->get_ip()->ptr(), @@ -7358,10 +7364,12 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user, proxy->get_with_grant()) { DBUG_PRINT("info", ("found")); + mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(FALSE); } } + mysql_mutex_unlock(&acl_cache->lock); my_error(ER_ACCESS_DENIED_NO_PASSWORD_ERROR, MYF(0), thd->security_ctx->user, thd->security_ctx->host_or_ip); From a86191c69c95240ba3dcd9858341a30898c34285 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Wed, 14 Oct 2015 12:00:39 +0530 Subject: [PATCH 18/29] Bug #21235226 : THE --ENABLE-CLEARTEXT-PLUGIN IS NOT IMPLEMENTED IN ALL CLIENT PROGRAMS Description: Option "enable-cleartext-plugin" is not available for the following client utilities:- mysqldump mysqlimport mysqlshow mysqlcheck Analysis: The unavailability of this option limits the features like PAM authentication from using the above mentioned utilities. Fix: Option "enable-cleartext-plugin" is implemented in the above mentioned client utilities. --- client/mysqlcheck.c | 15 ++++- client/mysqldump.c | 15 ++++- client/mysqlimport.c | 13 ++++ client/mysqlshow.c | 15 ++++- mysql-test/r/enable_cleartext_plugin.result | 35 ++++++++++ .../t/enable_cleartext_plugin-master.opt | 2 + mysql-test/t/enable_cleartext_plugin.test | 65 +++++++++++++++++++ 7 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 mysql-test/r/enable_cleartext_plugin.result create mode 100644 mysql-test/t/enable_cleartext_plugin-master.opt create mode 100644 mysql-test/t/enable_cleartext_plugin.test diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index ca06a85bec0..0d5570434e4 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2011, 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 @@ -42,6 +42,8 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0, opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0, opt_write_binlog= 1; static uint verbose = 0, opt_mysql_port=0; +static uint opt_enable_cleartext_plugin= 0; +static my_bool using_opt_enable_cleartext_plugin= 0; static int my_end_arg; static char * opt_mysql_unix_port = 0; static char *opt_password = 0, *current_user = 0, @@ -110,6 +112,10 @@ static struct my_option my_long_options[] = "Default authentication client-side plugin to use.", &opt_default_auth, &opt_default_auth, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN, + "Enable/disable the clear text authentication plugin.", + &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"fast",'F', "Check only tables that haven't been closed properly.", &opt_fast, &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -326,6 +332,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), verbose++; break; case 'V': print_version(); exit(0); + case OPT_ENABLE_CLEARTEXT_PLUGIN: + using_opt_enable_cleartext_plugin= TRUE; + break; case OPT_MYSQL_PROTOCOL: opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, opt->name); @@ -880,6 +889,10 @@ static int dbConnect(char *host, char *user, char *passwd) if (opt_default_auth && *opt_default_auth) mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth); + if (using_opt_enable_cleartext_plugin) + mysql_options(&mysql_connection, MYSQL_ENABLE_CLEARTEXT_PLUGIN, + (char *) &opt_enable_cleartext_plugin); + mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd, NULL, opt_mysql_port, opt_mysql_unix_port, 0))) diff --git a/client/mysqldump.c b/client/mysqldump.c index 2a873903d60..6bb249134e8 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -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 @@ -129,6 +129,8 @@ static ulong opt_compatible_mode= 0; #define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2 #define MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL 1 #define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2 +static uint opt_enable_cleartext_plugin= 0; +static my_bool using_opt_enable_cleartext_plugin= 0; static uint opt_mysql_port= 0, opt_master_data; static uint opt_slave_data; static uint my_end_arg; @@ -513,6 +515,10 @@ static struct my_option my_long_options[] = "Default authentication client-side plugin to use.", &opt_default_auth, &opt_default_auth, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN, + "Enable/disable the clear text authentication plugin.", + &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -883,6 +889,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; break; } + case (int) OPT_ENABLE_CLEARTEXT_PLUGIN: + using_opt_enable_cleartext_plugin= TRUE; + break; case (int) OPT_MYSQL_PROTOCOL: opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, opt->name); @@ -1485,6 +1494,10 @@ static int connect_to_db(char *host, char *user,char *passwd) if (opt_default_auth && *opt_default_auth) mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth); + if (using_opt_enable_cleartext_plugin) + mysql_options(&mysql_connection, MYSQL_ENABLE_CLEARTEXT_PLUGIN, + (char *) &opt_enable_cleartext_plugin); + if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd, NULL,opt_mysql_port,opt_mysql_unix_port, 0))) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 813c1baf793..f71111f7e9e 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -49,6 +49,8 @@ static char *opt_password=0, *current_user=0, *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0, *opt_columns=0, *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME; +static uint opt_enable_cleartext_plugin= 0; +static my_bool using_opt_enable_cleartext_plugin= 0; static uint opt_mysql_port= 0, opt_protocol= 0; static char * opt_mysql_unix_port=0; static char *opt_plugin_dir= 0, *opt_default_auth= 0; @@ -88,6 +90,10 @@ static struct my_option my_long_options[] = GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"delete", 'd', "First delete all rows from table.", &opt_delete, &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN, + "Enable/disable the clear text authentication plugin.", + &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"fields-terminated-by", OPT_FTB, "Fields in the input file are terminated by the given string.", &fields_terminated, &fields_terminated, 0, @@ -234,6 +240,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_local_file=1; break; #endif + case OPT_ENABLE_CLEARTEXT_PLUGIN: + using_opt_enable_cleartext_plugin= TRUE; + break; case OPT_MYSQL_PROTOCOL: opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, opt->name); @@ -435,6 +444,10 @@ static MYSQL *db_connect(char *host, char *database, if (opt_default_auth && *opt_default_auth) mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); + if (using_opt_enable_cleartext_plugin) + mysql_options(mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN, + (char*)&opt_enable_cleartext_plugin); + mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset); if (!(mysql_real_connect(mysql,host,user,passwd, database,opt_mysql_port,opt_mysql_unix_port, diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 5677681541b..a6705548bcb 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.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 @@ -37,6 +37,8 @@ static uint my_end_arg= 0; static uint opt_verbose=0; static char *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME; static char *opt_plugin_dir= 0, *opt_default_auth= 0; +static uint opt_enable_cleartext_plugin= 0; +static my_bool using_opt_enable_cleartext_plugin= 0; #ifdef HAVE_SMEM static char *shared_memory_base_name=0; @@ -133,6 +135,10 @@ int main(int argc, char **argv) if (opt_default_auth && *opt_default_auth) mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); + if (using_opt_enable_cleartext_plugin) + mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN, + (char*)&opt_enable_cleartext_plugin); + if (!(mysql_real_connect(&mysql,host,user,opt_password, (first_argument_uses_wildcards) ? "" : argv[0],opt_mysql_port,opt_mysql_unix_port, @@ -195,6 +201,10 @@ static struct my_option my_long_options[] = "Default authentication client-side plugin to use.", &opt_default_auth, &opt_default_auth, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN, + "Enable/disable the clear text authentication plugin.", + &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Connect to host.", &host, &host, 0, GET_STR, @@ -309,6 +319,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_protocol = MYSQL_PROTOCOL_PIPE; #endif break; + case (int) OPT_ENABLE_CLEARTEXT_PLUGIN: + using_opt_enable_cleartext_plugin= TRUE; + break; case OPT_MYSQL_PROTOCOL: opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, opt->name); diff --git a/mysql-test/r/enable_cleartext_plugin.result b/mysql-test/r/enable_cleartext_plugin.result new file mode 100644 index 00000000000..b57a6fc0e16 --- /dev/null +++ b/mysql-test/r/enable_cleartext_plugin.result @@ -0,0 +1,35 @@ +# +# Bug #21235226 : THE --ENABLE-CLEARTEXT-PLUGIN IS NOT IMPLEMENTED +# IN ALL CLIENT PROGRAMS +# +CREATE DATABASE db21235226; +USE db21235226; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2); +SELECT * FROM t1; +a +1 +2 +CREATE USER uplain@localhost IDENTIFIED WITH 'cleartext_plugin_server' + AS 'cleartext_test'; +GRANT ALL PRIVILEGES ON *.* TO uplain@localhost; +mysqldump: Got error: 2059: Authentication plugin 'mysql_clear_password' cannot be loaded: plugin not enabled when trying to connect +SELECT * FROM t1; +a +mysqlimport: Error: 2059 Authentication plugin 'mysql_clear_password' cannot be loaded: plugin not enabled +SELECT * FROM t1; +a +1 +2 +mysqlshow: Authentication plugin 'mysql_clear_password' cannot be loaded: plugin not enabled +Database: db21235226 ++--------+ +| Tables | ++--------+ +| t1 | ++--------+ +mysqlcheck: Got error: 2059: Authentication plugin 'mysql_clear_password' cannot be loaded: plugin not enabled when trying to connect +db21235226.t1 OK +DROP TABLE t1; +DROP DATABASE db21235226; +DROP USER uplain@localhost; diff --git a/mysql-test/t/enable_cleartext_plugin-master.opt b/mysql-test/t/enable_cleartext_plugin-master.opt new file mode 100644 index 00000000000..3536d102387 --- /dev/null +++ b/mysql-test/t/enable_cleartext_plugin-master.opt @@ -0,0 +1,2 @@ +$PLUGIN_AUTH_OPT +$PLUGIN_AUTH_LOAD diff --git a/mysql-test/t/enable_cleartext_plugin.test b/mysql-test/t/enable_cleartext_plugin.test new file mode 100644 index 00000000000..e2ae35c8e73 --- /dev/null +++ b/mysql-test/t/enable_cleartext_plugin.test @@ -0,0 +1,65 @@ +--source include/have_plugin_auth.inc +--source include/not_embedded.inc + +--echo # +--echo # Bug #21235226 : THE --ENABLE-CLEARTEXT-PLUGIN IS NOT IMPLEMENTED +--echo # IN ALL CLIENT PROGRAMS +--echo # + +CREATE DATABASE db21235226; +USE db21235226; + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2); +SELECT * FROM t1; + +CREATE USER uplain@localhost IDENTIFIED WITH 'cleartext_plugin_server' + AS 'cleartext_test'; + +GRANT ALL PRIVILEGES ON *.* TO uplain@localhost; + +#Reset the LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN variable. +let LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN=N; + +#Scenario 1 : MYSQL_DUMP without --enable_cleartext_plugin +# Should get CR_AUTH_PLUGIN_CANNOT_LOAD error +--error 2 +--exec $MYSQL_DUMP --user=uplain --password=cleartext_test --tab=$MYSQLTEST_VARDIR/tmp/ db21235226 2>&1 + +#Scenario 2 : MYSQL_DUMP with --enable_cleartext_plugin +--exec $MYSQL_DUMP --enable_cleartext_plugin --user=uplain --password=cleartext_test --tab=$MYSQLTEST_VARDIR/tmp/ db21235226 +--exec $MYSQL --enable_cleartext_plugin --user=uplain --password=cleartext_test db21235226 < $MYSQLTEST_VARDIR/tmp/t1.sql +SELECT * FROM t1; + +#Scenario 3 : MYSQL_IMPORT without --enable_cleartext_plugin +# Should get CR_AUTH_PLUGIN_CANNOT_LOAD error +--replace_regex /.*mysqlimport(\.exe)*/mysqlimport/ +--error 1 +--exec $MYSQL_IMPORT --user=uplain --password=cleartext_test --silent db21235226 $MYSQLTEST_VARDIR/tmp/t1.txt 2>&1 + +#Scenario 4 : MYSQL_IMPORT with --enable_cleartext_plugin +--exec $MYSQL_IMPORT --enable_cleartext_plugin --user=uplain --password=cleartext_test --silent db21235226 $MYSQLTEST_VARDIR/tmp/t1.txt +SELECT * FROM t1; + +#Scenario 5 : MYSQL_SHOW without --enable_cleartext_plugin +# Should get CR_AUTH_PLUGIN_CANNOT_LOAD error +--replace_regex /.*mysqlshow(\.exe)*/mysqlshow/ +--error 1 +--exec $MYSQL_SHOW --user=uplain --password=cleartext_test db21235226 2>&1 + +#Scenario 6 : MYSQL_SHOW with --enable_cleartext_plugin +--exec $MYSQL_SHOW --enable_cleartext_plugin --user=uplain --password=cleartext_test db21235226 + +#Scenario 7 : MYSQL_CHECK without --enable_cleartext_plugin +# Should get CR_AUTH_PLUGIN_CANNOT_LOAD error +--replace_regex /.*mysqlcheck(\.exe)*/mysqlcheck/ +--error 2 +--exec $MYSQL_CHECK --user=uplain --password=cleartext_test db21235226 t1 2>&1 + +#Scenario 8 : MYSQL_CHECK with --enable_cleartext_plugin +--exec $MYSQL_CHECK --enable_cleartext_plugin --user=uplain --password=cleartext_test db21235226 t1 + +#Cleanup +DROP TABLE t1; +DROP DATABASE db21235226; +DROP USER uplain@localhost; From 74a503b4ceecf0e813666fc8cdbcb92e580442bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Terje=20R=C3=B8sten?= Date: Fri, 16 Oct 2015 09:56:09 +0200 Subject: [PATCH 19/29] BUG#22024764 MAIN.EVENTS_1 FAILS BECAUSE IT USES ENDDATE OF 20151010 Move date 10 years forward to let test pass for some more years. --- mysql-test/r/events_1.result | 2 +- mysql-test/t/events_1.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/events_1.result b/mysql-test/r/events_1.result index 29e81975c87..05223b0afcf 100644 --- a/mysql-test/r/events_1.result +++ b/mysql-test/r/events_1.result @@ -114,7 +114,7 @@ create table t_event3 (a int, b float); drop event if exists event3; Warnings: Note 1305 Event event3 does not exist -create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); +create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20251010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); select count(*) from t_event3; count(*) 0 diff --git a/mysql-test/t/events_1.test b/mysql-test/t/events_1.test index 7f31e3fc881..bb71b334219 100644 --- a/mysql-test/t/events_1.test +++ b/mysql-test/t/events_1.test @@ -125,7 +125,7 @@ drop event existant; create table t_event3 (a int, b float); drop event if exists event3; -create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); +create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20251010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); let $wait_condition=SELECT count(*)=0 from t_event3; --source include/wait_condition.inc select count(*) from t_event3; From dea23408660130f04af7e954811122d86656900f Mon Sep 17 00:00:00 2001 From: Mithun C Y Date: Thu, 22 Oct 2015 17:02:12 +0530 Subject: [PATCH 20/29] Bug #20447262: REPEATED EXECUTION OF PREPARED STATEMENTS FAILS, IF DEFAULT DATABASE IS CHANGED. Issue: ====== While re-preparing the statement in Prepared_statement::swap_prepared_statement for swapping the database of PS we only swapped the db string but not its length. This resulted in mismatch between the actual string and its length. In one particular case where db of PS was dropped, we have db as null pointer and length as non-zero. strdup which used above values resulted in invalid memory access. Solution: ========= In Prepared_statement::swap_prepared_statement also swap db_length along with db variable. Also, remove DBUG_ASSERT(db_length == copy->db_length) as this have no meaning if they are 2 different entities. --- sql/sql_prepare.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 48d23cd5d21..f2f74c68085 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2002, 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 @@ -3668,8 +3668,8 @@ Prepared_statement::swap_prepared_statement(Prepared_statement *copy) swap_variables(LEX_STRING, name, copy->name); /* Ditto */ swap_variables(char *, db, copy->db); + swap_variables(size_t, db_length, copy->db_length); - DBUG_ASSERT(db_length == copy->db_length); DBUG_ASSERT(param_count == copy->param_count); DBUG_ASSERT(thd == copy->thd); last_error[0]= '\0'; From a60740607c9581ed2bf92bdd087139ea8d872484 Mon Sep 17 00:00:00 2001 From: Srikanth B R Date: Mon, 26 Oct 2015 16:19:11 +0530 Subject: [PATCH 21/29] BUG#22084221 : TEST IMPROVEMENT FOR MAIN.EVENTS_1 Issue: main.events_1 will fail after 10-10-2015 due to hardcoded dates specified with events. Fix: Replace harcoded dates with current dates and offset. --- mysql-test/r/events_1.result | 2 +- mysql-test/t/events_1.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/events_1.result b/mysql-test/r/events_1.result index 05223b0afcf..679eb63be35 100644 --- a/mysql-test/r/events_1.result +++ b/mysql-test/r/events_1.result @@ -114,7 +114,7 @@ create table t_event3 (a int, b float); drop event if exists event3; Warnings: Note 1305 Event event3 does not exist -create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20251010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); +create event event3 on schedule every 50 + 10 minute starts date_add(curdate(), interval 5 minute) ends date_add(curdate(), interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); select count(*) from t_event3; count(*) 0 diff --git a/mysql-test/t/events_1.test b/mysql-test/t/events_1.test index bb71b334219..032d5ecd380 100644 --- a/mysql-test/t/events_1.test +++ b/mysql-test/t/events_1.test @@ -125,7 +125,7 @@ drop event existant; create table t_event3 (a int, b float); drop event if exists event3; -create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20251010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); +create event event3 on schedule every 50 + 10 minute starts date_add(curdate(), interval 5 minute) ends date_add(curdate(), interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); let $wait_condition=SELECT count(*)=0 from t_event3; --source include/wait_condition.inc select count(*) from t_event3; From 1942506b82897e498493cc3ec274a2b402c4d105 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Thu, 29 Oct 2015 13:35:32 +0530 Subject: [PATCH 22/29] DESCRIPTION =========== When doing an upgrade, you execute mysql_upgrade. If mysql_upgrade fails to connect or it connects with a user without the proper privileges, it will return the error: FATAL ERROR: Upgrade failed which is not very informative. ANALYSIS ======== In main() and check_version_match(), the condition for errors are clubbed together and throw the same error msg. The functions need to be splitted up and the corresponding error msgs have to be displayed. FIX === Splitted the functions and added the specific error msg. --- client/mysql_upgrade.c | 36 ++++++++++++++++++++----------- mysql-test/r/mysql_upgrade.result | 8 ++++++- mysql-test/t/mysql_upgrade.test | 9 ++++++++ 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 33f9f030c1e..fcbde2653e8 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1,5 +1,5 @@ /* - 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 @@ -862,10 +862,17 @@ static int check_version_match(void) if (init_dynamic_string(&ds_version, NULL, NAME_CHAR_LEN, NAME_CHAR_LEN)) die("Out of memory"); - if (run_query("show variables like 'version'", - &ds_version, FALSE) || - extract_variable_from_show(&ds_version, version_str)) + + if (run_query("show variables like 'version'", &ds_version, FALSE)) { + fprintf(stderr, "Error: Failed while fetching Server version! Could be" + " due to unauthorized access.\n"); + dynstr_free(&ds_version); + return 1; /* Query failed */ + } + if (extract_variable_from_show(&ds_version, version_str)) + { + fprintf(stderr, "Error: Failed while extracting Server version!\n"); dynstr_free(&ds_version); return 1; /* Query failed */ } @@ -955,15 +962,20 @@ int main(int argc, char **argv) /* Run "mysqlcheck" and "mysql_fix_privilege_tables.sql" */ - if ((!opt_systables_only && - (run_mysqlcheck_fixnames() || run_mysqlcheck_upgrade())) || - run_sql_fix_privilege_tables()) + if (!opt_systables_only) { - /* - The upgrade failed to complete in some way or another, - significant error message should have been printed to the screen - */ - die("Upgrade failed" ); + if (run_mysqlcheck_fixnames()) + die("Error during call to mysql_check for fixing the db/tables names."); + + if (run_mysqlcheck_upgrade()) + die("Error during call to mysql_check for upgrading the tables names."); + } + + if (run_sql_fix_privilege_tables()) + { + /* Specific error msg (if present) would be printed in the function call + * above */ + die("Upgrade failed"); } verbose("OK"); diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index 8ce3f426375..6ba874f327a 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -86,7 +86,7 @@ mysql.user OK DROP USER mysqltest1@'%'; Run mysql_upgrade with a non existing server socket mysqlcheck: Got error: 2005: Unknown MySQL server host 'not_existing_host' (errno) when trying to connect -FATAL ERROR: Upgrade failed +FATAL ERROR: Error during call to mysql_check for fixing the db/tables names. set GLOBAL sql_mode='STRICT_ALL_TABLES,ANSI_QUOTES,NO_ZERO_DATE'; mtr.global_suppressions OK mtr.test_suppressions OK @@ -226,4 +226,10 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +# +# Bug #21489398: MYSQL_UPGRADE: FATAL ERROR: UPGRADE FAILED - IMPROVE ERROR +# +Run mysql_upgrade with unauthorized access +Error: Failed while fetching Server version! Could be due to unauthorized access. +FATAL ERROR: Upgrade failed End of tests diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index c52a328c28b..faf7ed21a28 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -124,4 +124,13 @@ let $MYSQLD_DATADIR= `select @@datadir`; # so the following command should never fail. --remove_file $MYSQLD_DATADIR/mysql_upgrade_info + +--echo # +--echo # Bug #21489398: MYSQL_UPGRADE: FATAL ERROR: UPGRADE FAILED - IMPROVE ERROR +--echo # + +--echo Run mysql_upgrade with unauthorized access +--error 1 +--exec $MYSQL_UPGRADE --skip-verbose --user=root --password=wrong_password 2>&1 + --echo End of tests From 9b6ac73419256cf3c9554d8a782c4eaee6c6cf79 Mon Sep 17 00:00:00 2001 From: Chaithra Gopalareddy Date: Mon, 2 Nov 2015 16:30:57 +0530 Subject: [PATCH 23/29] Bug#20755389 SERVER CRASHES IN ITEM_FUNC_GROUP_CONCAT::FIX_FIELDS ON 2ND EXECUTION OF PS Description: ------------ When MySQL calls 'EXECUTE stmt' firstly to deal with ORDER BY clause which is similar with 'ORDER BY 1,(t2a.f2+1)' in find_order_in_list(), it believes the first expression is a position, the function replaces the pointer of the first expression with Item_field object associated with a temporary table field, then releases it after the end of the execution, that behavior destroys the pointer of first expression. After that, when MySQL calls 'EXECUTE stmt' once more, the first expression points to an invalid pointer, so it crashed. Fix: ---- If an item of ORDER clause is a location, reset 'args' with a original value. --- sql/item_sum.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f491795c449..b63cbbd3c26 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3184,7 +3184,9 @@ void Item_func_group_concat::cleanup() ORDER **order_ptr= order; for (uint i= 0; i < arg_count_order; i++) { - (*order_ptr)->item= &args[arg_count_field + i]; + + if ((*order_ptr)->counter_used) + args[arg_count_field + i]= (*order_ptr)->item_ptr; order_ptr++; } DBUG_VOID_RETURN; From 5e9a50efc37c233f1e2a3616f8bcb36315aba4c2 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Tue, 3 Nov 2015 07:43:54 +0530 Subject: [PATCH 24/29] Bug #22023218: MYSQL 5.5: MAIN.FULLTEXT HAS VALGRIND ISSUES. Issue ----- This problem occurs when varchar columns are used in a internal temporary table. The type of the field is set incorrectly to the generic FIELD_NORMAL type. This in turn results in an inaccurate calculation of the record length. Valgrind issues will occur since initialization has not happend for some bytes. Fix ---- While creating the temporary table, the type of the field needs to be to set FIELD_VARCHAR. This will allow myisam to calculate the record length accurately. This fix is a backport of BUG#13350136. --- sql/sql_select.cc | 36 ++++++++++++++++++++++++++---------- storage/myisam/mi_create.c | 5 ++--- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 956551a0786..96f60d46651 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10313,8 +10313,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, uint temp_pool_slot=MY_BIT_NONE; uint fieldnr= 0; ulong reclength, string_total_length; - bool using_unique_constraint= 0; - bool use_packed_rows= 0; + bool using_unique_constraint= false; + bool use_packed_rows= false; bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS); char *tmpname,path[FN_REFLEN]; uchar *pos, *group_buff, *bitmaps; @@ -10370,10 +10370,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, { (*tmp->item)->marker=4; // Store null in key if ((*tmp->item)->max_length >= CONVERT_IF_BIGGER_TO_BLOB) - using_unique_constraint=1; + using_unique_constraint= true; } if (param->group_length >= MAX_BLOB_WIDTH) - using_unique_constraint=1; + using_unique_constraint= true; if (group) distinct=0; // Can't use distinct } @@ -10588,6 +10588,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, *blob_field++= fieldnr; blob_count++; } + + if (new_field->real_type() == MYSQL_TYPE_STRING || + new_field->real_type() == MYSQL_TYPE_VARCHAR) + { + string_count++; + string_total_length+= new_field->pack_length(); + } + if (item->marker == 4 && item->maybe_null) { group_null_items++; @@ -10638,7 +10646,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, if (group && (param->group_parts > table->file->max_key_parts() || param->group_length > table->file->max_key_length())) - using_unique_constraint=1; + using_unique_constraint= true; } else { @@ -10791,6 +10799,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, field->real_type() == MYSQL_TYPE_STRING && length >= MIN_STRING_LENGTH_TO_PACK_ROWS) recinfo->type=FIELD_SKIP_ENDSPACE; + else if (use_packed_rows && + field->real_type() == MYSQL_TYPE_VARCHAR && + length >= MIN_STRING_LENGTH_TO_PACK_ROWS) + recinfo->type= FIELD_VARCHAR; else recinfo->type=FIELD_NORMAL; if (!--hidden_field_count) @@ -11229,11 +11241,15 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, create_info.data_file_length= ~(ulonglong) 0; if ((error=mi_create(share->table_name.str, share->keys, &keydef, - (uint) (param->recinfo-param->start_recinfo), - param->start_recinfo, - share->uniques, &uniquedef, - &create_info, - HA_CREATE_TMP_TABLE))) + (uint) (param->recinfo-param->start_recinfo), + param->start_recinfo, + share->uniques, &uniquedef, + &create_info, + HA_CREATE_TMP_TABLE | + ((share->db_create_options & HA_OPTION_PACK_RECORD) ? + HA_PACK_RECORD : 0) + ))) + { table->file->print_error(error,MYF(0)); /* purecov: inspected */ /* diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 8873b8f71fb..02fa88cbab9 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, 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 @@ -462,7 +462,6 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, key_del[i]=HA_OFFSET_ERROR; unique_key_parts=0; - offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH; for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++) { uniquedef->key=keys+i; @@ -727,7 +726,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, #endif } /* Create extra keys for unique definitions */ - offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH; + offset=real_reclength - uniques * MI_UNIQUE_HASH_LENGTH; bzero((char*) &tmp_keydef,sizeof(tmp_keydef)); bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg)); for (i=0; i < uniques ; i++) From 75bfdea40f9c2954d8eadccbadc795231e310ab7 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Tue, 3 Nov 2015 07:59:57 +0530 Subject: [PATCH 25/29] Bug #22123583: MYSQL 5.5: MAIN.SP HAS VALGRIND ISSUES Issue: ----- When a varchar column is used to fill the record in an internal temporary table, the length of the string stored in the column is not taken into account. Instead the default length of packed data is used to copy with memmove. This will cause valgrind issues since some bytes are uninitialized. SOLUTION: --------- The solution is to take into account the length of the string stored in the column while filling the record. This fix is a backport of BUG#13389854. --- sql/field.h | 20 +++--- sql/field_conv.cc | 163 ++++++++++++++++++++++++++-------------------- 2 files changed, 104 insertions(+), 79 deletions(-) diff --git a/sql/field.h b/sql/field.h index 73922460037..cc4b79a9e4a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -209,7 +209,7 @@ public: DBUG_ENTER("Field::pack_length_from_metadata"); DBUG_RETURN(field_metadata); } - virtual uint row_pack_length() { return 0; } + virtual uint row_pack_length() const { return 0; } virtual int save_field_metadata(uchar *first_byte) { return do_save_field_metadata(first_byte); } @@ -733,7 +733,7 @@ public: int store_decimal(const my_decimal *); my_decimal *val_decimal(my_decimal *); uint is_equal(Create_field *new_field); - uint row_pack_length() { return pack_length(); } + uint row_pack_length() const { return pack_length(); } uint32 pack_length_from_metadata(uint field_metadata) { uint32 length= pack_length(); DBUG_PRINT("result", ("pack_length_from_metadata(%d): %u", @@ -923,7 +923,7 @@ public: uint size_of() const { return sizeof(*this); } uint32 pack_length() const { return (uint32) bin_size; } uint pack_length_from_metadata(uint field_metadata); - uint row_pack_length() { return pack_length(); } + uint row_pack_length() const { return pack_length(); } bool compatible_field_size(uint field_metadata, Relay_log_info *rli, uint16 mflags, int *order_var); uint is_equal(Create_field *new_field); @@ -1195,7 +1195,7 @@ public: int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); uint32 pack_length() const { return sizeof(float); } - uint row_pack_length() { return pack_length(); } + uint row_pack_length() const { return pack_length(); } void sql_type(String &str) const; private: int do_save_field_metadata(uchar *first_byte); @@ -1235,7 +1235,7 @@ public: int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); uint32 pack_length() const { return sizeof(double); } - uint row_pack_length() { return pack_length(); } + uint row_pack_length() const { return pack_length(); } void sql_type(String &str) const; private: int do_save_field_metadata(uchar *first_byte); @@ -1621,7 +1621,7 @@ public: } bool compatible_field_size(uint field_metadata, Relay_log_info *rli, uint16 mflags, int *order_var); - uint row_pack_length() { return field_length; } + uint row_pack_length() const { return field_length; } int pack_cmp(const uchar *a,const uchar *b,uint key_length, my_bool insert_or_update); int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update); @@ -1671,7 +1671,7 @@ public: enum_field_types type() const { return MYSQL_TYPE_VARCHAR; } bool match_collation_to_optimize_range() const { return TRUE; } enum ha_base_keytype key_type() const; - uint row_pack_length() { return field_length; } + uint row_pack_length() const { return field_length; } bool zero_pack() const { return 0; } int reset(void) { bzero(ptr,field_length+length_bytes); return 0; } uint32 pack_length() const { return (uint32) field_length+length_bytes; } @@ -1797,7 +1797,7 @@ public: */ uint32 pack_length_no_ptr() const { return (uint32) (packlength); } - uint row_pack_length() { return pack_length_no_ptr(); } + uint row_pack_length() const { return pack_length_no_ptr(); } uint32 sort_length() const; virtual uint32 max_data_length() const { @@ -1960,7 +1960,7 @@ public: enum_field_types real_type() const { return MYSQL_TYPE_ENUM; } uint pack_length_from_metadata(uint field_metadata) { return (field_metadata & 0x00ff); } - uint row_pack_length() { return pack_length(); } + uint row_pack_length() const { return pack_length(); } virtual bool zero_pack() const { return 0; } bool optimize_range(uint idx, uint part) { return 0; } bool eq_def(Field *field); @@ -2081,7 +2081,7 @@ public: uint32 pack_length() const { return (uint32) (field_length + 7) / 8; } uint32 pack_length_in_rec() const { return bytes_in_rec; } uint pack_length_from_metadata(uint field_metadata); - uint row_pack_length() + uint row_pack_length() const { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); } bool compatible_field_size(uint metadata, Relay_log_info *rli, uint16 mflags, int *order_var); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 14c4fd257fe..7eb49b9dd92 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -447,79 +447,99 @@ static void do_expand_string(Copy_field *copy) copy->to_length-copy->from_length, ' '); } +/** + Find how many bytes should be copied between Field_varstring fields + so that only the bytes in use in the 'from' field are copied. + Handles single and multi-byte charsets. Adds warning if not all + bytes in 'from' will fit into 'to'. -static void do_varstring1(Copy_field *copy) + @param to Variable length field we're copying to + @param from Variable length field we're copying from + + @return Number of bytes that should be copied from 'from' to 'to'. +*/ +static uint get_varstring_copy_length(Field_varstring *to, + const Field_varstring *from) { - uint length= (uint) *(uchar*) copy->from_ptr; - if (length > copy->to_length- 1) + CHARSET_INFO * const cs= from->charset(); + const bool is_multibyte_charset= (cs->mbmaxlen != 1); + const uint to_byte_length= to->row_pack_length(); + + uint bytes_to_copy; + if (from->length_bytes == 1) + bytes_to_copy= *from->ptr; + else + bytes_to_copy= uint2korr(from->ptr); + + if (is_multibyte_charset) { - length=copy->to_length - 1; - if (copy->from_field->table->in_use->count_cuted_fields) - copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, - WARN_DATA_TRUNCATED, 1); + int well_formed_error; + const char *from_beg= reinterpret_cast(from->ptr + from->length_bytes); + const uint to_char_length= (to_byte_length) / cs->mbmaxlen; + const uint from_byte_length= bytes_to_copy; + bytes_to_copy= + cs->cset->well_formed_len(cs, from_beg, + from_beg + from_byte_length, + to_char_length, + &well_formed_error); + if (bytes_to_copy < from_byte_length) + { + if (from->table->in_use->count_cuted_fields) + to->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, + WARN_DATA_TRUNCATED, 1); + } } - *(uchar*) copy->to_ptr= (uchar) length; - memcpy(copy->to_ptr+1, copy->from_ptr + 1, length); -} - - -static void do_varstring1_mb(Copy_field *copy) -{ - int well_formed_error; - CHARSET_INFO *cs= copy->from_field->charset(); - uint from_length= (uint) *(uchar*) copy->from_ptr; - const uchar *from_ptr= copy->from_ptr + 1; - uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen; - uint length= cs->cset->well_formed_len(cs, (char*) from_ptr, - (char*) from_ptr + from_length, - to_char_length, &well_formed_error); - if (length < from_length) + else { - if (current_thd->count_cuted_fields) - copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, - WARN_DATA_TRUNCATED, 1); + if (bytes_to_copy > (to_byte_length)) + { + bytes_to_copy= to_byte_length; + if (from->table->in_use->count_cuted_fields) + to->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, + WARN_DATA_TRUNCATED, 1); + } } - *copy->to_ptr= (uchar) length; - memcpy(copy->to_ptr + 1, from_ptr, length); + return bytes_to_copy; } +/** + A variable length string field consists of: + (a) 1 or 2 length bytes, depending on the VARCHAR column definition + (b) as many relevant character bytes, as defined in the length byte(s) + (c) unused padding up to the full length of the column -static void do_varstring2(Copy_field *copy) + This function only copies (a) and (b) + + Condition for using this function: to and from must use the same + number of bytes for length, i.e: to->length_bytes==from->length_bytes + + @param to Variable length field we're copying to + @param from Variable length field we're copying from +*/ +static void copy_field_varstring(Field_varstring * const to, + const Field_varstring * const from) { - uint length=uint2korr(copy->from_ptr); - if (length > copy->to_length- HA_KEY_BLOB_LENGTH) - { - length=copy->to_length-HA_KEY_BLOB_LENGTH; - if (copy->from_field->table->in_use->count_cuted_fields) - copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, - WARN_DATA_TRUNCATED, 1); - } - int2store(copy->to_ptr,length); - memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH, - length); + const uint length_bytes= from->length_bytes; + DBUG_ASSERT(length_bytes == to->length_bytes); + DBUG_ASSERT(length_bytes == 1 || length_bytes == 2); + + const uint bytes_to_copy= get_varstring_copy_length(to, from); + if (length_bytes == 1) + *to->ptr= static_cast(bytes_to_copy); + else + int2store(to->ptr, bytes_to_copy); + + // memcpy should not be used for overlaping memory blocks + DBUG_ASSERT(to->ptr != from->ptr); + memcpy(to->ptr + length_bytes, from->ptr + length_bytes, bytes_to_copy); } - -static void do_varstring2_mb(Copy_field *copy) +static void do_varstring(Copy_field *copy) { - int well_formed_error; - CHARSET_INFO *cs= copy->from_field->charset(); - uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen; - uint from_length= uint2korr(copy->from_ptr); - const uchar *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH; - uint length= cs->cset->well_formed_len(cs, (char*) from_beg, - (char*) from_beg + from_length, - char_length, &well_formed_error); - if (length < from_length) - { - if (current_thd->count_cuted_fields) - copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, - WARN_DATA_TRUNCATED, 1); - } - int2store(copy->to_ptr, length); - memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length); + copy_field_varstring(static_cast(copy->to_field), + static_cast(copy->from_field)); } - + /*************************************************************************** ** The different functions that fills in a Copy_field class @@ -711,11 +731,7 @@ Copy_field::get_copy_func(Field *to,Field *from) ((Field_varstring*) from)->length_bytes) return do_field_string; else - return (((Field_varstring*) to)->length_bytes == 1 ? - (from->charset()->mbmaxlen == 1 ? do_varstring1 : - do_varstring1_mb) : - (from->charset()->mbmaxlen == 1 ? do_varstring2 : - do_varstring2_mb)); + return do_varstring; } else if (to_length < from_length) return (from->charset()->mbmaxlen == 1 ? @@ -771,8 +787,20 @@ Copy_field::get_copy_func(Field *to,Field *from) int field_conv(Field *to,Field *from) { if (to->real_type() == from->real_type() && - !(to->type() == MYSQL_TYPE_BLOB && to->table->copy_blobs)) + !(to->type() == MYSQL_TYPE_BLOB && to->table->copy_blobs) && + to->charset() == from->charset()) { + if (to->real_type() == MYSQL_TYPE_VARCHAR && + from->real_type() == MYSQL_TYPE_VARCHAR) + { + Field_varstring *to_vc= static_cast(to); + const Field_varstring *from_vc= static_cast(from); + if (to_vc->length_bytes == from_vc->length_bytes) + { + copy_field_varstring(to_vc, from_vc); + return 0; + } + } if (to->pack_length() == from->pack_length() && !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) && to->real_type() != MYSQL_TYPE_ENUM && @@ -781,15 +809,12 @@ int field_conv(Field *to,Field *from) (to->real_type() != MYSQL_TYPE_NEWDECIMAL || (to->field_length == from->field_length && (((Field_num*)to)->dec == ((Field_num*)from)->dec))) && - from->charset() == to->charset() && to->table->s->db_low_byte_first == from->table->s->db_low_byte_first && (!(to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) || (to->type() != MYSQL_TYPE_DATE && to->type() != MYSQL_TYPE_DATETIME)) && - (from->real_type() != MYSQL_TYPE_VARCHAR || - ((Field_varstring*)from)->length_bytes == - ((Field_varstring*)to)->length_bytes)) + (from->real_type() != MYSQL_TYPE_VARCHAR)) { // Identical fields // to->ptr==from->ptr may happen if one does 'UPDATE ... SET x=x' memmove(to->ptr, from->ptr, to->pack_length()); From 5f2d3479ffed18e28435c9ad130d400e7290e0bb Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Wed, 4 Nov 2015 16:12:27 +0530 Subject: [PATCH 26/29] BUG 22005375 - DEVEL PACKAGES INSTALL FAILS IF MYSQL-CONNECTOR-C-DEVEL-6.1.6 IS INSTALLED As MySQL Connector C 6.1 is end of life, added conflict with mysql-connector-c-devel dependencies --- packaging/rpm-oel/mysql.spec.in | 2 +- packaging/rpm-sles/mysql.spec.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/rpm-oel/mysql.spec.in b/packaging/rpm-oel/mysql.spec.in index 2d91975f56c..3136e47230b 100644 --- a/packaging/rpm-oel/mysql.spec.in +++ b/packaging/rpm-oel/mysql.spec.in @@ -301,7 +301,7 @@ Obsoletes: mysql-devel < %{version}-%{release} Obsoletes: mariadb-devel Provides: mysql-devel = %{version}-%{release} Provides: mysql-devel%{?_isa} = %{version}-%{release} -Conflicts: mysql-connector-c-shared-devel < 6.2 +Conflicts: mysql-connector-c-devel < 6.2 %description devel This package contains the development header files and libraries necessary diff --git a/packaging/rpm-sles/mysql.spec.in b/packaging/rpm-sles/mysql.spec.in index b5fb5b77642..cb42dfacf71 100644 --- a/packaging/rpm-sles/mysql.spec.in +++ b/packaging/rpm-sles/mysql.spec.in @@ -268,7 +268,7 @@ Obsoletes: mariadb-devel Obsoletes: libmysqlclient-devel Provides: mysql-devel = %{version}-%{release} Provides: libmysqlclient-devel = %{version}-%{release} -Conflicts: mysql-connector-c-shared-devel < 6.2 +Conflicts: mysql-connector-c-devel < 6.2 %description devel This package contains the development header files and libraries necessary From fd9831410dfc878420fcd95dc576b955e94d2c76 Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Thu, 5 Nov 2015 16:33:47 +0530 Subject: [PATCH 27/29] BUG#21950975 - MYSQL RPM INSTALLER(NEW STYLE) FAILS TO CREATE 'MYSQL' USER FOR EL5 - Remove -N option in useradd for EL5 platforms --- packaging/rpm-oel/mysql.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpm-oel/mysql.spec.in b/packaging/rpm-oel/mysql.spec.in index 3136e47230b..a76eaa114f8 100644 --- a/packaging/rpm-oel/mysql.spec.in +++ b/packaging/rpm-oel/mysql.spec.in @@ -622,7 +622,7 @@ rm -r $(readlink var) var %pre server /usr/sbin/groupadd -g 27 -o -r mysql >/dev/null 2>&1 || : -/usr/sbin/useradd -M -N -g mysql -o -r -d /var/lib/mysql -s /bin/bash \ +/usr/sbin/useradd -M %{!?el5:-N} -g mysql -o -r -d /var/lib/mysql -s /bin/bash \ -c "MySQL Server" -u 27 mysql >/dev/null 2>&1 || : %post server From 0dbd5a8797ed4bd18e8b883988fb62177eb0f73f Mon Sep 17 00:00:00 2001 From: Harin Vadodaria Date: Fri, 6 Nov 2015 16:41:55 +0530 Subject: [PATCH 28/29] Bug#21973610: BUFFER OVERFLOW ISSUES Description : Incorrect usage of sprintf/strcpy caused possible buffer overflow issues at various places. Solution : - Fixed mysql_plugin and mysqlshow - Fixed regex library issues Reviewed-By : Georgi Kodinov Reviewed-By : Venkata S Murthy Sidagam --- client/mysql_plugin.c | 10 ++++++++-- client/mysqlshow.c | 35 +++++++++++++++++++++-------------- libmysql/conf_to_src.c | 4 ++-- regex/main.c | 17 +++++++++++------ 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c index cf212b16f24..293bd6727cf 100644 --- a/client/mysql_plugin.c +++ b/client/mysql_plugin.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2011, 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 @@ -406,7 +406,7 @@ exit: static void usage(void) { PRINT_VERSION; - puts("Copyright (c) 2011, Oracle and/or its affiliates. " + puts("Copyright (c) 2011, 2015, Oracle and/or its affiliates. " "All rights reserved.\n"); puts("Enable or disable plugins."); printf("\nUsage: %s [options] ENABLE|DISABLE\n\nOptions:\n", @@ -757,6 +757,11 @@ static int check_options(int argc, char **argv, char *operation) /* read the plugin config file and check for match against argument */ else { + if (strlen(argv[i]) + 4 + 1 > FN_REFLEN) + { + fprintf(stderr, "ERROR: argument is too long.\n"); + return 1; + } strcpy(plugin_name, argv[i]); strcpy(config_file, argv[i]); strcat(config_file, ".ini"); @@ -848,6 +853,7 @@ static int process_options(int argc, char *argv[], char *operation) if (opt_basedir[i-1] != FN_LIBCHAR || opt_basedir[i-1] != FN_LIBCHAR2) { char buff[FN_REFLEN]; + memset(buff, 0, sizeof(buff)); strncpy(buff, opt_basedir, sizeof(buff) - 1); #ifdef __WIN__ diff --git a/client/mysqlshow.c b/client/mysqlshow.c index a6705548bcb..6cbbc5e2463 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -377,7 +377,7 @@ list_dbs(MYSQL *mysql,const char *wild) uint length, counter = 0; ulong rowcount = 0L; char tables[NAME_LEN+1], rows[NAME_LEN+1]; - char query[255]; + char query[NAME_LEN + 100]; MYSQL_FIELD *field; MYSQL_RES *result; MYSQL_ROW row= NULL, rrow; @@ -444,7 +444,8 @@ list_dbs(MYSQL *mysql,const char *wild) MYSQL_ROW trow; while ((trow = mysql_fetch_row(tresult))) { - sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]); + my_snprintf(query, sizeof(query), + "SELECT COUNT(*) FROM `%s`", trow[0]); if (!(mysql_query(mysql,query))) { MYSQL_RES *rresult; @@ -500,7 +501,7 @@ list_tables(MYSQL *mysql,const char *db,const char *table) { const char *header; uint head_length, counter = 0; - char query[255], rows[NAME_LEN], fields[16]; + char query[NAME_LEN + 100], rows[NAME_LEN], fields[16]; MYSQL_FIELD *field; MYSQL_RES *result; MYSQL_ROW row, rrow; @@ -585,7 +586,8 @@ list_tables(MYSQL *mysql,const char *db,const char *table) if (opt_verbose > 1) { /* Print the count of rows for each table */ - sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]); + my_snprintf(query, sizeof(query), "SELECT COUNT(*) FROM `%s`", + row[0]); if (!(mysql_query(mysql,query))) { if ((rresult = mysql_store_result(mysql))) @@ -645,13 +647,15 @@ list_tables(MYSQL *mysql,const char *db,const char *table) static int list_table_status(MYSQL *mysql,const char *db,const char *wild) { - char query[1024],*end; + char query[NAME_LEN + 100]; + int len; MYSQL_RES *result; MYSQL_ROW row; - end=strxmov(query,"show table status from `",db,"`",NullS); - if (wild && wild[0]) - strxmov(end," like '",wild,"'",NullS); + len= sizeof(query); + len-= my_snprintf(query, len, "show table status from `%s`", db); + if (wild && wild[0] && len) + strxnmov(query + strlen(query), len, " like '", wild, "'", NullS); if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) { fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n", @@ -683,7 +687,8 @@ static int list_fields(MYSQL *mysql,const char *db,const char *table, const char *wild) { - char query[1024],*end; + char query[NAME_LEN + 100]; + int len; MYSQL_RES *result; MYSQL_ROW row; ulong UNINIT_VAR(rows); @@ -697,7 +702,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table, if (opt_count) { - sprintf(query,"select count(*) from `%s`", table); + my_snprintf(query, sizeof(query), "select count(*) from `%s`", table); if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) { fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n", @@ -709,9 +714,11 @@ list_fields(MYSQL *mysql,const char *db,const char *table, mysql_free_result(result); } - end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`"); - if (wild && wild[0]) - strxmov(end," like '",wild,"'",NullS); + len= sizeof(query); + len-= my_snprintf(query, len, "show /*!32332 FULL */ columns from `%s`", + table); + if (wild && wild[0] && len) + strxnmov(query + strlen(query), len, " like '", wild, "'", NullS); if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) { fprintf(stderr,"%s: Cannot list columns in db: %s, table: %s: %s\n", @@ -732,7 +739,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table, print_res_top(result); if (opt_show_keys) { - end=strmov(strmov(strmov(query,"show keys from `"),table),"`"); + my_snprintf(query, sizeof(query), "show keys from `%s`", table); if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql))) { fprintf(stderr,"%s: Cannot list keys in db: %s, table: %s: %s\n", diff --git a/libmysql/conf_to_src.c b/libmysql/conf_to_src.c index a5a7d23db0b..0e92388c93c 100644 --- a/libmysql/conf_to_src.c +++ b/libmysql/conf_to_src.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2011, 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 @@ -118,7 +118,7 @@ print_arrays_for(char *set) { FILE *f; - sprintf(buf, "%s.conf", set); + snprintf(buf, sizeof(buf), "%s.conf", set); if ((f = fopen(buf, "r")) == NULL) { fprintf(stderr, "%s: can't read conf file for charset %s\n", prog, set); diff --git a/regex/main.c b/regex/main.c index f5b591907cf..d35d5a93734 100644 --- a/regex/main.c +++ b/regex/main.c @@ -425,7 +425,8 @@ char *should; (sub.rm_so != -1 && sub.rm_eo == -1) || (sub.rm_so != -1 && sub.rm_so < 0) || (sub.rm_eo != -1 && sub.rm_eo < 0) ) { - sprintf(grump, "start %ld end %ld", (long)sub.rm_so, + snprintf(grump, sizeof(grump), + "start %ld end %ld", (long)sub.rm_so, (long)sub.rm_eo); return(grump); } @@ -438,7 +439,8 @@ char *should; /* check for in range */ if ((int) sub.rm_eo > (int) strlen(str)) { - sprintf(grump, "start %ld end %ld, past end of string", + snprintf(grump, sizeof(grump), + "start %ld end %ld, past end of string", (long)sub.rm_so, (long)sub.rm_eo); return(grump); } @@ -449,13 +451,15 @@ char *should; /* check for not supposed to match */ if (should == NULL) { - sprintf(grump, "matched `%.*s'", len, p); + snprintf(grump, sizeof(grump), + "matched `%.*s'", len, p); return(grump); } /* check for wrong match */ if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) { - sprintf(grump, "matched `%.*s' instead", len, p); + snprintf(grump, sizeof(grump), + "matched `%.*s' instead", len, p); return(grump); } if (shlen > 0) @@ -468,7 +472,8 @@ char *should; if (shlen == 0) shlen = 1; /* force check for end-of-string */ if (strncmp(p, at, shlen) != 0) { - sprintf(grump, "matched null at `%.20s'", p); + snprintf(grump, sizeof(grump), + "matched null at `%.20s'", p); return(grump); } return(NULL); @@ -501,7 +506,7 @@ char *name; static char efbuf[100]; my_regex_t re; - sprintf(efbuf, "REG_%s", name); + snprintf(efbuf, sizeof(efbuf), "REG_%s", name); assert(strlen(efbuf) < sizeof(efbuf)); re.re_endp = efbuf; (void) my_regerror(REG_ATOI, &re, efbuf, sizeof(efbuf)); From 40ae1b9b618fbbc3b494a896a9d074b74e414337 Mon Sep 17 00:00:00 2001 From: Harin Vadodaria Date: Sat, 7 Nov 2015 22:03:47 +0530 Subject: [PATCH 29/29] Bug#21973610: BUFFER OVERFLOW ISSUES post push fix : Fixing test failures --- mysql-test/r/mysql_plugin.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/mysql_plugin.result b/mysql-test/r/mysql_plugin.result index 636b039047e..0bcb47e4a10 100644 --- a/mysql-test/r/mysql_plugin.result +++ b/mysql-test/r/mysql_plugin.result @@ -102,7 +102,7 @@ ERROR: Missing --plugin_dir option. # Show the help. # mysql_plugin Ver V.V.VV Distrib XX.XX.XX -Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. Enable or disable plugins.