Skip to content

Commit 98e185e

Browse files
committed
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.
1 parent 5b82751 commit 98e185e

File tree

4 files changed

+59
-64
lines changed

4 files changed

+59
-64
lines changed

mysql-test/suite/innodb/r/foreign_key.result

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,16 @@ Warnings:
9292
Warning 1088 failed to load FOREIGN KEY constraints
9393
ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f);
9494
DROP TABLE t1;
95+
#
96+
# MDEV-18630 Conditional jump or move depends on uninitialised value
97+
# in ib_push_warning / dict_create_foreign_constraints_low
98+
#
99+
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
100+
ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b);
101+
ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
102+
SHOW WARNINGS;
103+
Level Code Message
104+
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)'.
105+
Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
106+
Warning 1215 Cannot add foreign key constraint
107+
DROP TABLE t1;

mysql-test/suite/innodb/t/foreign_key.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,15 @@ SET SESSION FOREIGN_KEY_CHECKS = ON;
113113
ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f);
114114
ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f);
115115
DROP TABLE t1;
116+
117+
--echo #
118+
--echo # MDEV-18630 Conditional jump or move depends on uninitialised value
119+
--echo # in ib_push_warning / dict_create_foreign_constraints_low
120+
--echo #
121+
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
122+
--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/
123+
--error ER_CANT_CREATE_TABLE
124+
ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b);
125+
--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/
126+
SHOW WARNINGS;
127+
DROP TABLE t1;

storage/innobase/dict/dict0dict.cc

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4396,7 +4396,6 @@ dict_create_foreign_constraints_low(
43964396
const char* create_table_name;
43974397
const char* orig;
43984398
char create_name[MAX_TABLE_NAME_LEN + 1];
4399-
char operation[8];
44004399

44014400
ut_ad(!srv_read_only_mode);
44024401
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -4407,41 +4406,33 @@ dict_create_foreign_constraints_low(
44074406
orig = ptr;
44084407
ptr = dict_accept(cs, ptr, "ALTER", &success);
44094408

4410-
strcpy((char *)operation, success ? "Alter " : "Create ");
4409+
const char* const operation = success ? "Alter " : "Create ";
44114410

44124411
if (!success) {
44134412
orig = ptr;
44144413
ptr = dict_scan_to(ptr, "CREATE");
44154414
ptr = dict_scan_to(ptr, "TABLE");
44164415
ptr = dict_accept(cs, ptr, "TABLE", &success);
4416+
create_table_name = NULL;
44174417

44184418
if (success) {
44194419
ptr = dict_scan_table_name(cs, ptr, &table_to_create, name,
4420-
&success, heap, &create_table_name);
4420+
&success, heap, &create_table_name);
44214421
}
44224422

4423-
if (success) {
4424-
char *bufend;
4425-
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
4426-
create_table_name, strlen(create_table_name),
4427-
trx->mysql_thd, TRUE);
4428-
create_name[bufend-create_name]='\0';
4429-
ptr = orig;
4430-
} else {
4431-
char *bufend;
4432-
ptr = orig;
4433-
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
4434-
name, strlen(name), trx->mysql_thd, TRUE);
4435-
create_name[bufend-create_name]='\0';
4436-
}
4437-
4438-
goto loop;
4423+
ptr = orig;
4424+
const char* n = create_table_name ? create_table_name : name;
4425+
char *bufend = innobase_convert_name(create_name, MAX_TABLE_NAME_LEN,
4426+
n, strlen(n), trx->mysql_thd, TRUE);
4427+
create_name[bufend-create_name] = '\0';
4428+
} else {
4429+
strncpy(create_name, name, sizeof create_name);
4430+
create_name[(sizeof create_name) - 1] = '\0';
44394431
}
44404432

