Skip to content

Commit

Permalink
MDEV-29425 Buffer overflow in dict_index_t::col_info::add()
Browse files Browse the repository at this point in the history
- During rollback of DDL, InnoDB should copy the collation
changed column into the index heap
  • Loading branch information
Thirunarayanan committed Sep 1, 2022
1 parent 40aa94d commit e27c3d5
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 14 deletions.
41 changes: 33 additions & 8 deletions mysql-test/suite/innodb/r/change_column_collation.result
Original file line number Diff line number Diff line change
Expand Up @@ -51,37 +51,62 @@ id msg
DROP TABLE t1;
CREATE TABLE t1 (
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,
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;
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_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;
SET DEBUG_SYNC="now WAIT_FOR con1_go";
BEGIN;
SELECT * FROM t1;
id msg
1 aaa
id f1 f2 f3 msg msg_1
1 1 1 1 aaa aaa
SET DEBUG_SYNC="now SIGNAL alter_signal";
connection default;
ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
connection con1;
rollback;
INSERT INTO t1 VALUES(2, 'bbb');
INSERT INTO t1 VALUES(2, 2, 2, 2, 'bbb', 'bbb');
disconnect con1;
connection default;
SET DEBUG_SYNC=reset;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`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_1` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
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
INSERT INTO t1 VALUES(3, 'ccc');
INSERT INTO t1 VALUES(3, 3, 3, 3, 'ccc', 'ccc');
DROP TABLE t1;
CREATE TABLE t1(id INT PRIMARY KEY, msg VARCHAR(100),
msg_1 VARCHAR(100) AS (msg) VIRTUAL,
Expand Down
22 changes: 17 additions & 5 deletions mysql-test/suite/innodb/t/change_column_collation.test
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,26 @@ DROP TABLE t1;

CREATE TABLE t1 (
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,
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;

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_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
--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;
SET DEBUG_SYNC="now WAIT_FOR con1_go";
Expand All @@ -96,14 +107,15 @@ SET DEBUG_SYNC="now SIGNAL alter_signal";
connection default;
--error ER_DUP_ENTRY
reap;
CHECK TABLE t1;
connection con1;
rollback;
INSERT INTO t1 VALUES(2, 'bbb');
INSERT INTO t1 VALUES(2, 2, 2, 2, 'bbb', 'bbb');
disconnect con1;
connection default;
SET DEBUG_SYNC=reset;
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES(3, 'ccc');
INSERT INTO t1 VALUES(3, 3, 3, 3, 'ccc', 'ccc');
DROP TABLE t1;

# Inplace Collation change is not supported for virtual column
Expand Down
6 changes: 5 additions & 1 deletion storage/innobase/handler/handler0alter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1444,9 +1444,13 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
for (unsigned i= 0, j= 0; i < index->n_fields; i++)
{
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->change_col_info->add(index->heap, *col, j++);
}
}
}
}
Expand Down

0 comments on commit e27c3d5

Please sign in to comment.