MDEV-29425 Buffer overflow in dict_index_t::col_info::add()

- During rollback of DDL, InnoDB should copy the collation
changed column into the index heap
parent 40aa94df
...@@ -51,25 +51,39 @@ id msg ...@@ -51,25 +51,39 @@ id msg
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
id INT PRIMARY KEY, id INT PRIMARY KEY,
f1 INT NOT NULL,
f2 INT NOT NULL,
f3 INT NOT NULL,
msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin, msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin,
unique index(msg) msg_1 VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin,
unique index(f1, msg, f2, msg_1, f3),
unique index(f1, msg_1, f2, msg, f3),
unique index(f1, msg, f3, msg_1, f2),
unique index(f1, msg_1, f3, msg, f2),
unique index(f2, msg_1, f1, msg, f3),
unique index(f2, msg, f3, msg_1, f1),
unique index(f3, f2, msg, msg_1, f1),
unique index(f3, msg, msg_1, f1, f2)
) ENGINE=INNODB; ) ENGINE=INNODB;
INSERT INTO t1 VALUES (1, 'aaa'); INSERT INTO t1 VALUES (1, 1, 1, 1, 'aaa', 'aaa');
SET DEBUG_DBUG="+d,create_index_fail"; SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY; ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, MODIFY msg_1 VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY;
connection con1; connection con1;
SET DEBUG_SYNC="now WAIT_FOR con1_go"; SET DEBUG_SYNC="now WAIT_FOR con1_go";
BEGIN; BEGIN;
SELECT * FROM t1; SELECT * FROM t1;
id msg id f1 f2 f3 msg msg_1
1 aaa 1 1 1 1 aaa aaa
SET DEBUG_SYNC="now SIGNAL alter_signal"; SET DEBUG_SYNC="now SIGNAL alter_signal";
connection default; connection default;
ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
connection con1; connection con1;
rollback; rollback;
INSERT INTO t1 VALUES(2, 'bbb'); INSERT INTO t1 VALUES(2, 2, 2, 2, 'bbb', 'bbb');
disconnect con1; disconnect con1;
connection default; connection default;
SET DEBUG_SYNC=reset; SET DEBUG_SYNC=reset;
...@@ -77,11 +91,22 @@ SHOW CREATE TABLE t1; ...@@ -77,11 +91,22 @@ SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL, `id` int(11) NOT NULL,
`f1` int(11) NOT NULL,
`f2` int(11) NOT NULL,
`f3` int(11) NOT NULL,
`msg` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL, `msg` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`msg_1` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `msg` (`msg`) UNIQUE KEY `f1` (`f1`,`msg`,`f2`,`msg_1`,`f3`),
UNIQUE KEY `f1_2` (`f1`,`msg_1`,`f2`,`msg`,`f3`),
UNIQUE KEY `f1_3` (`f1`,`msg`,`f3`,`msg_1`,`f2`),
UNIQUE KEY `f1_4` (`f1`,`msg_1`,`f3`,`msg`,`f2`),
UNIQUE KEY `f2` (`f2`,`msg_1`,`f1`,`msg`,`f3`),
UNIQUE KEY `f2_2` (`f2`,`msg`,`f3`,`msg_1`,`f1`),
UNIQUE KEY `f3` (`f3`,`f2`,`msg`,`msg_1`,`f1`),
UNIQUE KEY `f3_2` (`f3`,`msg`,`msg_1`,`f1`,`f2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES(3, 'ccc'); INSERT INTO t1 VALUES(3, 3, 3, 3, 'ccc', 'ccc');
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(id INT PRIMARY KEY, msg VARCHAR(100), CREATE TABLE t1(id INT PRIMARY KEY, msg VARCHAR(100),
msg_1 VARCHAR(100) AS (msg) VIRTUAL, msg_1 VARCHAR(100) AS (msg) VIRTUAL,
......
...@@ -78,15 +78,26 @@ DROP TABLE t1; ...@@ -78,15 +78,26 @@ DROP TABLE t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
id INT PRIMARY KEY, id INT PRIMARY KEY,
f1 INT NOT NULL,
f2 INT NOT NULL,
f3 INT NOT NULL,
msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin, msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin,
unique index(msg) msg_1 VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin,
unique index(f1, msg, f2, msg_1, f3),
unique index(f1, msg_1, f2, msg, f3),
unique index(f1, msg, f3, msg_1, f2),
unique index(f1, msg_1, f3, msg, f2),
unique index(f2, msg_1, f1, msg, f3),
unique index(f2, msg, f3, msg_1, f1),
unique index(f3, f2, msg, msg_1, f1),
unique index(f3, msg, msg_1, f1, f2)
) ENGINE=INNODB; ) ENGINE=INNODB;
INSERT INTO t1 VALUES (1, 'aaa'); INSERT INTO t1 VALUES (1, 1, 1, 1, 'aaa', 'aaa');
SET DEBUG_DBUG="+d,create_index_fail"; SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
--send --send
ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY; ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, MODIFY msg_1 VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY;
connection con1; connection con1;
SET DEBUG_SYNC="now WAIT_FOR con1_go"; SET DEBUG_SYNC="now WAIT_FOR con1_go";
...@@ -96,14 +107,15 @@ SET DEBUG_SYNC="now SIGNAL alter_signal"; ...@@ -96,14 +107,15 @@ SET DEBUG_SYNC="now SIGNAL alter_signal";
connection default; connection default;
--error ER_DUP_ENTRY --error ER_DUP_ENTRY
reap; reap;
CHECK TABLE t1;
connection con1; connection con1;
rollback; rollback;
INSERT INTO t1 VALUES(2, 'bbb'); INSERT INTO t1 VALUES(2, 2, 2, 2, 'bbb', 'bbb');
disconnect con1; disconnect con1;
connection default; connection default;
SET DEBUG_SYNC=reset; SET DEBUG_SYNC=reset;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES(3, 'ccc'); INSERT INTO t1 VALUES(3, 3, 3, 3, 'ccc', 'ccc');
DROP TABLE t1; DROP TABLE t1;
# Inplace Collation change is not supported for virtual column # Inplace Collation change is not supported for virtual column
......
...@@ -1444,12 +1444,16 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx ...@@ -1444,12 +1444,16 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
for (unsigned i= 0, j= 0; i < index->n_fields; i++) for (unsigned i= 0, j= 0; i < index->n_fields; i++)
{ {
const dict_col_t *col= index->fields[i].col; const dict_col_t *col= index->fields[i].col;
if (change_col_collate.find(col->ind) == collate_end) auto it= change_col_collate.find(col->ind);
if (it != collate_end)
{
ut_ad(it->second == col);
index->fields[i].col= index->fields[i].col=
index->change_col_info->add(index->heap, *col, j++); index->change_col_info->add(index->heap, *col, j++);
} }
} }
} }
}
}; };
/********************************************************************//** /********************************************************************//**
......
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