Commit 913e33e4 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.1 into 10.2

Rewrite the MDEV-13818 fix to prevent heap-use-after-free.

Add a test case for MDEV-18272.
parents 2faefe5f e3adf96a
...@@ -86,3 +86,11 @@ int main (int argc __attribute__((unused)), ...@@ -86,3 +86,11 @@ int main (int argc __attribute__((unused)),
return 0; return 0;
#endif /* DBUG_OFF */ #endif /* DBUG_OFF */
} }
#ifdef __SANITIZE_ADDRESS__
/* Disable LeakSanitizer in this executable */
const char* __asan_default_options()
{
return "detect_leaks=0";
}
#endif
...@@ -693,8 +693,12 @@ extern void my_mutex_end(void); ...@@ -693,8 +693,12 @@ extern void my_mutex_end(void);
We need to have at least 256K stack to handle calls to myisamchk_init() We need to have at least 256K stack to handle calls to myisamchk_init()
with the current number of keys and key parts. 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) #define DEFAULT_THREAD_STACK (292*1024L)
#endif #endif
#endif
#define MY_PTHREAD_LOCK_READ 0 #define MY_PTHREAD_LOCK_READ 0
#define MY_PTHREAD_LOCK_WRITE 1 #define MY_PTHREAD_LOCK_WRITE 1
......
...@@ -13,7 +13,7 @@ set sql_mode=ansi_quotes; ...@@ -13,7 +13,7 @@ set sql_mode=ansi_quotes;
set global div_precision_increment=5; set global div_precision_increment=5;
--replace_regex /^\/\S+/PATH/ --replace_regex /^\/\S+/PATH/
--replace_result $MASTER_MYPORT MASTER_MYPORT --replace_result $MASTER_MYPORT MASTER_MYPORT 372736 299008
select * from information_schema.system_variables select * from information_schema.system_variables
where variable_name not like 'aria%' and where variable_name not like 'aria%' and
variable_name not like 'debug%' and variable_name not like 'debug%' and
......
# #
# only global # only global
# #
--replace_result 196608 262144 --replace_result 372736 299008
select @@global.thread_stack; select @@global.thread_stack;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR --error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.thread_stack; select @@session.thread_stack;
--replace_result 196608 262144 --replace_result 372736 299008
show global variables like 'thread_stack'; show global variables like 'thread_stack';
--replace_result 196608 262144 --replace_result 372736 299008
show session variables like 'thread_stack'; 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'; 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'; select * from information_schema.session_variables where variable_name='thread_stack';
# #
......
...@@ -57,7 +57,7 @@ perl; ...@@ -57,7 +57,7 @@ perl;
# fixes for 32-bit # fixes for 32-bit
s/\b4294967295\b/18446744073709551615/; s/\b4294967295\b/18446744073709551615/;
s/\b2146435072\b/9223372036853727232/; s/\b2146435072\b/9223372036853727232/;
s/\b196608\b/262144/; s/\b372736\b/299008/;
s/\b4294963200\b/18446744073709547520/; s/\b4294963200\b/18446744073709547520/;
foreach $var (@env) { s/\Q$ENV{$var}\E/$var/ } foreach $var (@env) { s/\Q$ENV{$var}\E/$var/ }
next if /use --skip-(use-)?symbolic-links to disable/; # for valgrind, again next if /use --skip-(use-)?symbolic-links to disable/; # for valgrind, again
......
...@@ -6198,23 +6198,16 @@ dict_ind_free() ...@@ -6198,23 +6198,16 @@ dict_ind_free()
/** Get an index by name. /** Get an index by name.
@param[in] table the table where to look for the index @param[in] table the table where to look for the index
@param[in] name the index name to look for @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 */ @return index, NULL if does not exist */
dict_index_t* dict_index_t*
dict_table_get_index_on_name( dict_table_get_index_on_name(dict_table_t* table, const char* name)
dict_table_t* table,
const char* name,
bool committed)
{ {
dict_index_t* index; dict_index_t* index;
index = dict_table_get_first_index(table); index = dict_table_get_first_index(table);
while (index != NULL) { while (index != NULL) {
if (index->is_committed() == committed if (index->is_committed() && !strcmp(index->name, name)) {
&& strcmp(index->name, name) == 0) {
return(index); return(index);
} }
......
...@@ -4860,8 +4860,7 @@ prepare_inplace_alter_table_dict( ...@@ -4860,8 +4860,7 @@ prepare_inplace_alter_table_dict(
/* Create the indexes in SYS_INDEXES and load into dictionary. */ /* 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 if (index_defs[a].ind_type & DICT_VIRTUAL
&& ctx->num_to_drop_vcol > 0 && !new_clustered) { && ctx->num_to_drop_vcol > 0 && !new_clustered) {
innodb_v_adjust_idx_col(ha_alter_info, old_table, innodb_v_adjust_idx_col(ha_alter_info, old_table,
...@@ -4869,17 +4868,23 @@ prepare_inplace_alter_table_dict( ...@@ -4869,17 +4868,23 @@ prepare_inplace_alter_table_dict(
&index_defs[a]); &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->add_index[a] = row_merge_create_index(
ctx->trx, ctx->new_table, &index_defs[a], add_v); 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; add_key_nums[a] = index_defs[a].key_number;
if (!ctx->add_index[a]) { if (!ctx->add_index[a]) {
error = ctx->trx->error_state; error = ctx->trx->error_state;
DBUG_ASSERT(error != DB_SUCCESS); DBUG_ASSERT(error != DB_SUCCESS);
while (--a >= 0) {
dict_mem_index_free(ctx->add_index[a]);
}
goto error_handling; goto error_handling;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -1599,31 +1599,21 @@ dict_tables_have_same_db( ...@@ -1599,31 +1599,21 @@ dict_tables_have_same_db(
/** Get an index by name. /** Get an index by name.
@param[in] table the table where to look for the index @param[in] table the table where to look for the index
@param[in] name the index name to look for @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 */ @return index, NULL if does not exist */
dict_index_t* dict_index_t*
dict_table_get_index_on_name( dict_table_get_index_on_name(dict_table_t* table, const char* name)
dict_table_t* table,
const char* name,
bool committed=true)
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
/** Get an index by name. /** Get an index by name.
@param[in] table the table where to look for the index @param[in] table the table where to look for the index
@param[in] name the index name to look for @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 */ @return index, NULL if does not exist */
inline inline
const dict_index_t* const dict_index_t*
dict_table_get_index_on_name( dict_table_get_index_on_name(const dict_table_t* table, const char* name)
const dict_table_t* table,
const char* name,
bool committed=true)
{ {
return(dict_table_get_index_on_name( return dict_table_get_index_on_name(const_cast<dict_table_t*>(table),
const_cast<dict_table_t*>(table), name, committed)); name);
} }
/*************************************************************** /***************************************************************
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -4310,7 +4310,7 @@ dberr_t ...@@ -4310,7 +4310,7 @@ dberr_t
row_merge_create_index_graph( row_merge_create_index_graph(
trx_t* trx, trx_t* trx,
dict_table_t* table, dict_table_t* table,
dict_index_t* index, dict_index_t*& index,
const dict_add_v_col_t* add_v) const dict_add_v_col_t* add_v)
{ {
ind_node_t* node; /*!< Index creation node */ ind_node_t* node; /*!< Index creation node */
...@@ -4337,6 +4337,8 @@ row_merge_create_index_graph( ...@@ -4337,6 +4337,8 @@ row_merge_create_index_graph(
err = trx->error_state; err = trx->error_state;
index = node->index;
que_graph_free((que_t*) que_node_get_parent(thr)); que_graph_free((que_t*) que_node_get_parent(thr));
DBUG_RETURN(err); DBUG_RETURN(err);
...@@ -4400,25 +4402,23 @@ row_merge_create_index( ...@@ -4400,25 +4402,23 @@ row_merge_create_index(
dict_mem_index_add_field(index, name, ifield->prefix_len); 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. */ /* Add the index to SYS_INDEXES, using the index prototype. */
err = row_merge_create_index_graph(trx, table, index, add_v); err = row_merge_create_index_graph(trx, table, index, add_v);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
ut_ad(index != index_template);
index = dict_table_get_index_on_name(table, index_def->name,
index_def->rebuild);
ut_a(index);
index->parser = index_def->parser; index->parser = index_def->parser;
index->has_new_v_col = has_new_v_col; index->has_new_v_col = has_new_v_col;
/* Note the id of the transaction that created this /* Note the id of the transaction that created this
index, we use it to restrict readers from accessing index, we use it to restrict readers from accessing
this index, to ensure read consistency. */ this index, to ensure read consistency. */
ut_ad(index->trx_id == trx->id); ut_ad(index->trx_id == trx->id);
} else { } else {
ut_ad(!index || index == index_template);
if (index) {
dict_mem_index_free(index); dict_mem_index_free(index);
}
index = NULL; index = NULL;
} }
......
...@@ -706,8 +706,7 @@ row_mysql_handle_errors( ...@@ -706,8 +706,7 @@ row_mysql_handle_errors(
switch (err) { switch (err) {
case DB_LOCK_WAIT_TIMEOUT: case DB_LOCK_WAIT_TIMEOUT:
if (row_rollback_on_timeout) { if (row_rollback_on_timeout) {
trx_rollback_to_savepoint(trx, NULL); goto rollback;
break;
} }
/* fall through */ /* fall through */
case DB_DUPLICATE_KEY: case DB_DUPLICATE_KEY:
...@@ -726,6 +725,7 @@ row_mysql_handle_errors( ...@@ -726,6 +725,7 @@ row_mysql_handle_errors(
case DB_TABLE_NOT_FOUND: case DB_TABLE_NOT_FOUND:
case DB_DECRYPTION_FAILED: case DB_DECRYPTION_FAILED:
case DB_COMPUTE_VALUE_FAILED: case DB_COMPUTE_VALUE_FAILED:
rollback_to_savept:
DBUG_EXECUTE_IF("row_mysql_crash_if_error", { DBUG_EXECUTE_IF("row_mysql_crash_if_error", {
log_buffer_flush_to_disk(); log_buffer_flush_to_disk();
DBUG_SUICIDE(); }); DBUG_SUICIDE(); });
...@@ -752,6 +752,7 @@ row_mysql_handle_errors( ...@@ -752,6 +752,7 @@ row_mysql_handle_errors(
case DB_DEADLOCK: case DB_DEADLOCK:
case DB_LOCK_TABLE_FULL: case DB_LOCK_TABLE_FULL:
rollback:
/* Roll back the whole transaction; this resolution was added /* Roll back the whole transaction; this resolution was added
to version 3.23.43 */ to version 3.23.43 */
...@@ -773,13 +774,13 @@ row_mysql_handle_errors( ...@@ -773,13 +774,13 @@ row_mysql_handle_errors(
" tablespace. If the mysqld server crashes after" " tablespace. If the mysqld server crashes after"
" the startup or when you dump the tables. " " the startup or when you dump the tables. "
<< FORCE_RECOVERY_MSG; << FORCE_RECOVERY_MSG;
break; goto rollback_to_savept;
case DB_FOREIGN_EXCEED_MAX_CASCADE: case DB_FOREIGN_EXCEED_MAX_CASCADE:
ib::error() << "Cannot delete/update rows with cascading" ib::error() << "Cannot delete/update rows with cascading"
" foreign key constraints that exceed max depth of " " foreign key constraints that exceed max depth of "
<< FK_MAX_CASCADE_DEL << ". Please drop excessive" << FK_MAX_CASCADE_DEL << ". Please drop excessive"
" foreign constraints and try again"; " foreign constraints and try again";
break; goto rollback_to_savept;
default: default:
ib::fatal() << "Unknown error code " << err << ": " ib::fatal() << "Unknown error code " << err << ": "
<< ut_strerr(err); << ut_strerr(err);
......
...@@ -3097,10 +3097,18 @@ prepare_inplace_alter_table_dict( ...@@ -3097,10 +3097,18 @@ prepare_inplace_alter_table_dict(
/* Create the indexes in SYS_INDEXES and load into dictionary. */ /* Create the indexes in SYS_INDEXES and load into dictionary. */
for (ulint a = 0; a < ctx->num_to_add_index; a++) { 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->add_index[a] = row_merge_create_index(
ctx->trx, ctx->new_table, &index_defs[a]); ctx->trx, ctx->new_table, &index_defs[a]);
#ifndef DBUG_OFF
index_created:
#endif
add_key_nums[a] = index_defs[a].key_number; add_key_nums[a] = index_defs[a].key_number;
if (!ctx->add_index[a]) { if (!ctx->add_index[a]) {
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -84,7 +85,7 @@ ut_dbg_assertion_failed( ...@@ -84,7 +85,7 @@ ut_dbg_assertion_failed(
/** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */ /** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */
#define ut_ad(EXPR) ut_a(EXPR) #define ut_ad(EXPR) ut_a(EXPR)
/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */ /** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
#define ut_d(EXPR) do {EXPR;} while (0) #define ut_d(EXPR) EXPR
#else #else
/** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */ /** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */
#define ut_ad(EXPR) #define ut_ad(EXPR)
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -3705,7 +3705,7 @@ row_merge_create_index_graph( ...@@ -3705,7 +3705,7 @@ row_merge_create_index_graph(
/*=========================*/ /*=========================*/
trx_t* trx, /*!< in: trx */ trx_t* trx, /*!< in: trx */
dict_table_t* table, /*!< in: table */ 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 */ ind_node_t* node; /*!< Index creation node */
mem_heap_t* heap; /*!< Memory heap */ mem_heap_t* heap; /*!< Memory heap */
...@@ -3729,6 +3729,8 @@ row_merge_create_index_graph( ...@@ -3729,6 +3729,8 @@ row_merge_create_index_graph(
err = trx->error_state; err = trx->error_state;
index = node->index;
que_graph_free((que_t*) que_node_get_parent(thr)); que_graph_free((que_t*) que_node_get_parent(thr));
return(err); return(err);
...@@ -3770,20 +3772,21 @@ row_merge_create_index( ...@@ -3770,20 +3772,21 @@ row_merge_create_index(
ifield->prefix_len); ifield->prefix_len);
} }
ut_d(const dict_index_t* const index_template = index);
/* Add the index to SYS_INDEXES, using the index prototype. */ /* Add the index to SYS_INDEXES, using the index prototype. */
err = row_merge_create_index_graph(trx, table, index); err = row_merge_create_index_graph(trx, table, index);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
ut_ad(index != index_template);
index = dict_table_get_index_on_name(table, index_def->name);
ut_a(index);
/* Note the id of the transaction that created this /* Note the id of the transaction that created this
index, we use it to restrict readers from accessing index, we use it to restrict readers from accessing
this index, to ensure read consistency. */ this index, to ensure read consistency. */
ut_ad(index->trx_id == trx->id); ut_ad(index->trx_id == trx->id);
} else { } else {
ut_ad(!index || index == index_template);
if (index) {
dict_mem_index_free(index);
}
index = NULL; index = NULL;
} }
......
...@@ -615,8 +615,7 @@ row_mysql_handle_errors( ...@@ -615,8 +615,7 @@ row_mysql_handle_errors(
switch (err) { switch (err) {
case DB_LOCK_WAIT_TIMEOUT: case DB_LOCK_WAIT_TIMEOUT:
if (row_rollback_on_timeout) { if (row_rollback_on_timeout) {
trx_rollback_to_savepoint(trx, NULL); goto rollback;
break;
} }
/* fall through */ /* fall through */
case DB_DUPLICATE_KEY: case DB_DUPLICATE_KEY:
...@@ -635,6 +634,7 @@ row_mysql_handle_errors( ...@@ -635,6 +634,7 @@ row_mysql_handle_errors(
case DB_DICT_CHANGED: case DB_DICT_CHANGED:
case DB_TABLE_NOT_FOUND: case DB_TABLE_NOT_FOUND:
case DB_DECRYPTION_FAILED: case DB_DECRYPTION_FAILED:
rollback_to_savept:
if (savept) { if (savept) {
/* Roll back the latest, possibly incomplete insertion /* Roll back the latest, possibly incomplete insertion
or update */ or update */
...@@ -658,6 +658,7 @@ row_mysql_handle_errors( ...@@ -658,6 +658,7 @@ row_mysql_handle_errors(
case DB_DEADLOCK: case DB_DEADLOCK:
case DB_LOCK_TABLE_FULL: case DB_LOCK_TABLE_FULL:
rollback:
/* Roll back the whole transaction; this resolution was added /* Roll back the whole transaction; this resolution was added
to version 3.23.43 */ to version 3.23.43 */
...@@ -687,14 +688,14 @@ row_mysql_handle_errors( ...@@ -687,14 +688,14 @@ row_mysql_handle_errors(
"InnoDB: you dump the tables, look at\n" "InnoDB: you dump the tables, look at\n"
"InnoDB: " REFMAN "forcing-innodb-recovery.html" "InnoDB: " REFMAN "forcing-innodb-recovery.html"
" for help.\n", stderr); " for help.\n", stderr);
break; goto rollback_to_savept;
case DB_FOREIGN_EXCEED_MAX_CASCADE: case DB_FOREIGN_EXCEED_MAX_CASCADE:
fprintf(stderr, "InnoDB: Cannot delete/update rows with" fprintf(stderr, "InnoDB: Cannot delete/update rows with"
" cascading foreign key constraints that exceed max" " cascading foreign key constraints that exceed max"
" depth of %lu\n" " depth of %lu\n"
"Please drop excessive foreign constraints" "Please drop excessive foreign constraints"
" and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD); " and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
break; goto rollback_to_savept;
default: default:
fprintf(stderr, "InnoDB: unknown error code %lu\n", fprintf(stderr, "InnoDB: unknown error code %lu\n",
(ulong) err); (ulong) err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment