1
0
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:
Aleksey Midenkov
2026-10-12 14:19:29 +03:00
parent 8226e48ab5
commit ac9c38fde0
3 changed files with 35 additions and 1 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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);