summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2021-03-25 11:33:11 +0300
committerAleksey Midenkov <midenok@gmail.com>2021-04-23 14:09:43 +0300
commit4649ba7493897b3a140ab354b88decd3f0540491 (patch)
tree0f0a6d22df366270f6b2b228d9f87110a995eef0
parent018d7440fdcf1baf3d0ce235092433d4ea46c485 (diff)
downloadmariadb-git-4649ba7493897b3a140ab354b88decd3f0540491.tar.gz
MDEV-23455 Hangs + Sig11 in unknown location(s) due to single complex FK query
Buffer overflow in ib_push_warning() fixed by using vsnprintf(). InnoDB parser was obsoleted by MDEV-16417. Thanks to Nikita Malyavin for review and suggestion.
-rw-r--r--mysql-test/suite/innodb/r/foreign_key.result11
-rw-r--r--mysql-test/suite/innodb/t/foreign_key.test39
-rw-r--r--storage/innobase/handler/ha_innodb.cc7
3 files changed, 54 insertions, 3 deletions
diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result
index ca27595ffa0..efaa9028eae 100644
--- a/mysql-test/suite/innodb/r/foreign_key.result
+++ b/mysql-test/suite/innodb/r/foreign_key.result
@@ -801,4 +801,15 @@ ERROR 23000: Duplicate entry '10' for key 'ind9'
SET FOREIGN_KEY_CHECKS= 0;
ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (pk);
DROP TABLE t1;
+SET FOREIGN_KEY_CHECKS= 1;
+#
+# MDEV-23455 Hangs + Sig11 in unknown location(s) due to single complex FK query
+#
+Parsing foreign keys 1...
+ERROR HY000: Can't create table `test`.`t0` (errno: 150 "Foreign key constraint is incorrectly formed")
+Parsing foreign keys 2...
+ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+Parsing foreign keys 3...
+ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+Parsing foreign keys 4...
# End of 10.2 tests
diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test
index 7756d48046f..08f2c529659 100644
--- a/mysql-test/suite/innodb/t/foreign_key.test
+++ b/mysql-test/suite/innodb/t/foreign_key.test
@@ -782,6 +782,45 @@ ALTER TABLE t1 ADD UNIQUE INDEX ind9 (b), LOCK=SHARED;
SET FOREIGN_KEY_CHECKS= 0;
ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (pk);
DROP TABLE t1;
+SET FOREIGN_KEY_CHECKS= 1;
+
+--echo #
+--echo # MDEV-23455 Hangs + Sig11 in unknown location(s) due to single complex FK query
+--echo #
+let $constr_prefix= aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
+let $fk_ref= xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
+let $fk_field= yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
+let $constr_count= 200; # each 100 constrs is 1 sec of test execution
+let $i= 0;
+
+while ($i < $constr_count)
+{
+ let $p= $constr_prefix$i;
+ let $constr= CONSTRAINT $p FOREIGN KEY ($fk_field) REFERENCES t1($fk_ref) ON UPDATE SET NULL;
+ if ($i)
+ {
+ let $constrs= $constrs, $constr;
+ }
+ if (!$i)
+ {
+ let $constrs= $constr;
+ }
+ inc $i;
+}
+--disable_query_log
+--echo Parsing foreign keys 1...
+--error ER_CANT_CREATE_TABLE
+eval create table t0($fk_field int, $constrs) engine innodb;
+--echo Parsing foreign keys 2...
+--error ER_CANT_CREATE_TABLE
+eval create table t1($fk_field int, $constrs) engine innodb;
+--echo Parsing foreign keys 3...
+--error ER_CANT_CREATE_TABLE
+eval create table t1($fk_ref int, $fk_field int, $constrs) engine innodb;
+--echo Parsing foreign keys 4...
+eval create table t1($fk_ref int primary key, $fk_field int, $constrs) engine innodb;
+drop table t1;
+--enable_query_log
--echo # End of 10.2 tests
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c95e6646968..a725569fa6e 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -22600,8 +22600,8 @@ ib_push_warning(
va_start(args, format);
buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
- vsprintf(buf,format, args);
-
+ buf[MAX_BUF_SIZE - 1] = 0;
+ vsnprintf(buf, MAX_BUF_SIZE - 1, format, args);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
convert_error_code_to_mysql((dberr_t)error, 0, thd),
buf);
@@ -22632,7 +22632,8 @@ ib_push_warning(
if (thd) {
va_start(args, format);
buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
- vsprintf(buf,format, args);
+ buf[MAX_BUF_SIZE - 1] = 0;
+ vsnprintf(buf, MAX_BUF_SIZE - 1, format, args);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
convert_error_code_to_mysql((dberr_t)error, 0, thd),