Skip to content

Commit 8ce702a

Browse files
committed
MDEV-17540 Server crashes in row_purge after TRUNCATE TABLE
row_purge_upd_exist_or_extern_func(): Check for node->vcol_op_failed() after row_purge_remove_sec_if_poss(), like row_purge_del_mark() did. This avoids us dereferencing the node->table=NULL pointer. The test case, submitted by Elena Stepanova, is not deterministic and does not repeat the bug on 10.2. With the added loop, for me, it reliably crashes 10.3 without the fix. I was unable to create a deterministic test case for either 10.2 or 10.3. Reviewed by Thirunarayanan Balathandayuthapani
1 parent b2f3755 commit 8ce702a

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,21 @@ CREATE TABLE t1 (a VARCHAR(30), b INT, a2 VARCHAR(30) GENERATED ALWAYS AS (a) VI
142142
CREATE INDEX idx ON t1(a2(10), b, a2(20));
143143
ERROR 42S21: Duplicate column name 'a2'
144144
DROP TABLE t1;
145+
#
146+
# MDEV-17540 Server crashes in row_purge after TRUNCATE TABLE
147+
#
148+
CREATE TABLE t1 (a BIT(14)) ENGINE=InnoDB;
149+
INSERT INTO t1 VALUES
150+
(b'01110110101011'),(b'01100111111000'),(b'00001011110100'),
151+
(b'01110110111010'),(b'10001010101011'),(b'01100111001111');
152+
CREATE TABLE t2 (
153+
pk INT DEFAULT 1,
154+
b YEAR,
155+
c BIT(14),
156+
d YEAR AS (b),
157+
e BIT(14) AS (c),
158+
UNIQUE(pk),
159+
KEY(e)
160+
) ENGINE=InnoDB;
161+
DROP TABLE t1, t2;
145162
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,5 +137,40 @@ CREATE INDEX idx ON t1(a2(10), b, a2(20));
137137

138138
DROP TABLE t1;
139139

140+
--echo #
141+
--echo # MDEV-17540 Server crashes in row_purge after TRUNCATE TABLE
142+
--echo #
143+
144+
# Note: this test case is nondeterministic and should depend on
145+
# MDEV-12288 to trigger the needed purge activity.
146+
# The test does not seem to repeat the bug on MariaDB 10.2.
147+
148+
CREATE TABLE t1 (a BIT(14)) ENGINE=InnoDB;
149+
INSERT INTO t1 VALUES
150+
(b'01110110101011'),(b'01100111111000'),(b'00001011110100'),
151+
(b'01110110111010'),(b'10001010101011'),(b'01100111001111');
152+
153+
CREATE TABLE t2 (
154+
pk INT DEFAULT 1,
155+
b YEAR,
156+
c BIT(14),
157+
d YEAR AS (b),
158+
e BIT(14) AS (c),
159+
UNIQUE(pk),
160+
KEY(e)
161+
) ENGINE=InnoDB;
162+
163+
# Run a few times in order to improve the chances of triggering the bug.
164+
--disable_query_log
165+
let $n=10;
166+
while ($n) {
167+
REPLACE INTO t2 (c) SELECT a FROM t1;
168+
TRUNCATE TABLE t2;
169+
dec $n;
170+
}
171+
--enable_query_log
172+
173+
DROP TABLE t1, t2;
174+
140175
--source include/wait_until_count_sessions.inc
141176
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;

storage/innobase/row/row0purge.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,14 @@ row_purge_upd_exist_or_extern_func(
824824
node->row, NULL, node->index,
825825
heap, ROW_BUILD_FOR_PURGE);
826826
row_purge_remove_sec_if_poss(node, node->index, entry);
827+
828+
if (node->vcol_op_failed()) {
829+
ut_ad(!node->table);
830+
mem_heap_free(heap);
831+
return;
832+
}
833+
ut_ad(node->table);
834+
827835
mem_heap_empty(heap);
828836
}
829837

0 commit comments

Comments
 (0)