[MDEV-30926] Segfault after MyISAM repair of vcol-indexed table Created: 2023-03-25  Updated: 2024-01-31

Status: In Review
Project: MariaDB Server
Component/s: Storage Engine - MyISAM, Virtual Columns
Affects Version/s: 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 10.10, 10.11, 11.0
Fix Version/s: 10.4, 10.5, 10.6, 10.11, 11.0

Type: Bug Priority: Major
Reporter: Roel Van de Paar Assignee: Sergei Golubchik
Resolution: Unresolved Votes: 0
Labels: ASAN, memory_corruption

Issue Links:
Duplicate
is duplicated by MDEV-31782 ASAN heap-use-after-free in MyISAM bu... Stalled
is duplicated by MDEV-32089 Assertion `!strcmp(&path[strlen(path)... Stalled
Relates
relates to MDEV-23294 Segfault or assertion upon MyISAM repair Closed

 Description   

SIGSEGV in l_find or lf_hash_destroy on UPDATE or INSERT depending on version, ASAN: heap-use-after-free in Field::set_notnull

SET sql_mode='';
CREATE TABLE t2 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM;
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
XA START 'a';
UPDATE t1,non_existing_1 SET 1=1;
DELETE FROM mysql.db;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 (SELECT 1);
INSERT INTO non_existing_2 VALUES (1);  # Crashing on 2nd execution on 10.6 (opt), 10.8 (dbg+opt), 10.10 (opt)
UPDATE t2 SET a=1;
SELECT SLEEP (1);  # Shows server gone

Leads to:

11.0.1 f2dc4d4c10ac36a73b5c1eb765352d3aee808d66 (Optimized)

Core was generated by `/test/MD180223-mariadb-11.0.1-linux-x86_64-opt/bin/mariadbd --no-defaults --cor'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  l_find (head=0x14b8e8057df8, head@entry=0x55efd1933010, cs=cs@entry=0x0, 
    hashnr=hashnr@entry=0, 
    key=key@entry=0x7ffdaced3a68 "\310\070\265\321\357U", 
    keylen=keylen@entry=0, cursor=cursor@entry=0x7ffdaced38e0, 
    pins=<optimized out>, callback=<optimized out>)
    at /test/11.0_opt/mysys/lf_hash.cc:114
[Current thread is 1 (Thread 0x14b9dfd26480 (LWP 843505))]
(gdb) bt
#0  l_find (head=0x14b8e8057df8, head@entry=0x55efd1933010, cs=cs@entry=0x0, hashnr=hashnr@entry=0, key=key@entry=0x7ffdaced3a68 "\310\070\265\321\357U", keylen=keylen@entry=0, cursor=cursor@entry=0x7ffdaced38e0, pins=<optimized out>, callback=<optimized out>) at /test/11.0_opt/mysys/lf_hash.cc:114
#1  0x000055efceb986ef in lf_hash_iterate (hash=0x55efcf666560 <tdc_hash>, pins=0x55efd1a0b1f0, action=0x55efce666d70 <tc_purge_callback(TDC_element*, Share_free_tables::List*)>, argument=0x7ffdaced3a68) at /test/11.0_opt/mysys/lf_hash.cc:531
#2  0x000055efce668496 in tdc_iterate (thd=thd@entry=0x0, action=action@entry=0x55efce666d70 <tc_purge_callback(TDC_element*, Share_free_tables::List*)>, argument=argument@entry=0x7ffdaced3a68, no_dups=no_dups@entry=false) at /test/11.0_opt/sql/table_cache.cc:1186
#3  0x000055efce6686ca in tc_purge () at /test/11.0_opt/sql/table_cache.cc:315
#4  0x000055efce427f52 in purge_tables () at /test/11.0_opt/sql/sql_base.cc:326
#5  0x000055efce667481 in tdc_start_shutdown () at /test/11.0_opt/sql/table_cache.cc:639
#6  0x000055efce38d953 in clean_up (print_message=true) at /test/11.0_opt/sql/mysqld.cc:1994
#7  clean_up (print_message=<optimized out>) at /test/11.0_opt/sql/mysqld.cc:1961
#8  0x000055efce3960a7 in mysqld_main (argc=<optimized out>, argv=<optimized out>) at /test/11.0_opt/sql/mysqld.cc:6047
#9  0x000014b9dfffdd90 in __libc_start_call_main (main=main@entry=0x55efce34d540 <main(int, char**)>, argc=argc@entry=10, argv=argv@entry=0x7ffdaced3f18) at ../sysdeps/nptl/libc_start_call_main.h:58
#10 0x000014b9dfffde40 in __libc_start_main_impl (main=0x55efce34d540 <main(int, char**)>, argc=10, argv=0x7ffdaced3f18, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffdaced3f08) at ../csu/libc-start.c:392
#11 0x000055efce38b6e5 in _start ()

Issue does not appear sporadic. However, interestingly, versions 10.6 (opt), 10.8 (dbg+opt) and 10.10 (opt) do not immediately crash on the testcase above. However, when repeating the testcase in the same client session, we see a different crash location (the final INSERT) with a different stack:

10.6.13 6aec87544c675751141100d6efe3a2d943cb528f (Optimized)

