summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-05-10 10:49:09 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2019-05-10 10:50:35 +0300
commit8ce702aa90c174566f4ac950e85cc7570bf9b647 (patch)
tree2b061af942a1ac94c33f68d8706c69b6a2a93a49
parentb2f3755c8e174ec5385c9a56783f0a77f054c562 (diff)
downloadmariadb-git-8ce702aa90c174566f4ac950e85cc7570bf9b647.tar.gz
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
-rw-r--r--mysql-test/suite/gcol/r/innodb_virtual_purge.result17
-rw-r--r--mysql-test/suite/gcol/t/innodb_virtual_purge.test35
-rw-r--r--storage/innobase/row/row0purge.cc8
3 files changed, 60 insertions, 0 deletions
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_purge.result
index 308b01ded25..ee88527ec2e 100644
--- a/mysql-test/suite/gcol/r/innodb_virtual_purge.result
+++ b/mysql-test/suite/gcol/r/innodb_virtual_purge.result
@@ -142,4 +142,21 @@ CREATE TABLE t1 (a VARCHAR(30), b INT, a2 VARCHAR(30) GENERATED ALWAYS AS (a) VI
CREATE INDEX idx ON t1(a2(10), b, a2(20));
ERROR 42S21: Duplicate column name 'a2'
DROP TABLE t1;
+#
+# MDEV-17540 Server crashes in row_purge after TRUNCATE TABLE
+#
+CREATE TABLE t1 (a BIT(14)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(b'01110110101011'),(b'01100111111000'),(b'00001011110100'),
+(b'01110110111010'),(b'10001010101011'),(b'01100111001111');
+CREATE TABLE t2 (
+pk INT DEFAULT 1,
+b YEAR,
+c BIT(14),
+d YEAR AS (b),
+e BIT(14) AS (c),
+UNIQUE(pk),
+KEY(e)
+) ENGINE=InnoDB;
+DROP TABLE t1, t2;
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
diff --git a/mysql-test/suite/gcol/t/innodb_virtual_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_purge.test
index 4eb5d8c65b8..c79a817dd4e 100644
--- a/mysql-test/suite/gcol/t/innodb_virtual_purge.test
+++ b/mysql-test/suite/gcol/t/innodb_virtual_purge.test
@@ -137,5 +137,40 @@ CREATE INDEX idx ON t1(a2(10), b, a2(20));
DROP TABLE t1;
+--echo #
+--echo # MDEV-17540 Server crashes in row_purge after TRUNCATE TABLE
+--echo #
+
+# Note: this test case is nondeterministic and should depend on
+# MDEV-12288 to trigger the needed purge activity.
+# The test does not seem to repeat the bug on MariaDB 10.2.
+
+CREATE TABLE t1 (a BIT(14)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+ (b'01110110101011'),(b'01100111111000'),(b'00001011110100'),
+ (b'01110110111010'),(b'10001010101011'),(b'01100111001111');
+
+CREATE TABLE t2 (
+ pk INT DEFAULT 1,
+ b YEAR,
+ c BIT(14),
+ d YEAR AS (b),
+ e BIT(14) AS (c),
+ UNIQUE(pk),
+ KEY(e)
+) ENGINE=InnoDB;
+
+# Run a few times in order to improve the chances of triggering the bug.
+--disable_query_log
+let $n=10;
+while ($n) {
+REPLACE INTO t2 (c) SELECT a FROM t1;
+TRUNCATE TABLE t2;
+dec $n;
+}
+--enable_query_log
+
+DROP TABLE t1, t2;
+
--source include/wait_until_count_sessions.inc
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index f5078c5dffb..bd709f98b08 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -824,6 +824,14 @@ row_purge_upd_exist_or_extern_func(
node->row, NULL, node->index,
heap, ROW_BUILD_FOR_PURGE);
row_purge_remove_sec_if_poss(node, node->index, entry);
+
+ if (node->vcol_op_failed()) {
+ ut_ad(!node->table);
+ mem_heap_free(heap);
+ return;
+ }
+ ut_ad(node->table);
+
mem_heap_empty(heap);
}