From 14521992b012c4f108be062b9e672910a5308923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 21 Dec 2021 17:33:26 +0200 Subject: MDEV-27336 Crash on DROP DATABASE due to out-of-bounds result from InnoDB SUBSTR() 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. --- mysql-test/suite/innodb/r/dropdb.result | 10 ++++++++++ mysql-test/suite/innodb/t/dropdb.test | 11 +++++++++++ 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(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); } /*****************************************************************//** -- cgit v1.2.1