Commit 46764652 authored by Marko Mäkelä's avatar Marko Mäkelä

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.
parent 0b849a44
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. 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 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 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() ...@@ -1217,6 +1217,8 @@ inline bool dict_index_t::reconstruct_fields()
{ {
DBUG_ASSERT(is_primary()); DBUG_ASSERT(is_primary());
const auto old_n_fields = n_fields;
n_fields += table->instant->n_dropped; n_fields += table->instant->n_dropped;
n_def += table->instant->n_dropped; n_def += table->instant->n_dropped;
...@@ -1241,11 +1243,11 @@ inline bool dict_index_t::reconstruct_fields() ...@@ -1241,11 +1243,11 @@ inline bool dict_index_t::reconstruct_fields()
} else { } else {
DBUG_ASSERT(!c.is_not_null()); DBUG_ASSERT(!c.is_not_null());
const auto old = std::find_if( 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) [c](const dict_field_t& o)
{ return o.col->ind == c.ind(); }); { return o.col->ind == c.ind(); });
if (old >= fields + n_fields if (old >= fields + old_n_fields
|| old->prefix_len || old->prefix_len
|| old->col != &table->cols[c.ind()]) { || old->col != &table->cols[c.ind()]) {
return true; return true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment