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)),
return 0;
#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);
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
......
......@@ -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
......
#
# 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';
#
......
......@@ -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
......
......@@ -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);
}
......
......@@ -4860,8 +4860,7 @@ prepare_inplace_alter_table_dict(
/* 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 @@ prepare_inplace_alter_table_dict(
&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;
}
......
......@@ -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);
}
/***************************************************************
......
/*****************************************************************************
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;
}
......
......@@ -706,8 +706,7 @@ row_mysql_handle_errors(
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 @@ row_mysql_handle_errors(
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 @@ row_mysql_handle_errors(
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 @@ row_mysql_handle_errors(
" 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);
......
......@@ -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]) {
......
/*****************************************************************************
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)
......
/*****************************************************************************
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;
}
......
......@@ -615,8 +615,7 @@ row_mysql_handle_errors(
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 @@ row_mysql_handle_errors(
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 @@ row_mysql_handle_errors(
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 @@ row_mysql_handle_errors(
"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);
......
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