From 98e185ee373310291825fe6ac87f45afe6a3ccf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 18 Feb 2019 21:42:58 +0200 Subject: [PATCH] MDEV-18630 Uninitialised value in FOREIGN KEY error message dict_create_foreign_constraints_low(): Clean up the way in which the error messages are initialized, and ensure that the table name is always initialized. --- mysql-test/suite/innodb/r/foreign_key.result | 13 ++++++ mysql-test/suite/innodb/t/foreign_key.test | 12 +++++ storage/innobase/dict/dict0dict.cc | 49 +++++++------------- storage/xtradb/dict/dict0dict.cc | 49 +++++++------------- 4 files changed, 59 insertions(+), 64 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index d28ade4c54353..3c881b4350419 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -92,3 +92,16 @@ Warnings: Warning 1088 failed to load FOREIGN KEY constraints ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f); DROP TABLE t1; +# +# MDEV-18630 Conditional jump or move depends on uninitialised value +# in ib_push_warning / dict_create_foreign_constraints_low +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b); +ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed") +SHOW WARNINGS; +Level Code Message +Warning 150 Alter table test/#sql-temporary with foreign key constraint failed. Referenced table `test`.`t2` not found in the data dictionary near 'FOREIGN KEY (a) REFERENCES t2 (b)'. +Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed") +Warning 1215 Cannot add foreign key constraint +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 3fc8449a6b000..f4117d2d780e6 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -113,3 +113,15 @@ SET SESSION FOREIGN_KEY_CHECKS = ON; ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f); ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f); DROP TABLE t1; + +--echo # +--echo # MDEV-18630 Conditional jump or move depends on uninitialised value +--echo # in ib_push_warning / dict_create_foreign_constraints_low +--echo # +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/ +--error ER_CANT_CREATE_TABLE +ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b); +--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/ +SHOW WARNINGS; +DROP TABLE t1; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 2a37db4e0764a..06c6c3effab67 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -4396,7 +4396,6 @@ dict_create_foreign_constraints_low( const char* create_table_name; const char* orig; char create_name[MAX_TABLE_NAME_LEN + 1]; - char operation[8]; ut_ad(!srv_read_only_mode); ut_ad(mutex_own(&(dict_sys->mutex))); @@ -4407,41 +4406,33 @@ dict_create_foreign_constraints_low( orig = ptr; ptr = dict_accept(cs, ptr, "ALTER", &success); - strcpy((char *)operation, success ? "Alter " : "Create "); + const char* const operation = success ? "Alter " : "Create "; if (!success) { orig = ptr; ptr = dict_scan_to(ptr, "CREATE"); ptr = dict_scan_to(ptr, "TABLE"); ptr = dict_accept(cs, ptr, "TABLE", &success); + create_table_name = NULL; if (success) { ptr = dict_scan_table_name(cs, ptr, &table_to_create, name, - &success, heap, &create_table_name); + &success, heap, &create_table_name); } - if (success) { - char *bufend; - bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN, - create_table_name, strlen(create_table_name), - trx->mysql_thd, TRUE); - create_name[bufend-create_name]='\0'; - ptr = orig; - } else { - char *bufend; - ptr = orig; - bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN, - name, strlen(name), trx->mysql_thd, TRUE); - create_name[bufend-create_name]='\0'; - } - - goto loop; + ptr = orig; + const char* n = create_table_name ? create_table_name : name; + char *bufend = innobase_convert_name(create_name, MAX_TABLE_NAME_LEN, + n, strlen(n), trx->mysql_thd, TRUE); + create_name[bufend-create_name] = '\0'; + } else { + strncpy(create_name, name, sizeof create_name); + create_name[(sizeof create_name) - 1] = '\0'; } if (table == NULL) { mutex_enter(&dict_foreign_err_mutex); dict_foreign_error_report_low(ef, create_name); - dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint" " failed. Table %s not found from data dictionary." " Error close to %s.\n", @@ -4476,19 +4467,13 @@ dict_create_foreign_constraints_low( ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name, &success, heap, &referenced_table_name); - if (table_to_alter) { - char *bufend; - bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN, - table_to_alter->name, strlen(table_to_alter->name), - trx->mysql_thd, TRUE); - create_name[bufend-create_name]='\0'; - } else { - char *bufend; - bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN, - referenced_table_name, strlen(referenced_table_name), - trx->mysql_thd, TRUE); + { + const char* n = table_to_alter + ? table_to_alter->name : referenced_table_name; + char* bufend = innobase_convert_name( + create_name, MAX_TABLE_NAME_LEN, n, strlen(n), + trx->mysql_thd, TRUE); create_name[bufend-create_name]='\0'; - } if (!success) { diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index 1eb0a53e0b0c5..1c489d13f1a50 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -4405,7 +4405,6 @@ dict_create_foreign_constraints_low( const char* create_table_name; const char* orig; char create_name[MAX_TABLE_NAME_LEN + 1]; - char operation[8]; ut_ad(!srv_read_only_mode); ut_ad(mutex_own(&(dict_sys->mutex))); @@ -4416,41 +4415,33 @@ dict_create_foreign_constraints_low( orig = ptr; ptr = dict_accept(cs, ptr, "ALTER", &success); - strcpy((char *)operation, success ? "Alter " : "Create "); + const char* const operation = success ? "Alter " : "Create "; if (!success) { orig = ptr; ptr = dict_scan_to(ptr, "CREATE"); ptr = dict_scan_to(ptr, "TABLE"); ptr = dict_accept(cs, ptr, "TABLE", &success); + create_table_name = NULL; if (success) { ptr = dict_scan_table_name(cs, ptr, &table_to_create, name, - &success, heap, &create_table_name); + &success, heap, &create_table_name); } - if (success) { - char *bufend; - bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN, - create_table_name, strlen(create_table_name), - trx->mysql_thd, TRUE); - create_name[bufend-create_name]='\0'; - ptr = orig; - } else { - char *bufend; - ptr = orig; - bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN, - name, strlen(name), trx->mysql_thd, TRUE); - create_name[bufend-create_name]='\0'; - } - - goto loop; + ptr = orig; + const char* n = create_table_name ? create_table_name : name; + char *bufend = innobase_convert_name(create_name, MAX_TABLE_NAME_LEN, + n, strlen(n), trx->mysql_thd, TRUE); + create_name[bufend-create_name] = '\0'; + } else { + strncpy(create_name, name, sizeof create_name); + create_name[(sizeof create_name) - 1] = '\0'; } if (table == NULL) { mutex_enter(&dict_foreign_err_mutex); dict_foreign_error_report_low(ef, create_name); - dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint" " failed. Table %s not found from data dictionary." " Error close to %s.\n", @@ -4485,19 +4476,13 @@ dict_create_foreign_constraints_low( ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name, &success, heap, &referenced_table_name); - if (table_to_alter) { - char *bufend; - bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN, - table_to_alter->name, strlen(table_to_alter->name), - trx->mysql_thd, TRUE); - create_name[bufend-create_name]='\0'; - } else { - char *bufend; - bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN, - referenced_table_name, strlen(referenced_table_name), - trx->mysql_thd, TRUE); + { + const char* n = table_to_alter + ? table_to_alter->name : referenced_table_name; + char* bufend = innobase_convert_name( + create_name, MAX_TABLE_NAME_LEN, n, strlen(n), + trx->mysql_thd, TRUE); create_name[bufend-create_name]='\0'; - } if (!success) {