summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-12-21 17:33:26 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2021-12-21 17:33:26 +0200
commit14521992b012c4f108be062b9e672910a5308923 (patch)
tree12481048f57a7cef85ab4f9eb12a9f409b7119e9
parent8e5f09a6ed15cda6a413c59b84999d91e8eafb76 (diff)
downloadmariadb-git-st-10.6-marko.tar.gz
MDEV-27336 Crash on DROP DATABASE due to out-of-bounds result from InnoDB SUBSTR()st-10.6-marko
eval_substr(): Do not allow the string buffer of the first argument to be extended. Trim the length of the returned result if it would exceed the end of the buffer.
-rw-r--r--mysql-test/suite/innodb/r/dropdb.result10
-rw-r--r--mysql-test/suite/innodb/t/dropdb.test11
-rw-r--r--storage/innobase/eval/eval0eval.cc15
3 files changed, 34 insertions, 2 deletions
diff --git a/mysql-test/suite/innodb/r/dropdb.result b/mysql-test/suite/innodb/r/dropdb.result
index e612b02b4c8..e1ff475b304 100644
--- a/mysql-test/suite/innodb/r/dropdb.result
+++ b/mysql-test/suite/innodb/r/dropdb.result
@@ -10,3 +10,13 @@ create table `#mysql50#q.q` select 1;
ERROR 42000: Incorrect table name '#mysql50#q.q'
create table `#mysql50#q·q` select 1;
drop database `b`;
+#
+# MDEV-27336 Crash on DROP DATABASE due to out-of-bounds result
+# from InnoDB SUBSTR() function
+#
+USE test;
+CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2(a INT PRIMARY KEY REFERENCES t1(a)) ENGINE=InnoDB;
+CREATE DATABASE somewhat_longer_name_to_cause_trouble;
+DROP DATABASE somewhat_longer_name_to_cause_trouble;
+DROP TABLE t2,t1;
diff --git a/mysql-test/suite/innodb/t/dropdb.test b/mysql-test/suite/innodb/t/dropdb.test
index 5e45e8608c2..f27aede78ec 100644
--- a/mysql-test/suite/innodb/t/dropdb.test
+++ b/mysql-test/suite/innodb/t/dropdb.test
@@ -14,3 +14,14 @@ use `b`;
create table `#mysql50#q.q` select 1;
create table `#mysql50#q·q` select 1;
drop database `b`;
+
+--echo #
+--echo # MDEV-27336 Crash on DROP DATABASE due to out-of-bounds result
+--echo # from InnoDB SUBSTR() function
+--echo #
+USE test;
+CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t2(a INT PRIMARY KEY REFERENCES t1(a)) ENGINE=InnoDB;
+CREATE DATABASE somewhat_longer_name_to_cause_trouble;
+DROP DATABASE somewhat_longer_name_to_cause_trouble;
+DROP TABLE t2,t1;
diff --git a/storage/innobase/eval/eval0eval.cc b/storage/innobase/eval/eval0eval.cc
index 193a5814a78..73ab113cff5 100644
--- a/storage/innobase/eval/eval0eval.cc
+++ b/storage/innobase/eval/eval0eval.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2019, MariaDB Corporation.
+Copyright (c) 2019, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -378,12 +378,23 @@ eval_substr(
str1 = static_cast<byte*>(dfield_get_data(que_node_get_val(arg1)));
+ const ulint str1_len = dfield_get_len(que_node_get_val(arg1));
+
len1 = (ulint) eval_node_get_int_val(arg2);
len2 = (ulint) eval_node_get_int_val(arg3);
dfield = que_node_get_val(func_node);
- dfield_set_data(dfield, str1 + len1, len2);
+ if (len1 > str1_len) {
+ len2 = 0;
+ } else {
+ str1 += len1;
+ if (len2 > str1_len - len1) {
+ len2 = str1_len - len1;
+ }
+ }
+
+ dfield_set_data(dfield, str1, len2);
}
/*****************************************************************//**