Core was generated by `/test/MD110223-mariadb-10.6.13-linux-x86_64-opt/bin/mariadbd --no-defaults --co'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  l_find (head=0x150e2c058898, head@entry=0x55b4de464b88, 
    cs=0x55b4dd4c5c00 <my_charset_bin>, hashnr=<optimized out>, 
    key=key@entry=0x150e2c010c49 "test", keylen=keylen@entry=20, 
    cursor=cursor@entry=0x150ec40a5b30, pins=<optimized out>, 
    callback=<optimized out>) at /test/10.6_opt/mysys/lf_hash.cc:114
[Current thread is 1 (Thread 0x150ec40a8640 (LWP 867199))]
(gdb) bt
#0  l_find (head=0x150e2c058898, head@entry=0x55b4de464b88, cs=0x55b4dd4c5c00 <my_charset_bin>, hashnr=<optimized out>, key=key@entry=0x150e2c010c49 "test", keylen=keylen@entry=20, cursor=cursor@entry=0x150ec40a5b30, pins=<optimized out>, callback=<optimized out>) at /test/10.6_opt/mysys/lf_hash.cc:114
#1  0x000055b4dcbba045 in l_search (pins=0x55b4de45d2e0, keylen=20, key=0x150e2c010c49 "test", hashnr=<optimized out>, cs=<optimized out>, head=0x55b4de464b88) at /test/10.6_opt/mysys/lf_hash.cc:298
#2  lf_hash_search_using_hash_value (hash=0x55b4dd56b880 <tdc_hash>, pins=0x55b4de45d2e0, hashnr=<optimized out>, key=0x150e2c010c49, keylen=20) at /test/10.6_opt/mysys/lf_hash.cc:501
#3  0x000055b4dc66a110 in tdc_acquire_share (thd=thd@entry=0x150e2c000c68, tl=tl@entry=0x150e2c0107a0, flags=flags@entry=3, out_table=out_table@entry=0x150ec40a5c50) at /test/10.6_opt/sql/table_cache.cc:813
#4  0x000055b4dc4531ad in open_table (thd=0x150e2c000c68, table_list=0x150e2c0107a0, ot_ctx=0x150ec40a62d0) at /test/10.6_opt/sql/sql_base.cc:1886
#5  0x000055b4dc456b6a in open_and_process_table (ot_ctx=0x150ec40a62d0, has_prelocking_list=false, prelocking_strategy=0x150ec40a6490, flags=0, counter=0x150ec40a636c, tables=0x150e2c0107a0, thd=0x150e2c000c68) at /test/10.6_opt/sql/sql_base.cc:3847
#6  open_tables (thd=thd@entry=0x150e2c000c68, options=@0x150e2c006168: {m_options = DDL_options_st::OPT_NONE}, start=start@entry=0x150ec40a6358, counter=counter@entry=0x150ec40a636c, flags=flags@entry=0, prelocking_strategy=0x150ec40a6490) at /test/10.6_opt/sql/sql_base.cc:4330
#7  0x000055b4dc45733a in open_and_lock_tables (thd=thd@entry=0x150e2c000c68, options=<optimized out>, tables=<optimized out>, tables@entry=0x150e2c0107a0, derived=derived@entry=true, flags=flags@entry=0, prelocking_strategy=<optimized out>) at /test/10.6_opt/sql/sql_base.cc:5303
#8  0x000055b4dc4882bc in open_and_lock_tables (flags=<optimized out>, derived=<optimized out>, tables=<optimized out>, thd=<optimized out>) at /test/10.6_opt/sql/sql_base.h:509
#9  open_and_lock_for_insert_delayed (table_list=<optimized out>, thd=<optimized out>) at /test/10.6_opt/sql/sql_insert.cc:626
#10 mysql_insert (thd=thd@entry=0x150e2c000c68, table_list=0x150e2c0107a0, fields=@0x150e2c005b20: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x55b4dd543890 <end_of_list>, last = 0x150e2c005b20, elements = 0}, <No data fields>}, values_list=@0x150e2c005b68: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x150e2c011408, last = 0x150e2c011408, elements = 1}, <No data fields>}, update_fields=@0x150e2c005b50: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x55b4dd543890 <end_of_list>, last = 0x150e2c005b50, elements = 0}, <No data fields>}, update_values=@0x150e2c005b38: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x55b4dd543890 <end_of_list>, last = 0x150e2c005b38, elements = 0}, <No data fields>}, duplic=<optimized out>, ignore=<optimized out>, result=<optimized out>) at /test/10.6_opt/sql/sql_insert.cc:752
#11 0x000055b4dc4be861 in mysql_execute_command (thd=0x150e2c000c68, is_called_from_prepared_stmt=<optimized out>) at /test/10.6_opt/sql/sql_parse.cc:4570
#12 0x000055b4dc4c2f34 in mysql_parse (rawbuf=<optimized out>, length=<optimized out>, parser_state=<optimized out>, thd=0x150e2c000c68) at /test/10.6_opt/sql/sql_parse.cc:8021
#13 mysql_parse (thd=0x150e2c000c68, rawbuf=<optimized out>, length=<optimized out>, parser_state=<optimized out>) at /test/10.6_opt/sql/sql_parse.cc:7943
#14 0x000055b4dc4c5512 in dispatch_command (command=COM_QUERY, thd=0x150e2c000c68, packet=<optimized out>, packet_length=<optimized out>, blocking=<optimized out>) at /test/10.6_opt/sql/sql_parse.cc:1993
#15 0x000055b4dc4c6cb0 in do_command (thd=0x150e2c000c68, blocking=blocking@entry=true) at /test/10.6_opt/sql/sql_parse.cc:1409
#16 0x000055b4dc5cabf7 in do_handle_one_connection (connect=<optimized out>, connect@entry=0x55b4de5142c8, put_in_cache=put_in_cache@entry=true) at /test/10.6_opt/sql/sql_connect.cc:1416
#17 0x000055b4dc5caecd in handle_one_connection (arg=0x55b4de5142c8) at /test/10.6_opt/sql/sql_connect.cc:1318
#18 0x0000150ef139eb43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#19 0x0000150ef1430a00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

11.0.1 4d09050ca77a7efac4565d46e4bcd85a5f210c53 (Optimized, UBASAN)

==852581==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000010a18 at pc 0x5602419cbf07 bp 0x151232cc7930 sp 0x151232cc7920
READ of size 1 at 0x606000010a18 thread T20
    #0 0x5602419cbf06 in Field::set_notnull(long long) /test/11.0_opt_san/sql/field.h:1405
    #1 0x5602419cbf06 in save_int_value_in_field /test/11.0_opt_san/sql/item.cc:6927
    #2 0x5602419cbf06 in Item_int::save_in_field(Field*, bool) /test/11.0_opt_san/sql/item.cc:6934
    #3 0x560240c38678 in TABLE::update_virtual_fields(handler*, enum_vcol_update_mode) /test/11.0_opt_san/sql/table.cc:8892
    #4 0x56024193a95a in handler::ha_rnd_next(unsigned char*) /test/11.0_opt_san/sql/handler.cc:3447
    #5 0x56023fde33b3 in rr_sequential(READ_RECORD*) /test/11.0_opt_san/sql/records.cc:519
    #6 0x560240b93a29 in READ_RECORD::read_record() /test/11.0_opt_san/sql/records.h:81
    #7 0x560240b93a29 in mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, bool, unsigned long long*, unsigned long long*) /test/11.0_opt_san/sql/sql_update.cc:1018
    #8 0x560240496b54 in mysql_execute_command(THD*, bool) /test/11.0_opt_san/sql/sql_parse.cc:4410
    #9 0x5602404ae542 in mysql_parse(THD*, char*, unsigned int, Parser_state*) /test/11.0_opt_san/sql/sql_parse.cc:8000
    #10 0x5602404bbfa5 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /test/11.0_opt_san/sql/sql_parse.cc:1894
    #11 0x5602404c5700 in do_command(THD*, bool) /test/11.0_opt_san/sql/sql_parse.cc:1407
    #12 0x560240da603c in do_handle_one_connection(CONNECT*, bool) /test/11.0_opt_san/sql/sql_connect.cc:1416
    #13 0x560240da863c in handle_one_connection /test/11.0_opt_san/sql/sql_connect.cc:1318
    #14 0x151255a2ab42 in start_thread nptl/pthread_create.c:442
    #15 0x151255abc9ff  (/lib/x86_64-linux-gnu/libc.so.6+0x1269ff)
 
0x606000010a18 is located 24 bytes inside of 56-byte region [0x606000010a00,0x606000010a38)
freed by thread T20 here:
    #0 0x56023fbe24e7 in __interceptor_free (/test/UBASAN_MD130223-mariadb-11.0.1-linux-x86_64-opt/bin/mariadbd+0x79094e7)
    #1 0x560243d917ef in mi_repair_by_sort /test/11.0_opt_san/storage/myisam/mi_check.c:2560
    #2 0x560243d5b426 in ha_myisam::repair(THD*, st_handler_check_param&, bool) /test/11.0_opt_san/storage/myisam/ha_myisam.cc:1345
    #3 0x560243d60ea1 in ha_myisam::enable_indexes(unsigned int) /test/11.0_opt_san/storage/myisam/ha_myisam.cc:1684
    #4 0x560243d61d8c in ha_myisam::end_bulk_insert() /test/11.0_opt_san/storage/myisam/ha_myisam.cc:1879
    #5 0x56024026b18d in select_insert::prepare_eof() /test/11.0_opt_san/sql/sql_insert.cc:4251
    #6 0x56024026fdfb in select_insert::send_eof() /test/11.0_opt_san/sql/sql_insert.cc:4361
    #7 0x560240896b44 in JOIN::exec_inner() /test/11.0_opt_san/sql/sql_select.cc:4699
    #8 0x56024089df23 in JOIN::exec() /test/11.0_opt_san/sql/sql_select.cc:4600
    #9 0x56024088bd8d in mysql_select(THD*, TABLE_LIST*, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) /test/11.0_opt_san/sql/sql_select.cc:5080
    #10 0x56024088f8e0 in handle_select(THD*, LEX*, select_result*, unsigned long long) /test/11.0_opt_san/sql/sql_select.cc:581
    #11 0x5602404a48bd in mysql_execute_command(THD*, bool) /test/11.0_opt_san/sql/sql_parse.cc:4713
    #12 0x5602404ae542 in mysql_parse(THD*, char*, unsigned int, Parser_state*) /test/11.0_opt_san/sql/sql_parse.cc:8000
    #13 0x5602404bbfa5 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /test/11.0_opt_san/sql/sql_parse.cc:1894
    #14 0x5602404c5700 in do_command(THD*, bool) /test/11.0_opt_san/sql/sql_parse.cc:1407
    #15 0x560240da603c in do_handle_one_connection(CONNECT*, bool) /test/11.0_opt_san/sql/sql_connect.cc:1416
    #16 0x560240da863c in handle_one_connection /test/11.0_opt_san/sql/sql_connect.cc:1318
    #17 0x151255a2ab42 in start_thread nptl/pthread_create.c:442
 
previously allocated by thread T20 here:
    #0 0x56023fbe2837 in malloc (/test/UBASAN_MD130223-mariadb-11.0.1-linux-x86_64-opt/bin/mariadbd+0x7909837)
    #1 0x560243f55724 in my_malloc /test/11.0_opt_san/mysys/my_malloc.c:91
    #2 0x560243de07ef in mi_alloc_rec_buff /test/11.0_opt_san/storage/myisam/mi_open.c:762
    #3 0x560243d91b6d in mi_repair_by_sort /test/11.0_opt_san/storage/myisam/mi_check.c:2241
    #4 0x560243d5b426 in ha_myisam::repair(THD*, st_handler_check_param&, bool) /test/11.0_opt_san/storage/myisam/ha_myisam.cc:1345
    #5 0x560243d60ea1 in ha_myisam::enable_indexes(unsigned int) /test/11.0_opt_san/storage/myisam/ha_myisam.cc:1684
    #6 0x560243d61d8c in ha_myisam::end_bulk_insert() /test/11.0_opt_san/storage/myisam/ha_myisam.cc:1879
    #7 0x56024026b18d in select_insert::prepare_eof() /test/11.0_opt_san/sql/sql_insert.cc:4251
    #8 0x56024026fdfb in select_insert::send_eof() /test/11.0_opt_san/sql/sql_insert.cc:4361
    #9 0x560240896b44 in JOIN::exec_inner() /test/11.0_opt_san/sql/sql_select.cc:4699
    #10 0x56024089df23 in JOIN::exec() /test/11.0_opt_san/sql/sql_select.cc:4600
    #11 0x56024088bd8d in mysql_select(THD*, TABLE_LIST*, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) /test/11.0_opt_san/sql/sql_select.cc:5080
    #12 0x56024088f8e0 in handle_select(THD*, LEX*, select_result*, unsigned long long) /test/11.0_opt_san/sql/sql_select.cc:581
    #13 0x5602404a48bd in mysql_execute_command(THD*, bool) /test/11.0_opt_san/sql/sql_parse.cc:4713
    #14 0x5602404ae542 in mysql_parse(THD*, char*, unsigned int, Parser_state*) /test/11.0_opt_san/sql/sql_parse.cc:8000
    #15 0x5602404bbfa5 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /test/11.0_opt_san/sql/sql_parse.cc:1894
    #16 0x5602404c5700 in do_command(THD*, bool) /test/11.0_opt_san/sql/sql_parse.cc:1407
    #17 0x560240da603c in do_handle_one_connection(CONNECT*, bool) /test/11.0_opt_san/sql/sql_connect.cc:1416
    #18 0x560240da863c in handle_one_connection /test/11.0_opt_san/sql/sql_connect.cc:1318
    #19 0x151255a2ab42 in start_thread nptl/pthread_create.c:442
 
Thread T20 created by T0 here:
    #0 0x56023fb86675 in pthread_create (/test/UBASAN_MD130223-mariadb-11.0.1-linux-x86_64-opt/bin/mariadbd+0x78ad675)
    #1 0x56023fc3ad3e in create_thread_to_handle_connection(CONNECT*) /test/11.0_opt_san/sql/mysqld.cc:6100
    #2 0x56023fc4d04f in handle_accepted_socket(st_mysql_socket, st_mysql_socket) /test/11.0_opt_san/sql/mysqld.cc:6221
    #3 0x56023fc4dfd7 in handle_connections_sockets() /test/11.0_opt_san/sql/mysqld.cc:6345
    #4 0x56023fc5103d in mysqld_main(int, char**) /test/11.0_opt_san/sql/mysqld.cc:5995
    #5 0x1512559bfd8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
 
SUMMARY: AddressSanitizer: heap-use-after-free /test/11.0_opt_san/sql/field.h:1405 in Field::set_notnull(long long)
Shadow bytes around the buggy address:
  0x0c0c7fffa0f0: fd fd fd fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fffa100: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
  0x0c0c7fffa110: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fffa120: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c0c7fffa130: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
=>0x0c0c7fffa140: fd fd fd[fd]fd fd fd fa fa fa fa fa fd fd fd fd
  0x0c0c7fffa150: fd fd fd fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fffa160: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fffa170: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fffa180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fffa190: 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
==852581==ABORTING
...
Query (0x629000087238): UPDATE t2 SET a=1

This second method may also be used to produce the crash in any version when using MTR; see first comment below. However, please note the stack is different.

Bug confirmed present in:
MariaDB: 10.3.38 (dbg), 10.3.38 (opt), 10.4.29 (dbg), 10.4.29 (opt), 10.5.20 (dbg), 10.5.20 (opt), 10.6.13 (opt), 10.6.13 (dbg), 10.7.8 (dbg), 10.7.8 (opt), 10.8.8 (dbg), 10.8.8 (opt), 10.9.6 (dbg), 10.9.6 (opt), 10.10.4 (dbg), 10.10.4 (opt), 10.11.2 (dbg), 10.11.2 (opt), 11.0.1 (dbg), 11.0.1 (opt)

Bug (or feature/syntax) confirmed not present in:
MySQL: 5.5.62 (dbg), 5.5.62 (opt), 5.6.51 (dbg), 5.6.51 (opt), 5.7.40 (dbg), 5.7.40 (opt), 8.0.31 (dbg), 8.0.31 (opt)



 Comments   
Comment by Roel Van de Paar [ 2023-03-25 ]

In MTR, the testcase (even when made to work with MTR) does not fail in the same way. You can use the CLI to reproduce the original crash with the testcase. However, the server can be made to produce the second crash with MTR by repeating the INSERT, in any version, as follows:

--source include/have_innodb.inc
SET sql_mode='';
CREATE TABLE t2 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM;
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
XA START 'a';
--error ER_PARSE_ERROR
UPDATE t1,non_existing_1 SET 1=1;
DELETE FROM mysql.db;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 (SELECT 1);
--error ER_NO_SUCH_TABLE
INSERT INTO non_existing_2 VALUES (1);
UPDATE t2 SET a=1;
--error ER_NO_SUCH_TABLE
INSERT INTO non_existing_2 VALUES (1);
SELECT SLEEP (1);

Comment by Roel Van de Paar [ 2023-03-25 ]

This testcase variation produces a different stack, and the same ASAN error:

SET sql_mode='';
CREATE TABLE t2 (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM;
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
XA START 'a';
UPDATE t1,non_existing_1 SET tb=tb;
DELETE FROM mysql.db;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 (SELECT 1);
INSERT INTO non_existing_2 VALUES (1);
UPDATE t2 SET a=1;
SELECT SLEEP (1);

Leads to:

11.0.1 f2dc4d4c10ac36a73b5c1eb765352d3aee808d66 (Optimized)

Core was generated by `/test/MD180223-mariadb-11.0.1-linux-x86_64-opt/bin/mariadbd --no-defaults --cor'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  lf_hash_destroy (hash=0x5652a1838860 <mdl_locks>)
    at /test/11.0_opt/mysys/lf_hash.cc:386
