1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-18 23:03:28 +03:00

MDEV-35236 Assertion `(mem_root->flags & 4) == 0' failed in safe_lexcstrdup_root

Post-fix for MDEV-35144.

Cannot allocate options values on the statement arena, because
HA_CREATE_INFO is shallow-copied for every execution, so if the
option_list was initially empty, it will be reset for every execution
and any values allocated on the  statement arena will be lost.

Cannot allocate option values on the execution arena, because
HA_CREATE_INFO is shallow-copied for every execution, so if the
option_list was  initially NOT empty, any values appended to the
end will be preserved and if they're on the execution arena their
content will be destroyed.

Let's use thd->change_item_tree() to save and restore necessary pointers
for every execution.

followup for 3da565c41d
This commit is contained in:
Sergei Golubchik
2024-10-23 14:43:32 +02:00
parent eac33a23da
commit 3cd706b107
6 changed files with 46 additions and 12 deletions

View File

@ -8,3 +8,13 @@ connection default;
ERROR 70100: Query execution was interrupted
CREATE TABLE t1 (a SERIAL) ENGINE=InnoDB;
DROP TABLE t1;
# End of 10.2 tests
#
# MDEV-35236 Assertion `(mem_root->flags & 4) == 0' failed in safe_lexcstrdup_root
#
prepare stmt from 'create or replace table t engine=innodb select 1 as f';
set innodb_compression_default=on;
execute stmt;
execute stmt;
drop table t;
# End of 10.5 tests

View File

@ -26,3 +26,16 @@ reap;
CREATE TABLE t1 (a SERIAL) ENGINE=InnoDB;
DROP TABLE t1;
--source include/wait_until_count_sessions.inc
--echo # End of 10.2 tests
--echo #
--echo # MDEV-35236 Assertion `(mem_root->flags & 4) == 0' failed in safe_lexcstrdup_root
--echo #
prepare stmt from 'create or replace table t engine=innodb select 1 as f';
set innodb_compression_default=on;
execute stmt;
execute stmt;
drop table t;
--echo # End of 10.5 tests

View File

@ -247,9 +247,11 @@ static const size_t ha_option_type_sizeof[]=
bool extend_option_list(THD* thd, handlerton *hton, bool create,
engine_option_value **option_list,
ha_create_table_option *rules, MEM_ROOT *root)
ha_create_table_option *rules)
{
DBUG_ENTER("extend_option_list");
MEM_ROOT *root= thd->mem_root;
bool extended= false;
for (ha_create_table_option *opt= rules; rules && opt->name; opt++)
{
@ -280,8 +282,16 @@ bool extend_option_list(THD* thd, handlerton *hton, bool create,
if (found)
found->value= value;
else
{
if (!extended)
{
void *pos= *option_list ? &(last->next) : option_list;
thd->register_item_tree_change((Item**)pos);
extended= true;
}
new (root) engine_option_value(name, value,
opt->type != HA_OPTION_TYPE_ULL, option_list, &last);
}
}
}
}
@ -803,4 +813,3 @@ bool is_engine_option_known(engine_option_value *opt,
}
return false;
}

View File

@ -89,7 +89,7 @@ bool parse_option_list(THD* thd, void *option_struct,
bool suppress_warning, MEM_ROOT *root);
bool extend_option_list(THD* thd, handlerton *hton, bool create,
engine_option_value **option_list,
ha_create_table_option *rules, MEM_ROOT *root);
ha_create_table_option *rules);
bool engine_table_options_frm_read(const uchar *buff, size_t length,
TABLE_SHARE *share);

View File

@ -4301,14 +4301,19 @@ public:
return !stmt_arena->is_conventional();
}
void register_item_tree_change(Item **place)
{
/* TODO: check for OOM condition here */
if (is_item_tree_change_register_required())
nocheck_register_item_tree_change(place, *place, mem_root);
}
void change_item_tree(Item **place, Item *new_value)
{
DBUG_ENTER("THD::change_item_tree");
DBUG_PRINT("enter", ("Register: %p (%p) <- %p",
*place, place, new_value));
/* TODO: check for OOM condition here */
if (is_item_tree_change_register_required())
nocheck_register_item_tree_change(place, *place, mem_root);
register_item_tree_change(place);
*place= new_value;
DBUG_VOID_RETURN;
}

View File

@ -3769,8 +3769,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
auto_increment++;
extend_option_list(thd, create_info->db_type, !sql_field->field,
&sql_field->option_list,
create_info->db_type->field_options,
thd->stmt_arena->mem_root);
create_info->db_type->field_options);
if (parse_option_list(thd, &sql_field->option_struct,
&sql_field->option_list,
create_info->db_type->field_options, FALSE,
@ -4039,8 +4038,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->algorithm= key->key_create_info.algorithm;
key_info->option_list= key->option_list;
extend_option_list(thd, create_info->db_type, !key->old,
&key_info->option_list, create_info->db_type->index_options,
thd->stmt_arena->mem_root);
&key_info->option_list, create_info->db_type->index_options);
if (parse_option_list(thd, &key_info->option_struct,
&key_info->option_list,
create_info->db_type->index_options, FALSE,
@ -4633,8 +4631,7 @@ without_overlaps_err:
extend_option_list(thd, file->partition_ht(),
!thd->lex->create_like() && create_table_mode > C_ALTER_TABLE,
&create_info->option_list, file->partition_ht()->table_options,
thd->stmt_arena->mem_root);
&create_info->option_list, file->partition_ht()->table_options);
if (parse_option_list(thd, &create_info->option_struct,
&create_info->option_list,
file->partition_ht()->table_options, FALSE, thd->mem_root))