diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-02-23 13:31:14 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-02-23 13:31:14 +0200 |
commit | 46764652dfa7b779a058f2802fc1d4233aece79c (patch) | |
tree | 4acb08045604cbaa67fca9665351e3cb6a988f3f | |
parent | 0b849a441afaa5f4ce1ad1af877363d7b5c4a1e2 (diff) | |
download | mariadb-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.
-rw-r--r-- | storage/innobase/dict/dict0mem.cc | 8 |
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; |