summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-03-07 17:50:13 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-03-07 17:52:27 +0200
commit913e33e423b434712a9d708cd0f0244d2f03cb0b (patch)
tree6f276c6426bd91a8b7f35614a20ddfa2df89b213
parent2faefe5f7f432f8d9b3435dd8f4e2a37163c5527 (diff)
parente3adf96aeb39ad43143ca2a9c7a2f23d06e8e26b (diff)
downloadmariadb-git-913e33e423b434712a9d708cd0f0244d2f03cb0b.tar.gz
Merge 10.1 into 10.2
Rewrite the MDEV-13818 fix to prevent heap-use-after-free. Add a test case for MDEV-18272.
-rw-r--r--dbug/tests.c8
-rw-r--r--include/my_pthread.h4
-rw-r--r--mysql-test/suite/sys_vars/inc/sysvars_server.inc2
-rw-r--r--mysql-test/suite/sys_vars/t/thread_stack_basic.test10
-rw-r--r--mysql-test/t/mysqld--help.test2
-rw-r--r--storage/innobase/dict/dict0dict.cc11
-rw-r--r--storage/innobase/handler/handler0alter.cc17
-rw-r--r--storage/innobase/include/dict0dict.h20
-rw-r--r--storage/innobase/row/row0merge.cc20
-rw-r--r--storage/innobase/row/row0mysql.cc9
-rw-r--r--storage/xtradb/handler/handler0alter.cc12
-rw-r--r--storage/xtradb/include/ut0dbg.h3
-rw-r--r--storage/xtradb/row/row0merge.cc17
-rw-r--r--storage/xtradb/row/row0mysql.cc9
14 files changed, 79 insertions, 65 deletions
diff --git a/dbug/tests.c b/dbug/tests.c
index 22a445fdeca..70424046bf4 100644
--- a/dbug/tests.c
+++ b/dbug/tests.c
@@ -86,3 +86,11 @@ int main (int argc __attribute__((unused)),
return 0;
#endif /* DBUG_OFF */
}
+
+#ifdef __SANITIZE_ADDRESS__
+/* Disable LeakSanitizer in this executable */
+const char* __asan_default_options()
+{
+ return "detect_leaks=0";
+}
+#endif
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 0504a5f3272..dfd479fed36 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -693,8 +693,12 @@ extern void my_mutex_end(void);
We need to have at least 256K stack to handle calls to myisamchk_init()
with the current number of keys and key parts.
*/
+#ifdef __SANITIZE_ADDRESS__
+#define DEFAULT_THREAD_STACK (364*1024L)
+#else
#define DEFAULT_THREAD_STACK (292*1024L)
#endif
+#endif
#define MY_PTHREAD_LOCK_READ 0
#define MY_PTHREAD_LOCK_WRITE 1
diff --git a/mysql-test/suite/sys_vars/inc/sysvars_server.inc b/mysql-test/suite/sys_vars/inc/sysvars_server.inc
index 76d35f0fd55..29e8d412c07 100644
--- a/mysql-test/suite/sys_vars/inc/sysvars_server.inc
+++ b/mysql-test/suite/sys_vars/inc/sysvars_server.inc
@@ -13,7 +13,7 @@ set sql_mode=ansi_quotes;
set global div_precision_increment=5;
--replace_regex /^\/\S+/PATH/
---replace_result $MASTER_MYPORT MASTER_MYPORT
+--replace_result $MASTER_MYPORT MASTER_MYPORT 372736 299008
select * from information_schema.system_variables
where variable_name not like 'aria%' and
variable_name not like 'debug%' and
diff --git a/mysql-test/suite/sys_vars/t/thread_stack_basic.test b/mysql-test/suite/sys_vars/t/thread_stack_basic.test
index 2d4d144572d..bfd3fb40db3 100644
--- a/mysql-test/suite/sys_vars/t/thread_stack_basic.test
+++ b/mysql-test/suite/sys_vars/t/thread_stack_basic.test
@@ -1,17 +1,17 @@
#
# only global
#
---replace_result 196608 262144
+--replace_result 372736 299008
select @@global.thread_stack;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.thread_stack;
---replace_result 196608 262144
+--replace_result 372736 299008
show global variables like 'thread_stack';
---replace_result 196608 262144
+--replace_result 372736 299008
show session variables like 'thread_stack';
---replace_result 196608 262144
+--replace_result 372736 299008
select * from information_schema.global_variables where variable_name='thread_stack';
---replace_result 196608 262144
+--replace_result 372736 299008
select * from information_schema.session_variables where variable_name='thread_stack';
#
diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test
index 1613f8e7a4f..a9c20257c04 100644
--- a/mysql-test/t/mysqld--help.test
+++ b/mysql-test/t/mysqld--help.test
@@ -57,7 +57,7 @@ perl;
# fixes for 32-bit
s/\b4294967295\b/18446744073709551615/;
s/\b2146435072\b/9223372036853727232/;
- s/\b196608\b/262144/;
+ s/\b372736\b/299008/;
s/\b4294963200\b/18446744073709547520/;
foreach $var (@env) { s/\Q$ENV{$var}\E/$var/ }
next if /use --skip-(use-)?symbolic-links to disable/; # for valgrind, again
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 628038ff8fe..6e936b52174 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -6198,23 +6198,16 @@ dict_ind_free()
/** Get an index by name.
@param[in] table the table where to look for the index
@param[in] name the index name to look for
-@param[in] committed true=search for committed,
-false=search for uncommitted
@return index, NULL if does not exist */
dict_index_t*
-dict_table_get_index_on_name(
- dict_table_t* table,
- const char* name,
- bool committed)
+dict_table_get_index_on_name(dict_table_t* table, const char* name)
{
dict_index_t* index;
index = dict_table_get_first_index(table);
while (index != NULL) {
- if (index->is_committed() == committed
- && strcmp(index->name, name) == 0) {
-
+ if (index->is_committed() && !strcmp(index->name, name)) {
return(index);
}
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index d0b577f7535..72acca5d967 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -4860,8 +4860,7 @@ new_clustered_failed:
/* Create the indexes in SYS_INDEXES and load into dictionary. */
- for (int a = 0; a < ctx->num_to_add_index; a++) {
-
+ for (ulint a = 0; a < ctx->num_to_add_index; a++) {
if (index_defs[a].ind_type & DICT_VIRTUAL
&& ctx->num_to_drop_vcol > 0 && !new_clustered) {
innodb_v_adjust_idx_col(ha_alter_info, old_table,
@@ -4869,17 +4868,23 @@ new_clustered_failed:
&index_defs[a]);
}
+ DBUG_EXECUTE_IF(
+ "create_index_metadata_fail",
+ if (a + 1 == ctx->num_to_add_index) {
+ ctx->trx->error_state = DB_OUT_OF_FILE_SPACE;
+ ctx->add_index[a] = NULL;
+ goto index_created;
+ });
ctx->add_index[a] = row_merge_create_index(
ctx->trx, ctx->new_table, &index_defs[a], add_v);
-
+#ifndef DBUG_OFF
+index_created:
+#endif
add_key_nums[a] = index_defs[a].key_number;
if (!ctx->add_index[a]) {
error = ctx->trx->error_state;
DBUG_ASSERT(error != DB_SUCCESS);
- while (--a >= 0) {
- dict_mem_index_free(ctx->add_index[a]);
- }
goto error_handling;
}
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 26d5ed34318..d843374b866 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -2,7 +2,7 @@
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, MariaDB Corporation.
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
@@ -1599,31 +1599,21 @@ dict_tables_have_same_db(
/** Get an index by name.
@param[in] table the table where to look for the index
@param[in] name the index name to look for
-@param[in] committed true=search for committed,
-false=search for uncommitted
@return index, NULL if does not exist */
dict_index_t*
-dict_table_get_index_on_name(
- dict_table_t* table,
- const char* name,
- bool committed=true)
+dict_table_get_index_on_name(dict_table_t* table, const char* name)
MY_ATTRIBUTE((warn_unused_result));
/** Get an index by name.
@param[in] table the table where to look for the index
@param[in] name the index name to look for
-@param[in] committed true=search for committed,
-false=search for uncommitted
@return index, NULL if does not exist */
inline
const dict_index_t*
-dict_table_get_index_on_name(
- const dict_table_t* table,
- const char* name,
- bool committed=true)
+dict_table_get_index_on_name(const dict_table_t* table, const char* name)
{
- return(dict_table_get_index_on_name(
- const_cast<dict_table_t*>(table), name, committed));
+ return dict_table_get_index_on_name(const_cast<dict_table_t*>(table),
+ name);
}
/***************************************************************
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 92528ed4d2c..8eb720abb40 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2014, 2018, MariaDB Corporation.
+Copyright (c) 2014, 2019, MariaDB Corporation.
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
@@ -4310,7 +4310,7 @@ dberr_t
row_merge_create_index_graph(
trx_t* trx,
dict_table_t* table,
- dict_index_t* index,
+ dict_index_t*& index,
const dict_add_v_col_t* add_v)
{
ind_node_t* node; /*!< Index creation node */
@@ -4337,6 +4337,8 @@ row_merge_create_index_graph(
err = trx->error_state;
+ index = node->index;
+
que_graph_free((que_t*) que_node_get_parent(thr));
DBUG_RETURN(err);
@@ -4400,25 +4402,23 @@ row_merge_create_index(
dict_mem_index_add_field(index, name, ifield->prefix_len);
}
+ ut_d(const dict_index_t* const index_template = index);
/* Add the index to SYS_INDEXES, using the index prototype. */
err = row_merge_create_index_graph(trx, table, index, add_v);
if (err == DB_SUCCESS) {
-
- index = dict_table_get_index_on_name(table, index_def->name,
- index_def->rebuild);
-
- ut_a(index);
-
+ ut_ad(index != index_template);
index->parser = index_def->parser;
index->has_new_v_col = has_new_v_col;
-
/* Note the id of the transaction that created this
index, we use it to restrict readers from accessing
this index, to ensure read consistency. */
ut_ad(index->trx_id == trx->id);
} else {
- dict_mem_index_free(index);
+ ut_ad(!index || index == index_template);
+ if (index) {
+ dict_mem_index_free(index);
+ }
index = NULL;
}
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 4d1a05d516a..5fbc0cd3419 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -706,8 +706,7 @@ handle_new_error:
switch (err) {
case DB_LOCK_WAIT_TIMEOUT:
if (row_rollback_on_timeout) {
- trx_rollback_to_savepoint(trx, NULL);
- break;
+ goto rollback;
}
/* fall through */
case DB_DUPLICATE_KEY:
@@ -726,6 +725,7 @@ handle_new_error:
case DB_TABLE_NOT_FOUND:
case DB_DECRYPTION_FAILED:
case DB_COMPUTE_VALUE_FAILED:
+ rollback_to_savept:
DBUG_EXECUTE_IF("row_mysql_crash_if_error", {
log_buffer_flush_to_disk();
DBUG_SUICIDE(); });
@@ -752,6 +752,7 @@ handle_new_error:
case DB_DEADLOCK:
case DB_LOCK_TABLE_FULL:
+ rollback:
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */
@@ -773,13 +774,13 @@ handle_new_error:
" tablespace. If the mysqld server crashes after"
" the startup or when you dump the tables. "
<< FORCE_RECOVERY_MSG;
- break;
+ goto rollback_to_savept;
case DB_FOREIGN_EXCEED_MAX_CASCADE:
ib::error() << "Cannot delete/update rows with cascading"
" foreign key constraints that exceed max depth of "
<< FK_MAX_CASCADE_DEL << ". Please drop excessive"
" foreign constraints and try again";
- break;
+ goto rollback_to_savept;
default:
ib::fatal() << "Unknown error code " << err << ": "
<< ut_strerr(err);
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index 48803426082..bdc7c72cf8b 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -3097,10 +3097,18 @@ prepare_inplace_alter_table_dict(
/* Create the indexes in SYS_INDEXES and load into dictionary. */
for (ulint a = 0; a < ctx->num_to_add_index; a++) {
-
+ DBUG_EXECUTE_IF(
+ "create_index_metadata_fail",
+ if (a + 1 == ctx->num_to_add_index) {
+ ctx->trx->error_state = DB_OUT_OF_FILE_SPACE;
+ ctx->add_index[a] = NULL;
+ goto index_created;
+ });
ctx->add_index[a] = row_merge_create_index(
ctx->trx, ctx->new_table, &index_defs[a]);
-
+#ifndef DBUG_OFF
+index_created:
+#endif
add_key_nums[a] = index_defs[a].key_number;
if (!ctx->add_index[a]) {
diff --git a/storage/xtradb/include/ut0dbg.h b/storage/xtradb/include/ut0dbg.h
index 3f5baef0a3c..b4c941bc163 100644
--- a/storage/xtradb/include/ut0dbg.h
+++ b/storage/xtradb/include/ut0dbg.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2017, MariaDB Corporation.
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
@@ -84,7 +85,7 @@ ut_dbg_assertion_failed(
/** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */
#define ut_ad(EXPR) ut_a(EXPR)
/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
-#define ut_d(EXPR) do {EXPR;} while (0)
+#define ut_d(EXPR) EXPR
#else
/** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */
#define ut_ad(EXPR)
diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc
index e1b0a9f0610..0ec11a31500 100644
--- a/storage/xtradb/row/row0merge.cc
+++ b/storage/xtradb/row/row0merge.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2014, 2018, MariaDB Corporation.
+Copyright (c) 2014, 2019, MariaDB Corporation.
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
@@ -3705,7 +3705,7 @@ row_merge_create_index_graph(
/*=========================*/
trx_t* trx, /*!< in: trx */
dict_table_t* table, /*!< in: table */
- dict_index_t* index) /*!< in: index */
+ dict_index_t*& index) /*!< in,out: index */
{
ind_node_t* node; /*!< Index creation node */
mem_heap_t* heap; /*!< Memory heap */
@@ -3729,6 +3729,8 @@ row_merge_create_index_graph(
err = trx->error_state;
+ index = node->index;
+
que_graph_free((que_t*) que_node_get_parent(thr));
return(err);
@@ -3770,20 +3772,21 @@ row_merge_create_index(
ifield->prefix_len);
}
+ ut_d(const dict_index_t* const index_template = index);
/* Add the index to SYS_INDEXES, using the index prototype. */
err = row_merge_create_index_graph(trx, table, index);
if (err == DB_SUCCESS) {
-
- index = dict_table_get_index_on_name(table, index_def->name);
-
- ut_a(index);
-
+ ut_ad(index != index_template);
/* Note the id of the transaction that created this
index, we use it to restrict readers from accessing
this index, to ensure read consistency. */
ut_ad(index->trx_id == trx->id);
} else {
+ ut_ad(!index || index == index_template);
+ if (index) {
+ dict_mem_index_free(index);
+ }
index = NULL;
}
diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc
index 498a35a86ce..47075c6cbc8 100644
--- a/storage/xtradb/row/row0mysql.cc
+++ b/storage/xtradb/row/row0mysql.cc
@@ -615,8 +615,7 @@ handle_new_error:
switch (err) {
case DB_LOCK_WAIT_TIMEOUT:
if (row_rollback_on_timeout) {
- trx_rollback_to_savepoint(trx, NULL);
- break;
+ goto rollback;
}
/* fall through */
case DB_DUPLICATE_KEY:
@@ -635,6 +634,7 @@ handle_new_error:
case DB_DICT_CHANGED:
case DB_TABLE_NOT_FOUND:
case DB_DECRYPTION_FAILED:
+ rollback_to_savept:
if (savept) {
/* Roll back the latest, possibly incomplete insertion
or update */
@@ -658,6 +658,7 @@ handle_new_error:
case DB_DEADLOCK:
case DB_LOCK_TABLE_FULL:
+ rollback:
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */
@@ -687,14 +688,14 @@ handle_new_error:
"InnoDB: you dump the tables, look at\n"
"InnoDB: " REFMAN "forcing-innodb-recovery.html"
" for help.\n", stderr);
- break;
+ goto rollback_to_savept;
case DB_FOREIGN_EXCEED_MAX_CASCADE:
fprintf(stderr, "InnoDB: Cannot delete/update rows with"
" cascading foreign key constraints that exceed max"
" depth of %lu\n"
"Please drop excessive foreign constraints"
" and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
- break;
+ goto rollback_to_savept;
default:
fprintf(stderr, "InnoDB: unknown error code %lu\n",
(ulong) err);