summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-02-23 13:31:14 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2022-02-23 13:31:14 +0200
commit46764652dfa7b779a058f2802fc1d4233aece79c (patch)
tree4acb08045604cbaa67fca9665351e3cb6a988f3f /storage
parent0b849a441afaa5f4ce1ad1af877363d7b5c4a1e2 (diff)
downloadmariadb-git-46764652dfa7b779a058f2802fc1d4233aece79c.tar.gz
MDEV-27798 SIGSEGV in dict_index_t::reconstruct_fields()
When recovery is rolling back an incomplete instant DROP COLUMN operation, it may access non-existing fields. Let us avoid invoking std::find_if() outside the valid bounds of the array. This bug was reproduced with the Random Query Generator, using a combination of instant DROP, ADD...FIRST, CHANGE (renaming a column). Unfortunately, we were unable to create an mtr test case for reproducing this, despite spending considerable effort on it.
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/dict/dict0mem.cc8
1 files changed, 5 insertions, 3 deletions
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index 6b1f837634b..0bdb086a5b6 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -2,7 +2,7 @@
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2021, MariaDB Corporation.
+Copyright (c) 2013, 2022, 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
@@ -1217,6 +1217,8 @@ inline bool dict_index_t::reconstruct_fields()
{
DBUG_ASSERT(is_primary());
+ const auto old_n_fields = n_fields;
+
n_fields += table->instant->n_dropped;
n_def += table->instant->n_dropped;
@@ -1241,11 +1243,11 @@ inline bool dict_index_t::reconstruct_fields()
} else {
DBUG_ASSERT(!c.is_not_null());
const auto old = std::find_if(
- fields + n_first, fields + n_fields,
+ fields + n_first, fields + old_n_fields,
[c](const dict_field_t& o)
{ return o.col->ind == c.ind(); });
- if (old >= fields + n_fields
+ if (old >= fields + old_n_fields
|| old->prefix_len
|| old->col != &table->cols[c.ind()]) {
return true;