Commit 422f3204 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-29409 Buffer overflow in my_wc_mb_filename() on RENAME TABLE

dict_table_rename_in_cache(), dict_table_get_highest_foreign_id():
Reserve sufficient space for the fkid[] buffer, and ensure that the
fkid[] will be NUL-terminated.

The fkid[] must accommodate both the database name (which is already
encoded in my_charset_filename) and the constraint name
(which must be converted to my_charset_filename) so that we can check
if it is in the format databasename/tablename_ibfk_1 (all encoded in
my_charset_filename).
parent b2609038
...@@ -18,6 +18,14 @@ CREATE TABLE `d255`.`d245` (x INT) ENGINE=InnoDB; ...@@ -18,6 +18,14 @@ CREATE TABLE `d255`.`d245` (x INT) ENGINE=InnoDB;
DROP TABLE `d255`.`d250`; DROP TABLE `d255`.`d250`;
RENAME TABLE `d250#`.`d245` TO `d250#`.`d250`; RENAME TABLE `d250#`.`d245` TO `d250#`.`d250`;
RENAME TABLE `d255`.`d250` TO a; RENAME TABLE `d255`.`d250` TO a;
DROP DATABASE `d255`;
DROP TABLE a,t; DROP TABLE a,t;
#
# MDEV-29409 Buffer overflow in my_wc_mb_filename() on RENAME TABLE
#
CREATE TABLE `d255`.t(a INT PRIMARY KEY)ENGINE=InnoDB;
CREATE TABLE `d255`.u(a INT PRIMARY KEY,
CONSTRAINT `d320` FOREIGN KEY (a) REFERENCES `d255`.t (a)) ENGINE=InnoDB;
RENAME TABLE `d255`.u TO u;
DROP TABLE u;
DROP DATABASE `d255`;
# End of 10.3 tests # End of 10.3 tests
...@@ -54,7 +54,24 @@ eval RENAME TABLE `$d255`.`$d245` TO `$d255`.`$d250`; ...@@ -54,7 +54,24 @@ eval RENAME TABLE `$d255`.`$d245` TO `$d255`.`$d250`;
--replace_result $d250 d250 $d255 d255 --replace_result $d250 d250 $d255 d255
eval RENAME TABLE `$d255`.`$d250` TO a; eval RENAME TABLE `$d255`.`$d250` TO a;
--replace_result $d255 d255 --replace_result $d255 d255
eval DROP DATABASE `$d255`;
DROP TABLE a,t; DROP TABLE a,t;
--echo #
--echo # MDEV-29409 Buffer overflow in my_wc_mb_filename() on RENAME TABLE
--echo #
let $d225=#############################################;
let $d320=################################################################;
--replace_result $d255 d255
eval CREATE TABLE `$d255`.t(a INT PRIMARY KEY)ENGINE=InnoDB;
--replace_result $d255 d255 $d320 d320
eval CREATE TABLE `$d255`.u(a INT PRIMARY KEY,
CONSTRAINT `$d320` FOREIGN KEY (a) REFERENCES `$d255`.t (a)) ENGINE=InnoDB;
--replace_result $d255 d255
eval RENAME TABLE `$d255`.u TO u;
DROP TABLE u;
--replace_result $d255 d255
eval DROP DATABASE `$d255`;
--echo # End of 10.3 tests --echo # End of 10.3 tests
...@@ -1595,7 +1595,7 @@ dict_table_rename_in_cache( ...@@ -1595,7 +1595,7 @@ dict_table_rename_in_cache(
in UTF-8 charset. The variable fkid here is used in UTF-8 charset. The variable fkid here is used
to store foreign key constraint name in charset to store foreign key constraint name in charset
my_charset_filename for comparison further below. */ my_charset_filename for comparison further below. */
char fkid[MAX_TABLE_NAME_LEN+20]; char fkid[MAX_TABLE_NAME_LEN * 2 + 20];
ibool on_tmp = FALSE; ibool on_tmp = FALSE;
/* The old table name in my_charset_filename is stored /* The old table name in my_charset_filename is stored
...@@ -1629,7 +1629,8 @@ dict_table_rename_in_cache( ...@@ -1629,7 +1629,8 @@ dict_table_rename_in_cache(
} }
} }
strncpy(fkid, foreign->id, MAX_TABLE_NAME_LEN); strncpy(fkid, foreign->id, (sizeof fkid) - 1);
fkid[(sizeof fkid) - 1] = '\0';
if (strstr(fkid, TEMP_TABLE_PATH_PREFIX) == NULL) { if (strstr(fkid, TEMP_TABLE_PATH_PREFIX) == NULL) {
innobase_convert_to_filename_charset( innobase_convert_to_filename_charset(
...@@ -3671,10 +3672,11 @@ dict_table_get_highest_foreign_id( ...@@ -3671,10 +3672,11 @@ dict_table_get_highest_foreign_id(
for (dict_foreign_set::iterator it = table->foreign_set.begin(); for (dict_foreign_set::iterator it = table->foreign_set.begin();
it != table->foreign_set.end(); it != table->foreign_set.end();
++it) { ++it) {
char fkid[MAX_TABLE_NAME_LEN+20]; char fkid[MAX_TABLE_NAME_LEN * 2 + 20];
foreign = *it; foreign = *it;
strcpy(fkid, foreign->id); strncpy(fkid, foreign->id, (sizeof fkid) - 1);
fkid[(sizeof fkid) - 1] = '\0';
/* Convert foreign key identifier on dictionary memory /* Convert foreign key identifier on dictionary memory
cache to filename charset. */ cache to filename charset. */
innobase_convert_to_filename_charset( innobase_convert_to_filename_charset(
......
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