mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-30441 ASAN heap-use-after-free in Field_blob::pack/pack_row
When InnoDB computes an indexed virtual column (e.g. the long unique hash), TABLE::update_virtual_field() walked its expression with update_vcol_processor() and recomputed every vcol it referenced, including STORED ones. innobase_allocate_row_for_vcol() saves and restores Field_blob::value only for non-stored blob vcols, so recomputing a STORED blob vcol in Field_blob::store_field() did val_str(&value) and freed the buffer that record[0] still pointed to. The row-format binlog then packed record[0] from freed memory. The buffer is allocated only when the value is converted, so the bug needs a character set conversion (e.g. BLOB to utf8mb3 TEXT). The fix skips STORED vcols in update_vcol_processor(). Their values are already in the record: InnoDB copies them as base columns of the virtual column, and the SQL layer computes them before writing. The test cases detect the bug only under ASAN or Valgrind.
This commit is contained in:
@@ -850,4 +850,18 @@ create table t(c int primary key, c2 blob unique) engine=innodb;
|
||||
insert into t values (0, '');
|
||||
replace into t values (0, '123');
|
||||
drop table t;
|
||||
#
|
||||
# MDEV-30441 ASAN heap-use-after-free in Field_blob::pack/pack_row
|
||||
#
|
||||
create table t1 (a blob, va mediumtext as (a) stored, b varchar(3845),
|
||||
unique key (b, va(64)))
|
||||
engine=innodb default charset=utf8mb3;
|
||||
insert into t1 (a, b) values ('111', '222');
|
||||
delete from t1 order by b limit 1;
|
||||
drop table t1;
|
||||
create table t (a blob, b text as (a) stored, unique (b))
|
||||
engine=innodb character set utf8mb3
|
||||
as select 'x' as a;
|
||||
delete from t;
|
||||
drop table t;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -776,4 +776,20 @@ insert into t values (0, '');
|
||||
replace into t values (0, '123');
|
||||
drop table t;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-30441 ASAN heap-use-after-free in Field_blob::pack/pack_row
|
||||
--echo #
|
||||
create table t1 (a blob, va mediumtext as (a) stored, b varchar(3845),
|
||||
unique key (b, va(64)))
|
||||
engine=innodb default charset=utf8mb3;
|
||||
insert into t1 (a, b) values ('111', '222');
|
||||
delete from t1 order by b limit 1;
|
||||
drop table t1;
|
||||
|
||||
create table t (a blob, b text as (a) stored, unique (b))
|
||||
engine=innodb character set utf8mb3
|
||||
as select 'x' as a;
|
||||
delete from t;
|
||||
drop table t;
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
@@ -980,7 +980,11 @@ bool Item_field::check_field_expression_processor(void *arg)
|
||||
bool Item_field::update_vcol_processor(void *arg)
|
||||
{
|
||||
MY_BITMAP *map= (MY_BITMAP *) arg;
|
||||
if (field->vcol_info &&
|
||||
/*
|
||||
Stored vcols are not recomputed: the caller must have their values
|
||||
in the record (the engine fills them as base columns).
|
||||
*/
|
||||
if (!field->stored_in_db() &&
|
||||
!bitmap_fast_test_and_set(map, field->field_index))
|
||||
{
|
||||
field->vcol_info->expr->walk(&Item::update_vcol_processor, 0, arg);
|
||||
|
||||
Reference in New Issue
Block a user