[MDEV-26420] Buffer overflow on instant ADD/DROP of generated column Created: 2021-08-19  Updated: 2022-07-26  Resolved: 2022-07-26

Status: Closed
Project: MariaDB Server
Component/s: Data Definition - Alter Table, Storage Engine - InnoDB
Affects Version/s: 10.4, 10.5, 10.6, 10.7
Fix Version/s: 10.4.26, 10.5.17, 10.6.9, 10.7.5, 10.8.4, 10.9.2, 10.10.1

Type: Bug Priority: Blocker
Reporter: Zhiyong Wu Assignee: Marko Mäkelä
Resolution: Fixed Votes: 0
Labels: ASAN, crash, regression-10.4
Environment:

Linux version 5.13.0-1-MANJARO (builduser@LEGION) (gcc (GCC) 11.1.0, GNU ld (GNU Binutils) 2.36.1) #1 SMP PREEMPT Mon Jun 7 06:16:10 UTC 2021 x86_64


Issue Links:
Problem/Incident
is caused by MDEV-15562 Instant DROP COLUMN or changing the o... Closed

 Description   

PoC:

CREATE TABLE v0 ( v1 TIME NOT NULL PRIMARY KEY ) ;
 ALTER TABLE v0 ADD COLUMN v0 INT GENERATED ALWAYS AS ( lpad ( 'x' , NULL = 32 , 'x' ) ) STORED ;
 SHOW LOCAL STATUS WHERE COALESCE ( 27 , 51 - 39 ) = 'x' ;
 DELETE FROM v0 WHERE 44707452.000000 ;
 ALTER TABLE v0 ADD COLUMN v0 INT GENERATED ALWAYS AS ( v1 + v1 ) , DROP COLUMN v0 ;
 SELECT COUNT ( * ) FROM v0 WHERE v1 = -128 AND v1 = 'x' ;

Log and Asan report:

2021-08-16 14:41:38 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2021-08-16 14:41:38 0 [Note] InnoDB: Number of pools: 1
2021-08-16 14:41:38 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions
2021-08-16 14:41:38 0 [Note] mysqld: O_TMPFILE is not supported on /tmp (disabling future attempts)
2021-08-16 14:41:38 0 [Note] InnoDB: Using liburing
2021-08-16 14:41:38 0 [Note] InnoDB: Initializing buffer pool, total size = 134217728, chunk size = 134217728
2021-08-16 14:41:38 0 [Note] InnoDB: Completed initialization of buffer pool
2021-08-16 14:41:38 0 [Note] InnoDB: 128 rollback segments are active.
2021-08-16 14:41:38 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2021-08-16 14:41:38 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2021-08-16 14:41:38 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2021-08-16 14:41:38 0 [Note] InnoDB: 10.7.0 started; log sequence number 42161; transaction id 14
2021-08-16 14:41:38 0 [Note] InnoDB: Loading buffer pool(s) from /home/fuboat/mariadb-tmp/mysql-default-data/ib_buffer_pool
2021-08-16 14:41:38 0 [Note] Plugin 'FEEDBACK' is disabled.
2021-08-16 14:41:38 0 [Note] InnoDB: Buffer pool(s) load completed at 210816 14:41:38
2021-08-16 14:41:38 0 [Note] Server socket created on IP: '0.0.0.0'.
2021-08-16 14:41:38 0 [Note] Server socket created on IP: '::'.
2021-08-16 14:41:38 0 [Note] /usr/local/mysql/bin//mysqld: ready for connections.
Version: '10.7.0-MariaDB'  socket: '/tmp/0.socket'  port: 3306  Source distribution
2021-08-16 14:41:39 0 [Note] /usr/local/mysql/bin//mysqld (initiated by: root[root] @ localhost []): Normal shutdown
2021-08-16 14:41:39 0 [Note] InnoDB: FTS optimize thread exiting.
2021-08-16 14:41:39 0 [Note] InnoDB: Starting shutdown...
2021-08-16 14:41:39 0 [Note] InnoDB: Dumping buffer pool(s) to /home/fuboat/mariadb-tmp/mysql-default-data/ib_buffer_pool
2021-08-16 14:41:39 0 [Note] InnoDB: Buffer pool(s) dump completed at 210816 14:41:39
2021-08-16 14:41:39 0 [Note] InnoDB: Removed temporary tablespace data file: "./ibtmp1"
2021-08-16 14:41:39 0 [Note] InnoDB: Shutdown completed; log sequence number 42173; transaction id 15
2021-08-16 14:41:39 0 [Note] /usr/local/mysql/bin//mysqld: Shutdown complete
 
