diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-12-21 17:33:26 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-12-21 17:33:26 +0200 |
commit | 14521992b012c4f108be062b9e672910a5308923 (patch) | |
tree | 12481048f57a7cef85ab4f9eb12a9f409b7119e9 | |
parent | 8e5f09a6ed15cda6a413c59b84999d91e8eafb76 (diff) | |
download | mariadb-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.result | 10 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/dropdb.test | 11 | ||||
-rw-r--r-- | storage/innobase/eval/eval0eval.cc | 15 |
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); } /*****************************************************************//** |