MDEV-26281 ASAN use-after-poison when complex conversion is involved in blob

the bug was that in_vector array in Item_func_in was allocated in the
statement arena, not in the table->expr_arena.

revert part of the 5acd391e8b. Instead, change the arena correctly
in fix_all_session_vcol_exprs().

Remove TABLE_ARENA, that was introduced in 5acd391e8b to force
item tree changes to be rolled back (because they were allocated in the
wrong arena and didn't persist. now they do)
This commit is contained in:
Sergei Golubchik 2022-04-14 21:45:20 +02:00
parent cc08c43ed6
commit 4681b6f2d8
5 changed files with 43 additions and 28 deletions

View file

@ -1,3 +1,6 @@
#
# MDEV-9690 concurrent queries with virtual columns crash in temporal code
#
create table t1 (a datetime, create table t1 (a datetime,
# get_datetime_value # get_datetime_value
b int as (a > 1), # Arg_comparator b int as (a > 1), # Arg_comparator
@ -59,6 +62,9 @@ a b
Warnings: Warnings:
Warning 1292 Incorrect datetime value: '1' Warning 1292 Incorrect datetime value: '1'
drop table t1; drop table t1;
#
# MDEV-13435 Crash when selecting virtual columns generated using JSON functions
#
create table t1 ( create table t1 (
id int not null , id int not null ,
js varchar(1000) not null, js varchar(1000) not null,
@ -68,3 +74,16 @@ select * from t1;
id js t id js t
0 {"default" : {"start": "00:00:00", "end":"23:59:50"}} NULL 0 {"default" : {"start": "00:00:00", "end":"23:59:50"}} NULL
drop table t1; drop table t1;
#
# MDEV-26281 ASAN use-after-poison when complex conversion is involved in blob
#
create table t1 (v2 blob as ('a' is null), a1 int, a char(1) as (cast(a1 in (0,current_user() is null) as char(16777216) )));
insert ignore into t1 values ('x','x',v2) ;
Warnings:
Warning 1906 The value specified for generated column 'v2' in table 't1' has been ignored
Warning 1366 Incorrect integer value: 'x' for column `test`.`t1`.`a1` at row 1
Warning 1906 The value specified for generated column 'a' in table 't1' has been ignored
drop table t1;
#
# End of 10.2 tests
#

View file

@ -3,9 +3,9 @@
# not in the TABLE::expr_arena. # not in the TABLE::expr_arena.
# #
# --echo #
# MDEV-9690 concurrent queries with virtual columns crash in temporal code --echo # MDEV-9690 concurrent queries with virtual columns crash in temporal code
# --echo #
create table t1 (a datetime, create table t1 (a datetime,
# get_datetime_value # get_datetime_value
b int as (a > 1), # Arg_comparator b int as (a > 1), # Arg_comparator
@ -40,9 +40,9 @@ connection default;
select * from t1; select * from t1;
drop table t1; drop table t1;
# --echo #
# MDEV-13435 Crash when selecting virtual columns generated using JSON functions --echo # MDEV-13435 Crash when selecting virtual columns generated using JSON functions
# --echo #
create table t1 ( create table t1 (
id int not null , id int not null ,
js varchar(1000) not null, js varchar(1000) not null,
@ -50,3 +50,14 @@ create table t1 (
insert into t1(id,js) values (0, '{"default" : {"start": "00:00:00", "end":"23:59:50"}}'); insert into t1(id,js) values (0, '{"default" : {"start": "00:00:00", "end":"23:59:50"}}');
select * from t1; select * from t1;
drop table t1; drop table t1;
--echo #
--echo # MDEV-26281 ASAN use-after-poison when complex conversion is involved in blob
--echo #
create table t1 (v2 blob as ('a' is null), a1 int, a char(1) as (cast(a1 in (0,current_user() is null) as char(16777216) )));
insert ignore into t1 values ('x','x',v2) ;
drop table t1;
--echo #
--echo # End of 10.2 tests
--echo #

View file

@ -5010,16 +5010,13 @@ static bool fix_all_session_vcol_exprs(THD *thd, TABLE_LIST *tables)
if (!table->placeholder() && t->s->vcols_need_refixing && if (!table->placeholder() && t->s->vcols_need_refixing &&
table->lock_type >= TL_WRITE_ALLOW_WRITE) table->lock_type >= TL_WRITE_ALLOW_WRITE)
{ {
Query_arena *stmt_backup= thd->stmt_arena; Query_arena backup_arena;
if (thd->stmt_arena->is_conventional()) thd->set_n_backup_active_arena(t->expr_arena, &backup_arena);
thd->stmt_arena= t->expr_arena;
if (table->security_ctx) if (table->security_ctx)
thd->security_ctx= table->security_ctx; thd->security_ctx= table->security_ctx;
error= t->fix_vcol_exprs(thd); error= t->fix_vcol_exprs(thd);
thd->security_ctx= save_security_ctx; thd->security_ctx= save_security_ctx;
thd->stmt_arena= stmt_backup; thd->restore_active_arena(t->expr_arena, &backup_arena);
} }
} }
DBUG_RETURN(error); DBUG_RETURN(error);

View file

@ -967,7 +967,7 @@ public:
/* We build without RTTI, so dynamic_cast can't be used. */ /* We build without RTTI, so dynamic_cast can't be used. */
enum Type enum Type
{ {
STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE, TABLE_ARENA STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE
}; };
Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) : Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
@ -3728,8 +3728,7 @@ public:
bool is_item_tree_change_register_required() bool is_item_tree_change_register_required()
{ {
return !stmt_arena->is_conventional() return !stmt_arena->is_conventional();
|| stmt_arena->type() == Query_arena::TABLE_ARENA;
} }
void change_item_tree(Item **place, Item *new_value) void change_item_tree(Item **place, Item *new_value)

View file

@ -47,17 +47,6 @@
#define MYSQL57_GENERATED_FIELD 128 #define MYSQL57_GENERATED_FIELD 128
#define MYSQL57_GCOL_HEADER_SIZE 4 #define MYSQL57_GCOL_HEADER_SIZE 4
class Table_arena: public Query_arena
{
public:
Table_arena(MEM_ROOT *mem_root, enum enum_state state_arg) :
Query_arena(mem_root, state_arg){}
virtual Type type() const
{
return TABLE_ARENA;
}
};
static Virtual_column_info * unpack_vcol_info_from_frm(THD *, MEM_ROOT *, static Virtual_column_info * unpack_vcol_info_from_frm(THD *, MEM_ROOT *,
TABLE *, String *, Virtual_column_info **, bool *); TABLE *, String *, Virtual_column_info **, bool *);
static bool check_vcol_forward_refs(Field *, Virtual_column_info *); static bool check_vcol_forward_refs(Field *, Virtual_column_info *);
@ -1031,8 +1020,8 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
We need to use CONVENTIONAL_EXECUTION here to ensure that We need to use CONVENTIONAL_EXECUTION here to ensure that
any new items created by fix_fields() are not reverted. any new items created by fix_fields() are not reverted.
*/ */
table->expr_arena= new (alloc_root(mem_root, sizeof(Table_arena))) table->expr_arena= new (alloc_root(mem_root, sizeof(Query_arena)))
Table_arena(mem_root, Query_arena(mem_root,
Query_arena::STMT_CONVENTIONAL_EXECUTION); Query_arena::STMT_CONVENTIONAL_EXECUTION);
if (!table->expr_arena) if (!table->expr_arena)
DBUG_RETURN(1); DBUG_RETURN(1);