2021-08-16 14:49:19 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2021-08-16 14:49:19 0 [Note] InnoDB: Number of pools: 1
2021-08-16 14:49:19 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions
2021-08-16 14:49:19 0 [Note] mysqld: O_TMPFILE is not supported on /tmp (disabling future attempts)
2021-08-16 14:49:19 0 [Note] InnoDB: Using liburing
2021-08-16 14:49:19 0 [Note] InnoDB: Initializing buffer pool, total size = 134217728, chunk size = 134217728
2021-08-16 14:49:19 0 [Note] InnoDB: Completed initialization of buffer pool
2021-08-16 14:49:26 0 [Note] InnoDB: 128 rollback segments are active.
2021-08-16 14:49:26 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2021-08-16 14:49:26 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2021-08-16 14:49:26 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2021-08-16 14:49:26 0 [Note] InnoDB: 10.7.0 started; log sequence number 42173; transaction id 14
2021-08-16 14:49:26 0 [Note] InnoDB: Loading buffer pool(s) from /home/fuboat/mariadb-tmp/19/ib_buffer_pool
2021-08-16 14:49:26 0 [Note] Plugin 'FEEDBACK' is disabled.
2021-08-16 14:49:27 0 [Note] Server socket created on IP: '0.0.0.0'.
2021-08-16 14:49:27 0 [Note] Server socket created on IP: '::'.
2021-08-16 14:49:28 0 [Note] InnoDB: Buffer pool(s) load completed at 210816 14:49:28
2021-08-16 14:49:28 0 [Note] /usr/local/mysql/bin//mysqld: ready for connections.
Version: '10.7.0-MariaDB'  socket: '/tmp/19.socket'  port: 10019  Source distribution
=================================================================
==2119277==ERROR: AddressSanitizer: use-after-poison on address 0x6190000d6d60 at pc 0x55a3184baacf bp 0x7f47ed829920 sp 0x7f47ed829910
WRITE of size 64 at 0x6190000d6d60 thread T14
    #0 0x55a3184baace in prepare_inplace_add_virtual /experiment/mariadb-server/sql/field.h:1395
    #1 0x55a3184cc1db in prepare_inplace_alter_table_dict /experiment/mariadb-server/storage/innobase/handler/handler0alter.cc:6206
    #2 0x55a3184d9f06 in ha_innobase::prepare_inplace_alter_table(TABLE*, Alter_inplace_info*) /experiment/mariadb-server/storage/innobase/handler/handler0alter.cc:8270
    #3 0x55a3176a67d2 in mysql_inplace_alter_table /experiment/mariadb-server/sql/sql_table.cc:7326
    #4 0x55a3176a67d2 in mysql_alter_table(THD*, st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, HA_CREATE_INFO*, TABLE_LIST*, Alter_info*, unsigned int, st_order*, bool, bool) /experiment/mariadb-server/sql/sql_table.cc:10205
    #5 0x55a3177fcf99 in Sql_cmd_alter_table::execute(THD*) /experiment/mariadb-server/sql/sql_alter.cc:550
    #6 0x55a31741717f in mysql_execute_command(THD*, bool) /experiment/mariadb-server/sql/sql_parse.cc:5997
    #7 0x55a3174245a0 in mysql_parse(THD*, char*, unsigned int, Parser_state*) /experiment/mariadb-server/sql/sql_parse.cc:8030
    #8 0x55a31742a60b in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /experiment/mariadb-server/sql/sql_parse.cc:1896
    #9 0x55a31742f73c in do_command(THD*, bool) /experiment/mariadb-server/sql/sql_parse.cc:1404
    #10 0x55a3177eae56 in do_handle_one_connection(CONNECT*, bool) /experiment/mariadb-server/sql/sql_connect.cc:1418
    #11 0x55a3177eb33c in handle_one_connection /experiment/mariadb-server/sql/sql_connect.cc:1312
    #12 0x55a31827bc2b in pfs_spawn_thread /experiment/mariadb-server/storage/perfschema/pfs.cc:2201
    #13 0x7f4812443258 in start_thread (/usr/lib/libpthread.so.0+0x9258)
    #14 0x7f4811fee5e2 in __GI___clone (/usr/lib/libc.so.6+0xfe5e2)
 
