Skip to content

Commit 7df00f6

Browse files
committed
Bug#21808680: JSON + GENERATED COLUMN CORRUPTS TABLE CACHE MEMORY, CRASHES
In some cases pointers to stale data could be left in the Item tree of the generated column expression, which would lead to problems the next time the generated column was accessed. There is already code in place to avoid this situation. TABLE::cleanup_gc_items() calls Item::cleanup() on the generated column expression upon completion of a statement, and this is supposed to revert the Item tree to a pristine state, ready for reuse in a new statement. However, since the Item::cleanup() functions are not recursive, only the top-level item in the generated column expression will be cleaned up. Children, such as items representing the arguments of a function call, will not be cleaned up and can point to stale data inserted into the item tree during execution. The fix changes TABLE::cleanup_gc_items() so that it calls cleanup() on all the items in the generated column's item_free_list, and not only on the top-level item. The patch also removes an unused parameter from the function.
1 parent 9c3c6c7 commit 7df00f6

File tree

5 files changed

+30
-15
lines changed

5 files changed

+30
-15
lines changed

mysql-test/suite/gcol/r/gcol_bugfixes.result

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,3 +492,14 @@ c13
492492
00:00:01
493493
DROP TABLE C;
494494
DROP VIEW view_C;
495+
#
496+
# Bug #21808680: JSON + GENERATED COLUMN CORRUPTS TABLE CACHE
497+
# MEMORY, CRASHES
498+
#
499+
CREATE TABLE t (a INT, b JSON, c TEXT GENERATED ALWAYS AS (REPEAT(a=b, 2)));
500+
INSERT INTO t (a, b) VALUES (1, '2'), (3, '3');
501+
SELECT * FROM t;
502+
a b c
503+
1 2 00
504+
3 3 11
505+
DROP TABLE t;

mysql-test/suite/gcol/t/gcol_bugfixes.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,3 +485,13 @@ SELECT DISTINCT t1.c13 FROM C AS t1, view_C AS t2;
485485

486486
DROP TABLE C;
487487
DROP VIEW view_C;
488+
489+
--echo #
490+
--echo # Bug #21808680: JSON + GENERATED COLUMN CORRUPTS TABLE CACHE
491+
--echo # MEMORY, CRASHES
492+
--echo #
493+
CREATE TABLE t (a INT, b JSON, c TEXT GENERATED ALWAYS AS (REPEAT(a=b, 2)));
494+
INSERT INTO t (a, b) VALUES (1, '2'), (3, '3');
495+
# The next statement used to crash.
496+
SELECT * FROM t;
497+
DROP TABLE t;

sql/sql_base.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,7 @@ static void mark_temp_tables_as_free_for_reuse(THD *thd)
13371337
if ((table->query_id == thd->query_id) && ! table->open_by_handler)
13381338
{
13391339
mark_tmp_table_for_reuse(table);
1340-
table->cleanup_gc_items(thd);
1340+
table->cleanup_gc_items();
13411341
}
13421342
}
13431343
}
@@ -1567,7 +1567,7 @@ void close_thread_tables(THD *thd)
15671567
{
15681568
DBUG_ASSERT(table->file);
15691569
table->file->extra(HA_EXTRA_DETACH_CHILDREN);
1570-
table->cleanup_gc_items(thd);
1570+
table->cleanup_gc_items();
15711571
}
15721572
}
15731573

sql/table.cc

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4646,17 +4646,13 @@ bool TABLE::refix_gc_items(THD *thd)
46464646
}
46474647

46484648

4649-
void TABLE::cleanup_gc_items(THD *thd)
4649+
void TABLE::cleanup_gc_items()
46504650
{
4651-
if (vfield)
4652-
{
4653-
for (Field **vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
4654-
{
4655-
Field *vfield= *vfield_ptr;
4656-
DBUG_ASSERT(vfield->gcol_info && vfield->gcol_info->expr_item);
4657-
vfield->gcol_info->expr_item->cleanup();
4658-
}
4659-
}
4651+
if (!has_gcol())
4652+
return;
4653+
4654+
for (Field **vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
4655+
cleanup_items((*vfield_ptr)->gcol_info->item_free_list);
46604656
}
46614657

46624658
/*

sql/table.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,10 +1426,8 @@ struct TABLE
14261426
/**
14271427
Clean any state in items associated with generated columns to be ready for
14281428
the next statement.
1429-
1430-
@param[in] thd the current thread
14311429
*/
1432-
void cleanup_gc_items(THD *thd);
1430+
void cleanup_gc_items();
14331431
};
14341432

14351433

0 commit comments

Comments
 (0)