[Current thread is 1 (Thread 0x148d7e337480 (LWP 978641))]
(gdb) bt
#0  lf_hash_destroy (hash=0x5652a1838860 <mdl_locks>) at /test/11.0_opt/mysys/lf_hash.cc:386
#1  0x00005652a057c999 in clean_up (print_message=true) at /test/11.0_opt/sql/mysqld.cc:2005
#2  clean_up (print_message=<optimized out>) at /test/11.0_opt/sql/mysqld.cc:1961
#3  0x00005652a05850a7 in mysqld_main (argc=<optimized out>, argv=<optimized out>) at /test/11.0_opt/sql/mysqld.cc:6047
#4  0x0000148d7e60ed90 in __libc_start_call_main (main=main@entry=0x5652a053c540 <main(int, char**)>, argc=argc@entry=10, argv=argv@entry=0x7ffe4366d9a8) at ../sysdeps/nptl/libc_start_call_main.h:58
#5  0x0000148d7e60ee40 in __libc_start_main_impl (main=0x5652a053c540 <main(int, char**)>, argc=10, argv=0x7ffe4366d9a8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffe4366d998) at ../csu/libc-start.c:392
#6  0x00005652a057a6e5 in _start ()

Bug confirmed present in:
MariaDB: 10.3.38 (dbg), 10.3.38 (opt), 10.4.29 (dbg), 10.4.29 (opt), 10.5.20 (dbg), 10.5.20 (opt), 10.6.13 (dbg), 10.6.13 (opt), 10.7.8 (dbg), 10.7.8 (opt), 10.8.8 (dbg), 10.8.8 (opt), 10.9.6 (dbg), 10.9.6 (opt), 10.10.4 (dbg), 10.10.4 (opt), 10.11.2 (dbg), 10.11.2 (opt), 11.0.1 (dbg), 11.0.1 (opt)