0x6190000d6d60 is located 480 bytes inside of 1152-byte region [0x6190000d6b80,0x6190000d7000)
allocated by thread T14 here:
    #0 0x7f4812ad5279 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x55a3185c76c0 in ut_allocator<unsigned char, true>::allocate(unsigned long, unsigned char const*, unsigned int, bool, bool) /experiment/mariadb-server/storage/innobase/include/ut0new.h:375
    #2 0x55a3185c76c0 in mem_heap_create_block_func(mem_block_info_t*, unsigned long, unsigned long) /experiment/mariadb-server/storage/innobase/mem/mem0mem.cc:277
    #3 0x55a3184da801 in mem_heap_create_func /experiment/mariadb-server/storage/innobase/include/mem0mem.ic:377
    #4 0x55a3184da801 in ha_innobase::prepare_inplace_alter_table(TABLE*, Alter_inplace_info*) /experiment/mariadb-server/storage/innobase/handler/handler0alter.cc:7816
    #5 0x55a3176a67d2 in mysql_inplace_alter_table /experiment/mariadb-server/sql/sql_table.cc:7326
    #6 0x55a3176a67d2 in mysql_alter_table(THD*, st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, HA_CREATE_INFO*, TABLE_LIST*, Alter_info*, unsigned int, st_order*, bool, bool) /experiment/mariadb-server/sql/sql_table.cc:10205
    #7 0x55a3177fcf99 in Sql_cmd_alter_table::execute(THD*) /experiment/mariadb-server/sql/sql_alter.cc:550
    #8 0x55a31741717f in mysql_execute_command(THD*, bool) /experiment/mariadb-server/sql/sql_parse.cc:5997
    #9 0x55a3174245a0 in mysql_parse(THD*, char*, unsigned int, Parser_state*) /experiment/mariadb-server/sql/sql_parse.cc:8030
    #10 0x55a31742a60b in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /experiment/mariadb-server/sql/sql_parse.cc:1896
    #11 0x55a31742f73c in do_command(THD*, bool) /experiment/mariadb-server/sql/sql_parse.cc:1404
    #12 0x55a3177eae56 in do_handle_one_connection(CONNECT*, bool) /experiment/mariadb-server/sql/sql_connect.cc:1418
    #13 0x55a3177eb33c in handle_one_connection /experiment/mariadb-server/sql/sql_connect.cc:1312
    #14 0x55a31827bc2b in pfs_spawn_thread /experiment/mariadb-server/storage/perfschema/pfs.cc:2201
    #15 0x7f4812443258 in start_thread (/usr/lib/libpthread.so.0+0x9258)
 
Thread T14 created by T0 here:
    #0 0x7f4812a76fa7 in __interceptor_pthread_create /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:216
    #1 0x55a31827bea9 in my_thread_create /experiment/mariadb-server/storage/perfschema/my_thread.h:48
    #2 0x55a31827bea9 in pfs_spawn_thread_v1 /experiment/mariadb-server/storage/perfschema/pfs.cc:2252
    #3 0x55a3170ecb3c in inline_mysql_thread_create /experiment/mariadb-server/include/mysql/psi/mysql_thread.h:1139
    #4 0x55a3170ecb3c in create_thread_to_handle_connection(CONNECT*) /experiment/mariadb-server/sql/mysqld.cc:5934
    #5 0x55a3170f87b6 in handle_accepted_socket(st_mysql_socket, st_mysql_socket) /experiment/mariadb-server/sql/mysqld.cc:6055
    #6 0x55a3170f936f in handle_connections_sockets() /experiment/mariadb-server/sql/mysqld.cc:6179
    #7 0x55a3170fca52 in mysqld_main(int, char**) /experiment/mariadb-server/sql/mysqld.cc:5829
    #8 0x7f4811f17b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
 
SUMMARY: AddressSanitizer: use-after-poison /experiment/mariadb-server/sql/field.h:1395 in prepare_inplace_add_virtual
Shadow bytes around the buggy address:
  0x0c3280012d50: f7 f7 fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3280012d60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3280012d70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280012d80: f7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280012d90: 00 00 00 00 00 00 f7 00 00 00 00 00 00 00 00 00
=>0x0c3280012da0: 00 00 00 00 00 00 00 00 00 00 00 f7[f7]f7 f7 f7
  0x0c3280012db0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280012dc0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280012dd0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280012de0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280012df0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==2119277==ABORTING
GNU gdb (GDB) 10.2
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
 
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/local/mysql/bin//mysqld...
(gdb) (gdb) (gdb) quit



 Comments   
Comment by Alice Sherepa [ 2021-08-26 ]

Thank you! Reproducible on 10.4-10.6:

--source include/have_innodb.inc
 
CREATE TABLE t1 (i int AS ('x') stored, j int) engine=innodb;
ALTER TABLE t1 ADD COLUMN i INT GENERATED ALWAYS AS ('a'), DROP COLUMN i ;

10.4 dc6bc85cd29586631d