44414433
if (table == NULL) {
44424434
mutex_enter(&dict_foreign_err_mutex);
44434435
dict_foreign_error_report_low(ef, create_name);
4444-
dict_foreign_error_report_low(ef, create_name);
44454436
fprintf(ef, "%s table %s with foreign key constraint"
44464437
" failed. Table %s not found from data dictionary."
44474438
" Error close to %s.\n",
@@ -4476,19 +4467,13 @@ dict_create_foreign_constraints_low(
44764467
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
44774468
&success, heap, &referenced_table_name);
44784469

4479-
if (table_to_alter) {
4480-
char *bufend;
4481-
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
4482-
table_to_alter->name, strlen(table_to_alter->name),
4483-
trx->mysql_thd, TRUE);
4484-
create_name[bufend-create_name]='\0';
4485-
} else {
4486-
char *bufend;
4487-
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
4488-
referenced_table_name, strlen(referenced_table_name),
4489-
trx->mysql_thd, TRUE);
4470+
{
4471+
const char* n = table_to_alter
4472+
? table_to_alter->name : referenced_table_name;
4473+
char* bufend = innobase_convert_name(
4474+
create_name, MAX_TABLE_NAME_LEN, n, strlen(n),
4475+
trx->mysql_thd, TRUE);
44904476
create_name[bufend-create_name]='\0';
4491-
44924477
}
44934478

44944479
if (!success) {

storage/xtradb/dict/dict0dict.cc

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4405,7 +4405,6 @@ dict_create_foreign_constraints_low(
44054405
const char* create_table_name;
44064406
const char* orig;
44074407
char create_name[MAX_TABLE_NAME_LEN + 1];
4408-
char operation[8];
44094408

44104409
ut_ad(!srv_read_only_mode);
44114410
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -4416,41 +4415,33 @@ dict_create_foreign_constraints_low(
44164415
orig = ptr;
44174416
ptr = dict_accept(cs, ptr, "ALTER", &success);
44184417

4419-
strcpy((char *)operation, success ? "Alter " : "Create ");
4418+
const char* const operation = success ? "Alter " : "Create ";
44204419

44214420
if (!success) {
44224421
orig = ptr;
44234422
ptr = dict_scan_to(ptr, "CREATE");
44244423
ptr = dict_scan_to(ptr, "TABLE");
44254424
ptr = dict_accept(cs, ptr, "TABLE", &success);
4425+
create_table_name = NULL;
44264426

44274427
if (success) {
44284428
ptr = dict_scan_table_name(cs, ptr, &table_to_create, name,
4429-
&success, heap, &create_table_name);
4429+
&success, heap, &create_table_name);
44304430
}
44314431

4432-
if (success) {
4433-
char *bufend;
4434-
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
4435-
create_table_name, strlen(create_table_name),
4436-
trx->mysql_thd, TRUE);
4437-
create_name[bufend-create_name]='\0';
4438-
ptr = orig;
4439-
} else {
4440-
char *bufend;
4441-
ptr = orig;
4442-
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
4443-
name, strlen(name), trx->mysql_thd, TRUE);
4444-
create_name[bufend-create_name]='\0';
4445-
}
4446-
4447-
goto loop;
4432+
ptr = orig;
4433+
const char* n = create_table_name ? create_table_name : name;
4434+
char *bufend = innobase_convert_name(create_name, MAX_TABLE_NAME_LEN,
4435+
n, strlen(n), trx->mysql_thd, TRUE);
4436+
create_name[bufend-create_name] = '\0';
4437+
} else {
4438+
strncpy(create_name, name, sizeof create_name);
4439+
create_name[(sizeof create_name) - 1] = '\0';
44484440
}
44494441

44504442
if (table == NULL) {
44514443
mutex_enter(&dict_foreign_err_mutex);
44524444
dict_foreign_error_report_low(ef, create_name);
4453-
dict_foreign_error_report_low(ef, create_name);
44544445
fprintf(ef, "%s table %s with foreign key constraint"
44554446
" failed. Table %s not found from data dictionary."
44564447
" Error close to %s.\n",
@@ -4485,19 +4476,13 @@ dict_create_foreign_constraints_low(
44854476
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
44864477
&success, heap, &referenced_table_name);
44874478

4488-
if (table_to_alter) {
4489-
char *bufend;
4490-
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
4491-
table_to_alter->name, strlen(table_to_alter->name),
4492-
trx->mysql_thd, TRUE);
4493-
create_name[bufend-create_name]='\0';
4494-
} else {
4495-
char *bufend;
4496-
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
4497-
referenced_table_name, strlen(referenced_table_name),
4498-
trx->mysql_thd, TRUE);
4479+
{
4480+
const char* n = table_to_alter
4481+
? table_to_alter->name : referenced_table_name;
4482+
char* bufend = innobase_convert_name(
4483+
create_name, MAX_TABLE_NAME_LEN, n, strlen(n),
4484+
trx->mysql_thd, TRUE);
44994485
create_name[bufend-create_name]='\0';
4500-
45014486
}
45024487

45034488
if (!success) {

0 commit comments

Comments
 (0)