mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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 f0aa073f2b
(MDEV-20950).
This commit is contained in:
@ -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;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
--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;
|
|||||||
|
|
||||||
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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
|
|
||||||
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(
|
|||||||
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 @@ not_locked:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
Reference in New Issue
Block a user