Version: '10.4.22-MariaDB-debug-log'  
=================================================================
==620710==ERROR: AddressSanitizer: use-after-poison on address 0x6190000f3998 at pc 0x5623146114a1 bp 0x7fc65afb1b80 sp 0x7fc65afb1b70
WRITE of size 56 at 0x6190000f3998 thread T27
    #0 0x5623146114a0 in prepare_inplace_add_virtual /10.4/src/storage/innobase/handler/handler0alter.cc:5059
    #1 0x5623146199c0 in prepare_inplace_alter_table_dict /10.4/src/storage/innobase/handler/handler0alter.cc:6284
    #2 0x56231462eafc in ha_innobase::prepare_inplace_alter_table(TABLE*, Alter_inplace_info*) /10.4/src/storage/innobase/handler/handler0alter.cc:8356
    #3 0x562313fc4575 in handler::ha_prepare_inplace_alter_table(TABLE*, Alter_inplace_info*) /10.4/src/sql/handler.cc:4622
    #4 0x562313a01860 in mysql_inplace_alter_table /10.4/src/sql/sql_table.cc:7785
    #5 0x562313a136d2 in mysql_alter_table(THD*, st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, HA_CREATE_INFO*, TABLE_LIST*, Alter_info*, unsigned int, st_order*, bool) /10.4/src/sql/sql_table.cc:10251
    #6 0x562313b97587 in Sql_cmd_alter_table::execute(THD*) /10.4/src/sql/sql_alter.cc:520
    #7 0x5623137a6789 in mysql_execute_command(THD*) /10.4/src/sql/sql_parse.cc:6192
    #8 0x5623137b22d6 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /10.4/src/sql/sql_parse.cc:7995
    #9 0x562313788a52 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /10.4/src/sql/sql_parse.cc:1857
    #10 0x5623137854cf in do_command(THD*) /10.4/src/sql/sql_parse.cc:1373
    #11 0x562313b7eb38 in do_handle_one_connection(CONNECT*) /10.4/src/sql/sql_connect.cc:1420
    #12 0x562313b7e291 in handle_one_connection /10.4/src/sql/sql_connect.cc:1316
    #13 0x56231525074c in pfs_spawn_thread /10.4/src/storage/perfschema/pfs.cc:1869
    #14 0x7fc671cb4608 in start_thread /build/glibc-eX1tMB/glibc-2.31/nptl/pthread_create.c:477
    #15 0x7fc671889292 in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x122292)
 
0x6190000f3998 is located 536 bytes inside of 1152-byte region [0x6190000f3780,0x6190000f3c00)
allocated by thread T27 here:
    #0 0x7fc6722c8bc8 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #1 0x562314774ce9 in mem_heap_create_block_func(mem_block_info_t*, unsigned long, char const*, unsigned int, unsigned long) /10.4/src/storage/innobase/mem/mem0mem.cc:277
    #2 0x5623145ef526 in mem_heap_create_func /10.4/src/storage/innobase/include/mem0mem.ic:375
    #3 0x562314629f56 in ha_innobase::prepare_inplace_alter_table(TABLE*, Alter_inplace_info*) /10.4/src/storage/innobase/handler/handler0alter.cc:7913
    #4 0x562313fc4575 in handler::ha_prepare_inplace_alter_table(TABLE*, Alter_inplace_info*) /10.4/src/sql/handler.cc:4622
    #5 0x562313a01860 in mysql_inplace_alter_table /10.4/src/sql/sql_table.cc:7785
    #6 0x562313a136d2 in mysql_alter_table(THD*, st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, HA_CREATE_INFO*, TABLE_LIST*, Alter_info*, unsigned int, st_order*, bool) /10.4/src/sql/sql_table.cc:10251
    #7 0x562313b97587 in Sql_cmd_alter_table::execute(THD*) /10.4/src/sql/sql_alter.cc:520
    #8 0x5623137a6789 in mysql_execute_command(THD*) /10.4/src/sql/sql_parse.cc:6192
    #9 0x5623137b22d6 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /10.4/src/sql/sql_parse.cc:7995
    #10 0x562313788a52 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /10.4/src/sql/sql_parse.cc:1857
    #11 0x5623137854cf in do_command(THD*) /10.4/src/sql/sql_parse.cc:1373
    #12 0x562313b7eb38 in do_handle_one_connection(CONNECT*) /10.4/src/sql/sql_connect.cc:1420
    #13 0x562313b7e291 in handle_one_connection /10.4/src/sql/sql_connect.cc:1316
    #14 0x56231525074c in pfs_spawn_thread /10.4/src/storage/perfschema/pfs.cc:1869
    #15 0x7fc671cb4608 in start_thread /build/glibc-eX1tMB/glibc-2.31/nptl/pthread_create.c:477
 
