Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-16153

Server crashes in Apc_target::disable, ASAN heap-use-after-free in Explain_query::~Explain_query upon/after EXECUTE IMMEDIATE

Details

    Description

      CREATE OR REPLACE TABLE t1 (a INT) WITH SYSTEM VERSIONING;
      EXECUTE IMMEDIATE "SELECT * FROM t1 WHERE EXISTS (SELECT 1)";
      DROP TABLE t1;
      

      10.3 ASAN 15419a5583

      ==30831==ERROR: AddressSanitizer: heap-use-after-free on address 0x62b00002da70 at pc 0x5648473629bb bp 0x7f1d9095d970 sp 0x7f1d9095d968
      READ of size 1 at 0x62b00002da70 thread T5
          #0 0x5648473629ba in Explain_query::~Explain_query() /data/src/10.3/sql/sql_explain.cc:62
          #1 0x564847370cbc in delete_explain_query(LEX*) /data/src/10.3/sql/sql_explain.cc:2407
          #2 0x564846f949b4 in log_slow_statement(THD*) /data/src/10.3/sql/sql_parse.cc:2515
          #3 0x564846f93e81 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /data/src/10.3/sql/sql_parse.cc:2419
          #4 0x564846f8de9c in do_command(THD*) /data/src/10.3/sql/sql_parse.cc:1391
          #5 0x5648472fa2d3 in do_handle_one_connection(CONNECT*) /data/src/10.3/sql/sql_connect.cc:1402
          #6 0x5648472f9cdf in handle_one_connection /data/src/10.3/sql/sql_connect.cc:1308
          #7 0x564847e0e967 in pfs_spawn_thread /data/src/10.3/storage/perfschema/pfs.cc:1862
          #8 0x7f1d9cf22493 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)
          #9 0x7f1d9b30893e in __clone (/lib/x86_64-linux-gnu/libc.so.6+0xe893e)
       
      0x62b00002da70 is located 14448 bytes inside of 24716-byte region [0x62b00002a200,0x62b00003028c)
      freed by thread T5 here:
          #0 0x7f1d9d18c527 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x54527)
          #1 0x5648487c6a82 in free_memory /data/src/10.3/mysys/safemalloc.c:279
          #2 0x5648487c6088 in sf_free /data/src/10.3/mysys/safemalloc.c:197
          #3 0x56484879675d in my_free /data/src/10.3/mysys/my_malloc.c:222
          #4 0x564848776a75 in free_root /data/src/10.3/mysys/my_alloc.c:427
          #5 0x564846ff937e in Prepared_statement::~Prepared_statement() /data/src/10.3/sql/sql_prepare.cc:3812
          #6 0x564846ff9491 in Prepared_statement::~Prepared_statement() /data/src/10.3/sql/sql_prepare.cc:3814
          #7 0x564846ff3f63 in mysql_sql_stmt_execute_immediate(THD*) /data/src/10.3/sql/sql_prepare.cc:2886
          #8 0x564846f9c477 in mysql_execute_command(THD*) /data/src/10.3/sql/sql_parse.cc:3774
          #9 0x564846fb6a70 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /data/src/10.3/sql/sql_parse.cc:8019
          #10 0x564846f90e14 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /data/src/10.3/sql/sql_parse.cc:1846
          #11 0x564846f8de9c in do_command(THD*) /data/src/10.3/sql/sql_parse.cc:1391
          #12 0x5648472fa2d3 in do_handle_one_connection(CONNECT*) /data/src/10.3/sql/sql_connect.cc:1402
          #13 0x5648472f9cdf in handle_one_connection /data/src/10.3/sql/sql_connect.cc:1308
          #14 0x564847e0e967 in pfs_spawn_thread /data/src/10.3/storage/perfschema/pfs.cc:1862
          #15 0x7f1d9cf22493 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)
       
      previously allocated by thread T5 here:
          #0 0x7f1d9d18c73f in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x5473f)
          #1 0x5648487c57f8 in sf_malloc /data/src/10.3/mysys/safemalloc.c:118
          #2 0x564848795e50 in my_malloc /data/src/10.3/mysys/my_malloc.c:101
          #3 0x56484877461d in init_alloc_root /data/src/10.3/mysys/my_alloc.c:81
          #4 0x5648472703f2 in init_sql_alloc(st_mem_root*, char const*, unsigned int, unsigned int, unsigned long) /data/src/10.3/sql/thr_malloc.cc:65
          #5 0x564846ff8809 in Prepared_statement::Prepared_statement(THD*) /data/src/10.3/sql/sql_prepare.cc:3734
          #6 0x564846ff3d65 in mysql_sql_stmt_execute_immediate(THD*) /data/src/10.3/sql/sql_prepare.cc:2854
          #7 0x564846f9c477 in mysql_execute_command(THD*) /data/src/10.3/sql/sql_parse.cc:3774
          #8 0x564846fb6a70 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /data/src/10.3/sql/sql_parse.cc:8019
          #9 0x564846f90e14 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /data/src/10.3/sql/sql_parse.cc:1846
          #10 0x564846f8de9c in do_command(THD*) /data/src/10.3/sql/sql_parse.cc:1391
          #11 0x5648472fa2d3 in do_handle_one_connection(CONNECT*) /data/src/10.3/sql/sql_connect.cc:1402
          #12 0x5648472f9cdf in handle_one_connection /data/src/10.3/sql/sql_connect.cc:1308
          #13 0x564847e0e967 in pfs_spawn_thread /data/src/10.3/storage/perfschema/pfs.cc:1862
          #14 0x7f1d9cf22493 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)
       
      Thread T5 created by T0 here:
          #0 0x7f1d9d15bbba in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x23bba)
          #1 0x564847e0ef2f in spawn_thread_v1 /data/src/10.3/storage/perfschema/pfs.cc:1912
          #2 0x564846cfc6fa in inline_mysql_thread_create /data/src/10.3/include/mysql/psi/mysql_thread.h:1268
          #3 0x564846d127bf in create_thread_to_handle_connection(CONNECT*) /data/src/10.3/sql/mysqld.cc:6556
          #4 0x564846d12ec4 in create_new_thread /data/src/10.3/sql/mysqld.cc:6626
          #5 0x564846d13ed5 in handle_connections_sockets() /data/src/10.3/sql/mysqld.cc:6901
          #6 0x564846d11c7c in mysqld_main(int, char**) /data/src/10.3/sql/mysqld.cc:6178
          #7 0x564846cfa79f in main /data/src/10.3/sql/main.cc:25
          #8 0x7f1d9b2402b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
       
      SUMMARY: AddressSanitizer: heap-use-after-free /data/src/10.3/sql/sql_explain.cc:62 Explain_query::~Explain_query()
      Shadow bytes around the buggy address:
        0x0c567fffdaf0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
        0x0c567fffdb00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
        0x0c567fffdb10: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
        0x0c567fffdb20: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
        0x0c567fffdb30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
      =>0x0c567fffdb40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd
        0x0c567fffdb50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
        0x0c567fffdb60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
        0x0c567fffdb70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
        0x0c567fffdb80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
        0x0c567fffdb90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
      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
        Heap right redzone:      fb
        Freed heap region:       fd
        Stack left redzone:      f1
        Stack mid redzone:       f2
        Stack right redzone:     f3
        Stack partial redzone:   f4
        Stack after return:      f5
        Stack use after scope:   f8
        Global redzone:          f9
        Global init order:       f6
        Poisoned by user:        f7
        Contiguous container OOB:fc
        ASan internal:           fe
      ==30831==ABORTING
      

      10.3 15419a5583

      #3  <signal handler called>
      #4  0x0000557b30c6de54 in Apc_target::disable (this=0x8f8f8f8f8f8fccf7) at /data/src/10.3/sql/my_apc.h:68
      #5  0x0000557b30c653cb in Explain_query::~Explain_query (this=0x7f3564117bd0, __in_chrg=<optimized out>) at /data/src/10.3/sql/sql_explain.cc:63
      #6  0x0000557b30c6d429 in delete_explain_query (lex=0x7f35640048b8) at /data/src/10.3/sql/sql_explain.cc:2407
      #7  0x0000557b30acbf74 in log_slow_statement (thd=0x7f3564000b00) at /data/src/10.3/sql/sql_parse.cc:2515
      #8  0x0000557b30acbafc in dispatch_command (command=COM_QUERY, thd=0x7f3564000b00, packet=0x7f3564145801 "", packet_length=60, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:2419
      #9  0x0000557b30ac886b in do_command (thd=0x7f3564000b00) at /data/src/10.3/sql/sql_parse.cc:1391
      #10 0x0000557b30c2d891 in do_handle_one_connection (connect=0x557b34a46eb0) at /data/src/10.3/sql/sql_connect.cc:1402
      #11 0x0000557b30c2d615 in handle_one_connection (arg=0x557b34a46eb0) at /data/src/10.3/sql/sql_connect.cc:1308
      #12 0x0000557b310bcab1 in pfs_spawn_thread (arg=0x557b34ae87c0) at /data/src/10.3/storage/perfschema/pfs.cc:1862
      #13 0x00007f357dfc2494 in start_thread (arg=0x7f3576493700) at pthread_create.c:333
      #14 0x00007f357c3a893f in clone () from /lib/x86_64-linux-gnu/libc.so.6
      

      It appears to be a very recent regression (of the past few days), I didn't search for the exact commit which caused it.

      Attachments

        Activity

          Explain_query is created on stmt arena. This is a bug:

          Old value = (MEM_ROOT *) 0x62a0000bf730
          New value = (MEM_ROOT *) 0x6190000d46f8
          Query_arena::set_query_arena (this=0x62a0000ba220, set=0x6190000d43a0) at sql_class.cc:3826
          3826      free_list= set->free_list;
          #0  Query_arena::set_query_arena (this=0x62a0000ba220, set=0x6190000d43a0) at sql_class.cc:3826
          #1  THD::set_n_backup_active_arena (this=0x62a0000ba208, set=0x6190000d43a0, backup=0x7fffde5af420) at sql_class.cc:3914
          #2  THD::activate_stmt_arena_if_needed (this=0x62a0000ba208, backup=0x7fffde5af420) at sql_class.h:3937
          #3  JOIN::optimize_inner (this=0x62b000001230) at sql_select.cc:1601
          #4  JOIN::optimize (this=0x62b000001230) at sql_select.cc:1433
          #5  mysql_select (thd=0x62a0000ba208, tables=0x62b00002bbb8, wild_num=0, fields=List<Item> with 1 elements, conds=0x62b00002d710, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2416184064, result=0x62b00002d030, unit=0x62b00002a2e8, select_lex=0x62b00002aa60) at sql_select.cc:4157
          #6  handle_select (thd=0x62a0000ba208, lex=0x62b00002a220, result=0x62b00002d030, setup_tables_done_option=0) at sql_select.cc:370
          #7  execute_sqlcom_select (thd=0x62a0000ba208, all_tables=0x62b00002bbb8) at sql_parse.cc:6545
          #8  mysql_execute_command (thd=0x62a0000ba208) at sql_parse.cc:3768
          #9  Prepared_statement::execute (this=0x6190000d4388, expanded_query=0x7fffde5b7d40, open_cursor=false) at sql_prepare.cc:4764
          #10 Prepared_statement::execute_loop (this=0x6190000d4388, expanded_query=0x7fffde5b7d40, open_cursor=false, packet=0x0, packet_end=0x0) at sql_prepare.cc:4192
          #11 Prepared_statement::execute_immediate (this=0x6190000d4388, query=0x62b000000310 "select * from t1 where exists (select 1)", query_len=40) at sql_prepare.cc:4888
          #12 mysql_sql_stmt_execute_immediate (thd=0x62a0000ba208) at sql_prepare.cc:2880
           
          Thread 28 "mysqld" hit Breakpoint 4, alloc_root (mem_root=0x6190000d46f8, length=112) at my_alloc.c:277
          277       DBUG_PRINT("exit",("ptr: %p", point));
          #0  alloc_root (mem_root=0x6190000d46f8, length=112) at my_alloc.c:277
          #1  Sql_alloc::operator new (size=112, mem_root=0x6190000d46f8) at sql_alloc.h:39
          #2  create_explain_query (lex=0x62b00002a220, mem_root=0x6190000d46f8) at sql_explain.cc:2418
          #3  create_explain_query_if_not_exists (lex=0x62b00002a220, mem_root=0x6190000d46f8) at sql_explain.cc:2427
          #4  JOIN::build_explain (this=0x62b000001858) at sql_select.cc:1393
          #5  JOIN::optimize (this=0x62b000001858) at sql_select.cc:1439
          #6  subselect_single_select_engine::exec (this=0x62b00002cff0) at item_subselect.cc:3784
          #7  Item_subselect::exec (this=0x62b00002ce58) at item_subselect.cc:723
          #8  Item_exists_subselect::val_int (this=0x62b00002ce58) at item_subselect.cc:1594
          #9  Item_in_optimizer::val_int (this=0x62b00002d710) at item_cmpfunc.cc:1519
          #10 Item_cond::fix_fields (this=0x62b00002d878, thd=0x62a0000ba208, ref=0x7fffde5aeaa0) at item_cmpfunc.cc:4598
          #11 simplify_joins (join=0x62b000001230, join_list=0x62b00002ac00, conds=0x62b00002d878, top=true, in_sj=false) at sql_select.cc:15188
          #12 JOIN::optimize_inner (this=0x62b000001230) at sql_select.cc:1606
          #13 JOIN::optimize (this=0x62b000001230) at sql_select.cc:1433
          #14 mysql_select (thd=0x62a0000ba208, tables=0x62b00002bbb8, wild_num=0, fields=List<Item> with 1 elements, conds=0x62b00002d710, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2416184064, result=0x62b00002d030, unit=0x62b00002a2e8, select_lex=0x62b00002aa60) at sql_select.cc:4157
          #15 handle_select (thd=0x62a0000ba208, lex=0x62b00002a220, result=0x62b00002d030, setup_tables_done_option=0) at sql_select.cc:370
          #16 execute_sqlcom_select (thd=0x62a0000ba208, all_tables=0x62b00002bbb8) at sql_parse.cc:6545
          #17 mysql_execute_command (thd=0x62a0000ba208) at sql_parse.cc:3768
          #18 Prepared_statement::execute (this=0x6190000d4388, expanded_query=0x7fffde5b7d40, open_cursor=false) at sql_prepare.cc:4764
          #19 Prepared_statement::execute_loop (this=0x6190000d4388, expanded_query=0x7fffde5b7d40, open_cursor=false, packet=0x0, packet_end=0x0) at sql_prepare.cc:4192
          #20 Prepared_statement::execute_immediate (this=0x6190000d4388, query=0x62b000000310 "select * from t1 where exists (select 1)", query_len=40) at sql_prepare.cc:4888
          #21 mysql_sql_stmt_execute_immediate (thd=0x62a0000ba208) at sql_prepare.cc:2880
          

          Here 0x6190000d46f8 is a stmt_arena and 0x62a0000bf730 is THD own arena.

          Some diagnostic code:

          diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
          index 7139466be17..ecb70100b39 100644
          --- a/mysys/my_alloc.c
          +++ b/mysys/my_alloc.c
          @@ -491,3 +491,39 @@ void *memdup_root(MEM_ROOT *root, const void *str, size_t len)
               memcpy(pos,str,len);
             return pos;
           }
          +
          +static my_bool block_contains_allocated_address(USED_MEM *block, void *ptr)
          +{
          +  DBUG_ASSERT(block);
          +  void *right_boundary= (char *)block + block->size - block->left;
          +  return (void *)block <= ptr && ptr < right_boundary;
          +}
          +
          +my_bool contains_allocated_address(MEM_ROOT *root, void *ptr)
          +{
          +  USED_MEM *pre_alloc= root->pre_alloc;
          +  if (pre_alloc)
          +  {
          +    if (block_contains_allocated_address(pre_alloc, ptr))
          +    {
          +      return TRUE;
          +    }
          +  }
          +
          +  for (USED_MEM *block= root->used; block; block= block->next)
          +  {
          +    if (block_contains_allocated_address(block, ptr))
          +    {
          +      return TRUE;
          +    }
          +  }
          +  for (USED_MEM *block= root->free; block; block= block->next)
          +  {
          +    if (block_contains_allocated_address(block, ptr))
          +    {
          +      return TRUE;
          +    }
          +  }
          +
          +  return FALSE;
          +}
          

          GDB script for original test:

          set $problem_address = 0x62b00002da08
          # mysql_sql_stmt_execute_immediate()
          b sql_prepare.cc:2836
          commands
            bt
            p thd->mem_root
            p thd->stmt_arena->mem_root
            watch -l *&thd->mem_root
            commands
              bt
            end
          # init_alloc_root()
            b my_alloc.c:61
            commands
              bt
              p mem_root
            end
          # alloc_root()
            b my_alloc.c:277 if point <= $problem_address && $problem_address <= point + length
            commands
              bt
              p mem_root
            end
          # free_root()
            b my_alloc.c:393 if contains_allocated_address(root, $problem_address)
            commands
              bt
              p root
            end
          end
          

          GDB script for the same test bug without WITH SYSTEM VERSIONING:

          # mysql_sql_stmt_execute_immediate()
          b sql_prepare.cc:2836
          commands
            bt
            p thd->mem_root
            p thd->stmt_arena->mem_root
          # create_explain_query()
            b sql_explain.cc:2415
            commands
              bt
              p mem_root
            end
            watch -l *&thd->mem_root
            commands
              bt 10
            end
            init_alloc_root()
            b my_alloc.c:61
            commands
              bt 10
              p mem_root
            end
          end
          

          kevg Eugene Kosov (Inactive) added a comment - Explain_query is created on stmt arena. This is a bug: Old value = (MEM_ROOT *) 0x62a0000bf730 New value = (MEM_ROOT *) 0x6190000d46f8 Query_arena::set_query_arena (this=0x62a0000ba220, set=0x6190000d43a0) at sql_class.cc:3826 3826 free_list= set->free_list; #0 Query_arena::set_query_arena (this=0x62a0000ba220, set=0x6190000d43a0) at sql_class.cc:3826 #1 THD::set_n_backup_active_arena (this=0x62a0000ba208, set=0x6190000d43a0, backup=0x7fffde5af420) at sql_class.cc:3914 #2 THD::activate_stmt_arena_if_needed (this=0x62a0000ba208, backup=0x7fffde5af420) at sql_class.h:3937 #3 JOIN::optimize_inner (this=0x62b000001230) at sql_select.cc:1601 #4 JOIN::optimize (this=0x62b000001230) at sql_select.cc:1433 #5 mysql_select (thd=0x62a0000ba208, tables=0x62b00002bbb8, wild_num=0, fields=List<Item> with 1 elements, conds=0x62b00002d710, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2416184064, result=0x62b00002d030, unit=0x62b00002a2e8, select_lex=0x62b00002aa60) at sql_select.cc:4157 #6 handle_select (thd=0x62a0000ba208, lex=0x62b00002a220, result=0x62b00002d030, setup_tables_done_option=0) at sql_select.cc:370 #7 execute_sqlcom_select (thd=0x62a0000ba208, all_tables=0x62b00002bbb8) at sql_parse.cc:6545 #8 mysql_execute_command (thd=0x62a0000ba208) at sql_parse.cc:3768 #9 Prepared_statement::execute (this=0x6190000d4388, expanded_query=0x7fffde5b7d40, open_cursor=false) at sql_prepare.cc:4764 #10 Prepared_statement::execute_loop (this=0x6190000d4388, expanded_query=0x7fffde5b7d40, open_cursor=false, packet=0x0, packet_end=0x0) at sql_prepare.cc:4192 #11 Prepared_statement::execute_immediate (this=0x6190000d4388, query=0x62b000000310 "select * from t1 where exists (select 1)", query_len=40) at sql_prepare.cc:4888 #12 mysql_sql_stmt_execute_immediate (thd=0x62a0000ba208) at sql_prepare.cc:2880   Thread 28 "mysqld" hit Breakpoint 4, alloc_root (mem_root=0x6190000d46f8, length=112) at my_alloc.c:277 277 DBUG_PRINT("exit",("ptr: %p", point)); #0 alloc_root (mem_root=0x6190000d46f8, length=112) at my_alloc.c:277 #1 Sql_alloc::operator new (size=112, mem_root=0x6190000d46f8) at sql_alloc.h:39 #2 create_explain_query (lex=0x62b00002a220, mem_root=0x6190000d46f8) at sql_explain.cc:2418 #3 create_explain_query_if_not_exists (lex=0x62b00002a220, mem_root=0x6190000d46f8) at sql_explain.cc:2427 #4 JOIN::build_explain (this=0x62b000001858) at sql_select.cc:1393 #5 JOIN::optimize (this=0x62b000001858) at sql_select.cc:1439 #6 subselect_single_select_engine::exec (this=0x62b00002cff0) at item_subselect.cc:3784 #7 Item_subselect::exec (this=0x62b00002ce58) at item_subselect.cc:723 #8 Item_exists_subselect::val_int (this=0x62b00002ce58) at item_subselect.cc:1594 #9 Item_in_optimizer::val_int (this=0x62b00002d710) at item_cmpfunc.cc:1519 #10 Item_cond::fix_fields (this=0x62b00002d878, thd=0x62a0000ba208, ref=0x7fffde5aeaa0) at item_cmpfunc.cc:4598 #11 simplify_joins (join=0x62b000001230, join_list=0x62b00002ac00, conds=0x62b00002d878, top=true, in_sj=false) at sql_select.cc:15188 #12 JOIN::optimize_inner (this=0x62b000001230) at sql_select.cc:1606 #13 JOIN::optimize (this=0x62b000001230) at sql_select.cc:1433 #14 mysql_select (thd=0x62a0000ba208, tables=0x62b00002bbb8, wild_num=0, fields=List<Item> with 1 elements, conds=0x62b00002d710, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2416184064, result=0x62b00002d030, unit=0x62b00002a2e8, select_lex=0x62b00002aa60) at sql_select.cc:4157 #15 handle_select (thd=0x62a0000ba208, lex=0x62b00002a220, result=0x62b00002d030, setup_tables_done_option=0) at sql_select.cc:370 #16 execute_sqlcom_select (thd=0x62a0000ba208, all_tables=0x62b00002bbb8) at sql_parse.cc:6545 #17 mysql_execute_command (thd=0x62a0000ba208) at sql_parse.cc:3768 #18 Prepared_statement::execute (this=0x6190000d4388, expanded_query=0x7fffde5b7d40, open_cursor=false) at sql_prepare.cc:4764 #19 Prepared_statement::execute_loop (this=0x6190000d4388, expanded_query=0x7fffde5b7d40, open_cursor=false, packet=0x0, packet_end=0x0) at sql_prepare.cc:4192 #20 Prepared_statement::execute_immediate (this=0x6190000d4388, query=0x62b000000310 "select * from t1 where exists (select 1)", query_len=40) at sql_prepare.cc:4888 #21 mysql_sql_stmt_execute_immediate (thd=0x62a0000ba208) at sql_prepare.cc:2880 Here 0x6190000d46f8 is a stmt_arena and 0x62a0000bf730 is THD own arena. Some diagnostic code: diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 7139466be17..ecb70100b39 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -491,3 +491,39 @@ void *memdup_root(MEM_ROOT *root, const void *str, size_t len) memcpy(pos,str,len); return pos; } + +static my_bool block_contains_allocated_address(USED_MEM *block, void *ptr) +{ + DBUG_ASSERT(block); + void *right_boundary= (char *)block + block->size - block->left; + return (void *)block <= ptr && ptr < right_boundary; +} + +my_bool contains_allocated_address(MEM_ROOT *root, void *ptr) +{ + USED_MEM *pre_alloc= root->pre_alloc; + if (pre_alloc) + { + if (block_contains_allocated_address(pre_alloc, ptr)) + { + return TRUE; + } + } + + for (USED_MEM *block= root->used; block; block= block->next) + { + if (block_contains_allocated_address(block, ptr)) + { + return TRUE; + } + } + for (USED_MEM *block= root->free; block; block= block->next) + { + if (block_contains_allocated_address(block, ptr)) + { + return TRUE; + } + } + + return FALSE; +} GDB script for original test: set $problem_address = 0x62b00002da08 # mysql_sql_stmt_execute_immediate() b sql_prepare.cc:2836 commands bt p thd->mem_root p thd->stmt_arena->mem_root watch -l *&thd->mem_root commands bt end # init_alloc_root() b my_alloc.c:61 commands bt p mem_root end # alloc_root() b my_alloc.c:277 if point <= $problem_address && $problem_address <= point + length commands bt p mem_root end # free_root() b my_alloc.c:393 if contains_allocated_address(root, $problem_address) commands bt p root end end GDB script for the same test bug without WITH SYSTEM VERSIONING : # mysql_sql_stmt_execute_immediate() b sql_prepare.cc:2836 commands bt p thd->mem_root p thd->stmt_arena->mem_root # create_explain_query() b sql_explain.cc:2415 commands bt p mem_root end watch -l *&thd->mem_root commands bt 10 end init_alloc_root() b my_alloc.c:61 commands bt 10 p mem_root end end

          Terrible fix:

          diff --git a/sql/sql_class.h b/sql/sql_class.h
          index e453eb9ce60..b3cd7c71591 100644
          --- a/sql/sql_class.h
          +++ b/sql/sql_class.h
          @@ -4539,7 +4539,10 @@ class THD :public Statement,
               - for prepared queries, only to allocate runtime data. The parsed
               tree itself is reused between executions and thus is stored elsewhere.
             */
          +public:
             MEM_ROOT main_mem_root;
          +
          +private:
             Diagnostics_area main_da;
             Diagnostics_area *m_stmt_da;
           
          diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
          index 5d977c6d5c2..0f03f81c0cb 100644
          --- a/sql/sql_explain.cc
          +++ b/sql/sql_explain.cc
          @@ -2415,8 +2415,7 @@ void create_explain_query(LEX *lex, MEM_ROOT *mem_root)
             DBUG_ASSERT(!lex->explain);
             DBUG_ENTER("create_explain_query");
           
          -  lex->explain= new (mem_root) Explain_query(lex->thd, mem_root);
          -  DBUG_ASSERT(mem_root == current_thd->mem_root);
          +  lex->explain= new (&lex->thd->main_mem_root) Explain_query(lex->thd, &lex->thd->main_mem_root);
           
             DBUG_VOID_RETURN;
           }
          

          kevg Eugene Kosov (Inactive) added a comment - Terrible fix: diff --git a/sql/sql_class.h b/sql/sql_class.h index e453eb9ce60..b3cd7c71591 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4539,7 +4539,10 @@ class THD :public Statement, - for prepared queries, only to allocate runtime data. The parsed tree itself is reused between executions and thus is stored elsewhere. */ +public: MEM_ROOT main_mem_root; + +private: Diagnostics_area main_da; Diagnostics_area *m_stmt_da; diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 5d977c6d5c2..0f03f81c0cb 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -2415,8 +2415,7 @@ void create_explain_query(LEX *lex, MEM_ROOT *mem_root) DBUG_ASSERT(!lex->explain); DBUG_ENTER("create_explain_query"); - lex->explain= new (mem_root) Explain_query(lex->thd, mem_root); - DBUG_ASSERT(mem_root == current_thd->mem_root); + lex->explain= new (&lex->thd->main_mem_root) Explain_query(lex->thd, &lex->thd->main_mem_root); DBUG_VOID_RETURN; }

          Assigned to psergey for review.

          svoj Sergey Vojtovich added a comment - Assigned to psergey for review.
          svoj Sergey Vojtovich added a comment - Pull request: https://github.com/MariaDB/server/pull/754

          Test case w/o versioning:

          CREATE TABLE t1 (a INT);
          EXECUTE IMMEDIATE "SELECT * FROM t1 join t1 t2 ON (t1.a>5) WHERE EXISTS (SELECT 1)";
          DROP TABLE t1;
          

          serg Sergei Golubchik added a comment - Test case w/o versioning: CREATE TABLE t1 (a INT ); EXECUTE IMMEDIATE "SELECT * FROM t1 join t1 t2 ON (t1.a>5) WHERE EXISTS (SELECT 1)" ; DROP TABLE t1;
          elenst Elena Stepanova added a comment - - edited

          Thanks, demoting to Critical, then. It doesn't have to be a blocker for 10.3 if it also affects 10.2. Still would be good to have it fixed, though.

          The problem appeared in 10.2 tree with this merge

          commit 9b1824dcd2564c803e58d02ac63b49ec68bd60d2 92a13148e80c30422ae5460032169cbe1946fa6d ff579bc814551026a3271fac274f560cef3f523f
          Merge: 92a1314 ff579bc
          Author: Sergei Golubchik <serg@mariadb.org>
          Date:   Thu May 10 13:01:42 2018 +0200
           
              Merge branch '10.1' into 10.2
          

          but I can't tell which commit caused it.

          elenst Elena Stepanova added a comment - - edited Thanks, demoting to Critical, then. It doesn't have to be a blocker for 10.3 if it also affects 10.2. Still would be good to have it fixed, though. The problem appeared in 10.2 tree with this merge commit 9b1824dcd2564c803e58d02ac63b49ec68bd60d2 92a13148e80c30422ae5460032169cbe1946fa6d ff579bc814551026a3271fac274f560cef3f523f Merge: 92a1314 ff579bc Author: Sergei Golubchik <serg@mariadb.org> Date: Thu May 10 13:01:42 2018 +0200   Merge branch '10.1' into 10.2 but I can't tell which commit caused it.

          People

            serg Sergei Golubchik
            elenst Elena Stepanova
            Votes:
            1 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Git Integration

                Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.