Bug (or feature/syntax) confirmed not present in:
MySQL: 5.5.62 (dbg), 5.5.62 (opt), 5.6.51 (dbg), 5.6.51 (opt), 5.7.40 (dbg), 5.7.40 (opt), 8.0.31 (dbg), 8.0.31 (opt)

This testcase also produces a variety of stacks/UniqueID's across versions and reruns:

SIGSEGV|l_find|l_search|lf_hash_search_using_hash_value|lf_hash_search
SIGSEGV|l_find|lf_hash_iterate|tdc_iterate|tc_purge
SIGSEGV|lf_hash_destroy|MDL_map::destroy|mdl_destroy|clean_up
SIGSEGV|lf_hash_destroy|clean_up|clean_up|mysqld_main

Comment by Roel Van de Paar [ 2023-03-25 ]

All UniqueID's/stacks seen thus far:

SIGSEGV|l_find|lf_hash_iterate|tdc_iterate|tc_purge  # Main and second testcase, CLI only
SIGSEGV|l_find|l_search|lf_hash_search_using_hash_value|tdc_acquire_share  # Repeated testcase: MTR or 10.6(opt)/10.8(dbg+opt)/10.10(opt) in CLI
SIGSEGV|l_find|l_search|lf_hash_search_using_hash_value|lf_hash_search  # Second testcase
SIGSEGV|l_find|l_search|lf_hash_search_using_hash_value|MDL_map::find_or_insert  # Third testcase
SIGSEGV|lf_hash_destroy|MDL_map::destroy|mdl_destroy|clean_up  # Second testcase
SIGSEGV|lf_hash_destroy|clean_up|clean_up|mysqld_main  # Second testcase
ASAN|heap-use-after-free|sql/field.h|Field::set_notnull|save_int_value_in_field|Item_int::save_in_field|TABLE::update_virtual_fields  # ASAN builds