Thread T27 created by T0 here:
    #0 0x7fc6721f5805 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x3a805)
    #1 0x562315250b3d in spawn_thread_v1 /10.4/src/storage/perfschema/pfs.cc:1919
    #2 0x56231348cb8f in inline_mysql_thread_create /10.4/src/include/mysql/psi/mysql_thread.h:1275
    #3 0x5623134a4a94 in create_thread_to_handle_connection(CONNECT*) /10.4/src/sql/mysqld.cc:6241
    #4 0x5623134a522f in create_new_thread(CONNECT*) /10.4/src/sql/mysqld.cc:6311
    #5 0x5623134a5715 in handle_accepted_socket(st_mysql_socket, st_mysql_socket) /10.4/src/sql/mysqld.cc:6409
    #6 0x5623134a65e2 in handle_connections_sockets() /10.4/src/sql/mysqld.cc:6567
    #7 0x5623134a4188 in mysqld_main(int, char**) /10.4/src/sql/mysqld.cc:5899
    #8 0x56231348addc in main /10.4/src/sql/main.cc:25
    #9 0x7fc67178e0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
 
SUMMARY: AddressSanitizer: use-after-poison /10.4/src/storage/innobase/handler/handler0alter.cc:5059 in prepare_inplace_add_virtual
Shadow bytes around the buggy address:
  0x0c32800166e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c32800166f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280016700: f7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280016710: 00 00 00 00 00 00 00 00 00 f7 00 00 00 00 00 00
  0x0c3280016720: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c3280016730: 00 00 f7[f7]f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280016740: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280016750: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280016760: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280016770: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c3280016780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==620710==ABORTING
----------SERVER LOG END-------------

Comment by Marko Mäkelä [ 2022-07-26 ]

For alice’s test case, the memory had been poisoned here:

10.4 8911823f65a6557ce66ea5f8aecd55b115a85606

#3  0x0000562765feda32 in mem_heap_create_func (size=<optimized out>, 
    size@entry=1024, 
    file_name=file_name@entry=0x562766ef84c0 "/mariadb/10.4/storage/innobase/handler/handler0alter.cc", line=line@entry=7964, type=type@entry=0)
    at /mariadb/10.4/storage/innobase/include/mem0mem.inl:375
#4  0x000056276600a835 in ha_innobase::prepare_inplace_alter_table (
    this=0x61d000247ca8, altered_table=<optimized out>, 
    ha_alter_info=<optimized out>)
    at /mariadb/10.4/storage/innobase/handler/handler0alter.cc:7964
#5  0x000056276589c741 in handler::ha_prepare_inplace_alter_table (
    this=0x61d000247ca8, altered_table=altered_table@entry=0x7f6ba9085510, 
    ha_alter_info=ha_alter_info@entry=0x7f6ba90837a0)
    at /mariadb/10.4/sql/handler.cc:4637

So, it looks like an out-of-bounds access.

Comment by Marko Mäkelä [ 2022-07-26 ]

The out-of-bounds access occurs here:

		new (&ctx->add_vcol[j]) dict_v_col_t();

The j=0 is out-of-bounds because ctx->num_to_add_vcol=0 (instead of the correct value 1). The math goes wrong in prepare_inplace_add_virtual():

static
bool
prepare_inplace_add_virtual(
	Alter_inplace_info*	ha_alter_info,
	const TABLE*		altered_table,
	const TABLE*		table)
{
	ha_innobase_inplace_ctx*	ctx;
	ulint				i = 0;
	ulint				j = 0;
 
	ctx = static_cast<ha_innobase_inplace_ctx*>
		(ha_alter_info->handler_ctx);
 
	ctx->num_to_add_vcol = altered_table->s->virtual_fields
		+ ctx->num_to_drop_vcol - table->s->virtual_fields;

Here, we have both altered_table->s->virtual_fields and table->s->virtual_fields equal to 1. InnoDB really cares about generated columns that are not stored in the clustered index, so it looks like we must iterate through all columns to see for which ones Field::stored_in_db() holds.

The bug does not affect 10.3. For newer servers a work-around (to disable MDEV-15562) is innodb_instant_alter_column_allowed=add_last.

Comment by Marko Mäkelä [ 2022-07-26 ]

The simple fix is to over-estimate the size of the buffer as altered_table->s->virtual_fields + ctx->num_to_drop_vcol (not subtract any pre-existing generated columns), and to assign j at the end of the function to ctx->num_to_add_vcol.

Generated at Thu Feb 08 09:45:10 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.