Bug #119547 InnoDB crash occurred due to the invalid phy_pos in dict_index_t
Submitted: 12 Dec 11:23
Reporter: ksql- team Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S1 (Critical)
Version:mysql-8.0 OS:Any
Assigned to: CPU Architecture:Any

[12 Dec 11:23] ksql- team
Description:
We met a crash as follows:
```
[ERROR] [InnoDB] [FATAL] Field number: 32767 too large, Total fields in Record: 14.

/usr/bin/mysqld(my_server_abort()+0x7e) [0x1037c9e]
/usr/bin/mysqld(my_abort()+0xa) [0x218e47a]
/usr/bin/mysqld(ut_dbg_assertion_failed(char const*, char const*, unsigned long)+0x32f) [0x245c34f]
/usr/bin/mysqld(rec_offs_nth_extern(dict_index_t const*, unsigned long const*, unsigned long)+0x58) [0x2398b98]
/usr/bin/mysqld() [0x23de04d]
/usr/bin/mysqld(row_sel_store_mysql_rec(unsigned char*, row_prebuilt_t*, unsigned char const*, dtuple_t const*, bool, dict_index_t const*, dict_index_t const*, unsigned long const*, bool, lob::undo_vers_t*, mem_block_info_t*&)+0x2f9) [0x23e1849]
/usr/bin/mysqld(row_search_mvcc(unsigned char*, page_cur_mode_t, row_prebuilt_t*, unsigned long, unsigned long)+0x24b9) [0x23e5c19]
/usr/bin/mysqld(ha_innobase::index_read(unsigned char*, unsigned char const*, unsigned int, ha_rkey_function)+0x3f6) [0x22961f6]
/usr/bin/mysqld(ha_innobase::index_first(unsigned char*)+0x32) [0x2260a82]
/usr/bin/mysqld(ha_innobase::rnd_next(unsigned char*)+0x43) [0x22969b3]
/usr/bin/mysqld(handler::ha_rnd_next(unsigned char*)+0x1dc) [0x1146b7c]
/usr/bin/mysqld(TableScanIterator::Read()+0x7b) [0x129c11b]
/usr/bin/mysqld(FilterIterator::Read()+0x14) [0x141f9a4]
/usr/bin/mysqld(filesort(THD*, Filesort*, RowIterator*, unsigned long, unsigned long long, Filesort_info*, Sort_result*, unsigned long long*)+0x74d) [0x113446d]
/usr/bin/mysqld(SortingIterator::DoSort()+0x6e) [0x129e34e]
/usr/bin/mysqld(SortingIterator::Init()+0x30) [0x129e3e0]
/usr/bin/mysqld(LimitOffsetIterator::Init()+0x16) [0x141ff26]
/usr/bin/mysqld(Query_expression::ExecuteIteratorQuery(THD*)+0x25f) [0xf63e5f]
/usr/bin/mysqld(Query_expression::execute(THD*)+0x2c) [0xf6416c]
/usr/bin/mysqld(Sql_cmd_dml::execute(THD*)+0x1b0) [0xee0e50]
/usr/bin/mysqld(mysql_execute_command(THD*, bool)+0xc32) [0xe86fa2]
/usr/bin/mysqld(dispatch_sql_command(THD*, Parser_state*)+0x516) [0xe8b1a6]
/usr/bin/mysqld(dispatch_command(THD*, COM_DATA const*, enum_server_command)+0xdee) [0xe8c74e]
/usr/bin/mysqld(do_command(THD*)+0x207) [0xe8e947]
/usr/bin/mysqld(threadpool_process_request(THD*)+0x9b) [0xfbecbb]
/usr/bin/mysqld() [0xfd21af]
/usr/bin/mysqld() [0x28e24f5]
/lib64/libpthread.so.0(+0x7ea5) [0x7fa722977ea5]
/lib64/libc.so.6(clone+0x6d) [0x7fa7216678dd]
```

How to repeat:
```
CREATE TABLE `t1` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `c1` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

insert into t1 values (1, '1');

alter table t1 add c2 varchar(128) null;

## in debug mode would crash here
alter table t1 change column c1 c3 varchar(128), change column c2 c1 varchar(256);

## restart mysqld

## in release mode would crash here
select * from test.t1;
```

Suggested fix:
```
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index aebe98961a3..5febc9a71a4 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -522,12 +522,14 @@ static void dd_inplace_alter_copy_instant_metadata(
       }
     }

-    /* Get corresponding dd::column in new table */
-    dd::Column *new_dd_column = const_cast<dd::Column *>(
-        dd_find_column(new_dd_tab, old_dd_column->name().c_str()));
+    /* This column might have been renamed */
+    dd::Column *new_dd_column = get_renamed_col(
+        ha_alter_info, old_dd_column, new_dd_tab);
+
     if (new_dd_column == nullptr) {
-      /* This column might have been renamed */
-      new_dd_column = get_renamed_col(ha_alter_info, old_dd_column, new_dd_tab);
+      /* Get corresponding dd::column in new table */
+      new_dd_column = const_cast<dd::Column *>(dd_find_column(
+          new_dd_tab, old_dd_column->name().c_str()));
     }

     if (new_dd_column == nullptr) {
```