Comment by Roel Van de Paar [ 2023-03-25 ]

An additional testcase which can lead to a MDL_map::find_or_insert code path being used on some versions

SET sql_mode='';
CREATE TABLE t (a INT GENERATED ALWAYS AS (1) VIRTUAL,KEY(a)) ENGINE=MyISAM;
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
XA START 'a';
UPDATE t1,t2 SET tb=tb;
DELETE FROM mysql.db;
INSERT INTO t1 VALUES (1);
INSERT INTO t (SELECT 1);
INSERT INTO ti VALUES (1);
UPDATE t SET a=1;
SELECT SLEEP (1);

Leads to:

11.0.1 f2dc4d4c10ac36a73b5c1eb765352d3aee808d66 (Debug)

Core was generated by `/test/MD180223-mariadb-11.0.1-linux-x86_64-dbg/bin/mariadbd --no-defaults --cor'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  l_find (head=0x1478940a0ae8, head@entry=0x55a8b8f75da0, 
    cs=<optimized out>, hashnr=<optimized out>, 
    key=key@entry=0x1478d85e3348 "\002test", keylen=keylen@entry=9, 
    cursor=cursor@entry=0x1478d85e2de0, pins=<optimized out>, 
    callback=<optimized out>) at /test/11.0_dbg/mysys/lf_hash.cc:114
[Current thread is 1 (Thread 0x1478d85e4640 (LWP 1016556))]
(gdb) bt
#0  l_find (head=0x1478940a0ae8, head@entry=0x55a8b8f75da0, cs=<optimized out>, hashnr=<optimized out>, key=key@entry=0x1478d85e3348 "\002test", keylen=keylen@entry=9, cursor=cursor@entry=0x1478d85e2de0, pins=<optimized out>, callback=<optimized out>) at /test/11.0_dbg/mysys/lf_hash.cc:114
#1  0x000055a8b7746f08 in l_search (pins=0x55a8b8f6e698, keylen=9, key=0x1478d85e3348 "\002test", hashnr=<optimized out>, cs=<optimized out>, head=0x55a8b8f75da0) at /test/11.0_dbg/mysys/lf_hash.cc:298
#2  lf_hash_search_using_hash_value (hash=hash@entry=0x55a8b82d7300 <mdl_locks>, pins=pins@entry=0x55a8b8f6e698, hashnr=<optimized out>, key=key@entry=0x1478d85e3348, keylen=keylen@entry=9) at /test/11.0_dbg/mysys/lf_hash.cc:501
#3  0x000055a8b774703c in lf_hash_search (hash=0x55a8b82d7300 <mdl_locks>, pins=0x55a8b8f6e698, key=0x1478d85e3348, keylen=9) at /test/11.0_dbg/mysys/lf_hash.cc:541
#4  0x000055a8b6f5094b in MDL_map::find_or_insert (this=this@entry=0x55a8b82d7300 <mdl_locks>, pins=0x55a8b8f6e698, mdl_key=mdl_key@entry=0x1478d85e3340) at /test/11.0_dbg/sql/mdl.cc:861
#5  0x000055a8b6f52951 in MDL_context::try_acquire_lock_impl (this=this@entry=0x55a8b8fcbdc0, mdl_request=mdl_request@entry=0x1478d85e3320, out_ticket=out_ticket@entry=0x1478d85e2f48) at /test/11.0_dbg/sql/mdl.cc:2111
#6  0x000055a8b6f52e31 in MDL_context::acquire_lock (this=this@entry=0x55a8b8fcbdc0, mdl_request=mdl_request@entry=0x1478d85e3320, lock_wait_timeout=86400) at /test/11.0_dbg/sql/mdl.cc:2291
#7  0x000055a8b7632d89 in dict_acquire_mdl_shared<false, true> (table=table@entry=0x147894021290, thd=thd@entry=0x55a8b8fcbc68, mdl=mdl@entry=0x55a8b8eac0a0, table_op=table_op@entry=DICT_TABLE_OP_NORMAL) at /test/11.0_dbg/storage/innobase/dict/dict0dict.cc:734
#8  0x000055a8b7632f7b in dict_table_open_on_id<true> (table_id=18, dict_locked=dict_locked@entry=false, table_op=table_op@entry=DICT_TABLE_OP_NORMAL, thd=0x55a8b8fcbc68, mdl=mdl@entry=0x55a8b8eac0a0) at /test/11.0_dbg/storage/innobase/dict/dict0dict.cc:863
#9  0x000055a8b7502352 in row_purge_parse_undo_rec (updated_extern=0x1478d85e35c1, thr=0x55a8b8eabe88, undo_rec=0x55a8b8ea2450 "", node=0x55a8b8eabf28) at /test/11.0_dbg/storage/innobase/row/row0purge.cc:1026
#10 row_purge (thr=<optimized out>, undo_rec=<optimized out>, node=<optimized out>) at /test/11.0_dbg/storage/innobase/row/row0purge.cc:1204
#11 row_purge_step (thr=thr@entry=0x55a8b8eabe88) at /test/11.0_dbg/storage/innobase/row/row0purge.cc:1270
#12 0x000055a8b7486007 in que_thr_step (thr=0x55a8b8eabe88) at /test/11.0_dbg/storage/innobase/que/que0que.cc:597
#13 que_run_threads_low (thr=0x55a8b8eabe88) at /test/11.0_dbg/storage/innobase/que/que0que.cc:653
#14 que_run_threads (thr=0x55a8b8eabe88) at /test/11.0_dbg/storage/innobase/que/que0que.cc:673
#15 0x000055a8b7556b2c in trx_purge (n_tasks=<optimized out>, truncate=<optimized out>) at /test/11.0_dbg/storage/innobase/trx/trx0purge.cc:1404
#16 0x000055a8b7544dfa in purge_coordinator_state::do_purge (this=this@entry=0x55a8b8b2afa0 <purge_state>) at /test/11.0_dbg/storage/innobase/srv/srv0srv.cc:1533
#17 0x000055a8b7543897 in purge_coordinator_callback () at /test/11.0_dbg/storage/innobase/srv/srv0srv.cc:1687
#18 0x000055a8b76e0adb in tpool::task_group::execute (this=0x55a8b8b2ae20 <purge_coordinator_task_group>, t=t@entry=0x55a8b8b2ad80 <purge_coordinator_task>) at /test/11.0_dbg/tpool/task_group.cc:70
#19 0x000055a8b76e0d33 in tpool::task::execute (this=0x55a8b8b2ad80 <purge_coordinator_task>) at /test/11.0_dbg/tpool/task.cc:32
#20 0x000055a8b76deabe in tpool::thread_pool_generic::worker_main (this=0x55a8b8dfbc20, thread_var=0x55a8b8dfc350) at /test/11.0_dbg/tpool/tpool_generic.cc:580
#21 0x000055a8b76dfe3a in std::__invoke_impl<void, void (tpool::thread_pool_generic::*)(tpool::worker_data*), tpool::thread_pool_generic*, tpool::worker_data*> (__t=<optimized out>, __f=<optimized out>) at /usr/include/c++/11/bits/invoke.h:74
#22 std::__invoke<void (tpool::thread_pool_generic::*)(tpool::worker_data*), tpool::thread_pool_generic*, tpool::worker_data*> (__fn=<optimized out>) at /usr/include/c++/11/bits/invoke.h:96
#23 std::thread::_Invoker<std::tuple<void (tpool::thread_pool_generic::*)(tpool::worker_data*), tpool::thread_pool_generic*, tpool::worker_data*> >::_M_invoke<0ul, 1ul, 2ul> (this=<optimized out>) at /usr/include/c++/11/bits/std_thread.h:253
#24 std::thread::_Invoker<std::tuple<void (tpool::thread_pool_generic::*)(tpool::worker_data*), tpool::thread_pool_generic*, tpool::worker_data*> >::operator() (this=<optimized out>) at /usr/include/c++/11/bits/std_thread.h:260
#25 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (tpool::thread_pool_generic::*)(tpool::worker_data*), tpool::thread_pool_generic*, tpool::worker_data*> > >::_M_run (this=<optimized out>) at /usr/include/c++/11/bits/std_thread.h:211
#26 0x00001478f11012b3 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#27 0x00001478f0daab43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#28 0x00001478f0e3ca00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

Comment by Ramesh Sivaraman [ 2023-06-12 ]

Found almost similar stack without the XA transaction statement in the testcase

SET SQL_MODE='';
CREATE TABLE t (a INT GENERATED ALWAYS AS(1) VIRTUAL,KEY(a)) ENGINE=MyISAM;
INSERT INTO t SELECT 1;
SELECT * FROM non_existing_tbl;
SELECT * FROM t;
SHOW OPEN TABLES LIKE '';

10.4.30 8de6740a2ff13b95282595dcb817bcc16960b6d8 (Optimized)

Core was generated by `/test/MD050623-mariadb-10.4.30-linux-x86_64-opt/bin/mariadbd --no-defaults --co'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  l_find (head=0x145ff8062d78, head@entry=0x5606a23a4df0, cs=cs@entry=0x0, 
    hashnr=hashnr@entry=0, key=key@entry=0x1460401a1c00 "", 
    keylen=keylen@entry=0, cursor=cursor@entry=0x1460401a1b90, 
    pins=<optimized out>, callback=<optimized out>)
    at /test/10.4_opt/mysys/lf_hash.c:113
[Current thread is 1 (Thread 0x1460401a5700 (LWP 3182676))]
(gdb) bt
#0  l_find (head=0x145ff8062d78, head@entry=0x5606a23a4df0, cs=cs@entry=0x0, hashnr=hashnr@entry=0, key=key@entry=0x1460401a1c00 "", keylen=keylen@entry=0, cursor=cursor@entry=0x1460401a1b90, pins=<optimized out>, callback=<optimized out>) at /test/10.4_opt/mysys/lf_hash.c:113
#1  0x000056069fe79dc5 in lf_hash_iterate (hash=hash@entry=0x5606a07c1360 <tdc_hash>, pins=pins@entry=0x5606a2523df8, action=action@entry=0x56069f8e6100 <eliminate_duplicates(TDC_element*, eliminate_duplicates_arg*)>, argument=argument@entry=0x1460401a1c00) at /test/10.4_opt/mysys/lf_hash.c:522
#2  0x000056069f8e7aed in tdc_iterate (thd=thd@entry=0x145ff8000c48, action=0x56069f8e6100 <eliminate_duplicates(TDC_element*, eliminate_duplicates_arg*)>, action@entry=0x56069f7068c0 <list_open_tables_callback(TDC_element*, list_open_tables_arg*)>, argument=0x1460401a1c00, argument@entry=0x1460401a1d00, no_dups=no_dups@entry=true) at /test/10.4_opt/sql/table_cache.cc:1334
#3  0x000056069f70873b in list_open_tables (thd=thd@entry=0x145ff8000c48, db=<optimized out>, wild=<optimized out>) at /test/10.4_opt/sql/sql_base.cc:305
#4  0x000056069f7e1db3 in fill_open_tables (thd=0x145ff8000c48, tables=<optimized out>, cond=<optimized out>) at /test/10.4_opt/sql/sql_lex.h:3093
#5  0x000056069f7ee11b in get_schema_tables_result (join=join@entry=0x145ff8011230, executed_place=executed_place@entry=PROCESSED_BY_JOIN_EXEC) at /test/10.4_opt/sql/sql_show.cc:9083
#6  0x000056069f7d56d7 in JOIN::exec_inner (this=0x145ff8011230) at /test/10.4_opt/sql/sql_select.cc:4561
#7  0x000056069f7d5da6 in JOIN::exec (this=this@entry=0x145ff8011230) at /test/10.4_opt/sql/sql_select.cc:4387
#8  0x000056069f7d3e26 in mysql_select (thd=0x145ff8000c48, tables=0x145ff80104d0, wild_num=0, fields=@0x145ff80051b8: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x145ff80100d8, last = 0x145ff8010488, elements = 4}, <No data fields>}, conds=0x0, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=<optimized out>, result=0x145ff8011208, unit=0x145ff8004828, select_lex=0x145ff8005058) at /test/10.4_opt/sql/sql_select.cc:4826
#9  0x000056069f7d485a in handle_select (thd=thd@entry=0x145ff8000c48, lex=lex@entry=0x145ff8004768, result=result@entry=0x145ff8011208, setup_tables_done_option=setup_tables_done_option@entry=0) at /test/10.4_opt/sql/sql_select.cc:442
#10 0x000056069f760a2e in execute_sqlcom_select (thd=0x145ff8000c48, all_tables=0x145ff80104d0) at /test/10.4_opt/sql/sql_parse.cc:6473
#11 0x000056069f76ef9d in mysql_execute_command (thd=0x145ff8000c48) at /test/10.4_opt/sql/sql_parse.cc:3976
#12 0x000056069f7714e2 in mysql_parse (thd=0x145ff8000c48, rawbuf=<optimized out>, length=<optimized out>, parser_state=<optimized out>, is_com_multi=<optimized out>, is_next_command=<optimized out>) at /test/10.4_opt/sql/sql_parse.cc:8008
#13 0x000056069f773f95 in dispatch_command (command=COM_QUERY, thd=0x145ff8000c48, packet=<optimized out>, packet_length=<optimized out>, is_com_multi=<optimized out>, is_next_command=<optimized out>) at /test/10.4_opt/sql/sql_class.h:1231
#14 0x000056069f7757ef in do_command (thd=0x145ff8000c48) at /test/10.4_opt/sql/sql_parse.cc:1378
#15 0x000056069f86319e in do_handle_one_connection (connect=<optimized out>) at /test/10.4_opt/sql/sql_connect.cc:1420
#16 0x000056069f86322d in handle_one_connection (arg=<optimized out>) at /test/10.4_opt/sql/sql_connect.cc:1324
#17 0x000014605b0ca609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#18 0x000014605acb6133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Comment by Aleksey Midenkov [ 2023-09-22 ]

Please review bb-10.4-midenok

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