Commit f35d1721 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-23198 Crash in REPLACE

row_vers_impl_x_locked_low(): clust_offsets may point to memory
that is allocated by mem_heap_alloc() and may have been freed.
For initializing clust_offsets, try to use the stack-allocated
buffer instead of a pointer that may point to freed memory.

This fixes a regression that was introduced in
commit f0aa073f (MDEV-20950).
parent fd0abc89
...@@ -28,4 +28,18 @@ SELECT * FROM t1; ...@@ -28,4 +28,18 @@ SELECT * FROM t1;
a a
0 0
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-23198 Crash in REPLACE
#
BEGIN NOT ATOMIC
DECLARE c TEXT DEFAULT(SELECT CONCAT('CREATE TABLE t1(id INT PRIMARY KEY, c',
GROUP_CONCAT(seq SEPARATOR ' INT, c'),
' INT NOT NULL UNIQUE) ENGINE=InnoDB')
FROM seq_1_to_294);
EXECUTE IMMEDIATE c;
END;
$$
INSERT INTO t1 SET id=1,c294=1;
REPLACE t1 SET id=1,c294=1;
DROP TABLE t1;
SET GLOBAL innodb_file_per_table= @save_per_table; SET GLOBAL innodb_file_per_table= @save_per_table;
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_sequence.inc
SET @save_per_table= @@GLOBAL.innodb_file_per_table; SET @save_per_table= @@GLOBAL.innodb_file_per_table;
SET GLOBAL innodb_file_per_table= 1; SET GLOBAL innodb_file_per_table= 1;
...@@ -49,4 +50,23 @@ SELECT * FROM t1; ...@@ -49,4 +50,23 @@ SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-23198 Crash in REPLACE
--echo #
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE c TEXT DEFAULT(SELECT CONCAT('CREATE TABLE t1(id INT PRIMARY KEY, c',
GROUP_CONCAT(seq SEPARATOR ' INT, c'),
' INT NOT NULL UNIQUE) ENGINE=InnoDB')
FROM seq_1_to_294);
EXECUTE IMMEDIATE c;
END;
$$
DELIMITER ;$$
INSERT INTO t1 SET id=1,c294=1;
REPLACE t1 SET id=1,c294=1;
DROP TABLE t1;
SET GLOBAL innodb_file_per_table= @save_per_table; SET GLOBAL innodb_file_per_table= @save_per_table;
...@@ -91,7 +91,7 @@ row_vers_impl_x_locked_low( ...@@ -91,7 +91,7 @@ row_vers_impl_x_locked_low(
{ {
rec_t* prev_version = NULL; rec_t* prev_version = NULL;
rec_offs clust_offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs clust_offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs* clust_offsets = clust_offsets_; rec_offs* clust_offsets;
mem_heap_t* heap; mem_heap_t* heap;
dtuple_t* ientry = NULL; dtuple_t* ientry = NULL;
mem_heap_t* v_heap = NULL; mem_heap_t* v_heap = NULL;
...@@ -105,7 +105,7 @@ row_vers_impl_x_locked_low( ...@@ -105,7 +105,7 @@ row_vers_impl_x_locked_low(
heap = mem_heap_create(1024); heap = mem_heap_create(1024);
clust_offsets = rec_get_offsets(clust_rec, clust_index, clust_offsets, clust_offsets = rec_get_offsets(clust_rec, clust_index, clust_offsets_,
true, ULINT_UNDEFINED, &heap); true, ULINT_UNDEFINED, &heap);
const trx_id_t trx_id = row_get_rec_trx_id( const trx_id_t trx_id = row_get_rec_trx_id(
...@@ -187,7 +187,7 @@ row_vers_impl_x_locked_low( ...@@ -187,7 +187,7 @@ row_vers_impl_x_locked_low(
ut_ad(committed || prev_version ut_ad(committed || prev_version
|| !rec_get_deleted_flag(version, comp)); || !rec_get_deleted_flag(version, comp));
/* Free version. */ /* Free version and clust_offsets. */
mem_heap_free(old_heap); mem_heap_free(old_heap);
if (committed) { if (committed) {
...@@ -222,7 +222,7 @@ row_vers_impl_x_locked_low( ...@@ -222,7 +222,7 @@ row_vers_impl_x_locked_low(
} }
clust_offsets = rec_get_offsets( clust_offsets = rec_get_offsets(
prev_version, clust_index, clust_offsets, true, prev_version, clust_index, clust_offsets_, true,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
vers_del = rec_get_deleted_flag(prev_version, comp); vers_del = rec_get_deleted_flag(prev_version, comp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment