summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-02-18 21:42:58 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-02-18 21:42:58 +0200
commit98e185ee373310291825fe6ac87f45afe6a3ccf7 (patch)
tree8147b94ba3093e5e404978025bd3c371cd88b54c
parent5b827511116feb2e3f594cb4e7df816e8704b153 (diff)
downloadmariadb-git-98e185ee373310291825fe6ac87f45afe6a3ccf7.tar.gz
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.
-rw-r--r--mysql-test/suite/innodb/r/foreign_key.result13
-rw-r--r--mysql-test/suite/innodb/t/foreign_key.test12
-rw-r--r--storage/innobase/dict/dict0dict.cc49
-rw-r--r--storage/xtradb/dict/dict0dict.cc49
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 d28ade4c543..3c881b43504 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 3fc8449a6b0..f4117d2d780 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 2a37db4e076..06c6c3effab 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 1eb0a53e0b0..1c489d13f1a 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) {