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

Server crashes in base_list_iterator::next_fast on 1st execution of PS with a multi-table update

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • 5.5(EOL), 10.0(EOL), 10.1(EOL)
    • 5.5.45
    • Prepared Statements
    • None

    Description

      Test case

      CREATE TABLE t1 (a INT) ENGINE=MyISAM;
      INSERT INTO t1 VALUES (1),(2); # Not necessary, the table can be empty
       
      CREATE TABLE t2 (b INT) ENGINE=MyISAM;
      INSERT INTO t2 VALUES (3),(4); # Not necessary, the table can be empty
       
      CREATE TABLE t3 (c INT) ENGINE=MyISAM;
      INSERT INTO t3 VALUES (5),(6); # Not necessary, the table can be empty
       
      CREATE OR REPLACE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3;
       
      PREPARE stmt FROM 'UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM t3 )';
      UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM v3 );
      EXECUTE stmt;

      Stack trace from 5.5 commit e40bc659335f7f8b69427ed2d215c34c045a5ed7

      #3  <signal handler called>
      #4  0x0000000000591ccd in base_list_iterator::next_fast (this=0x7f78ebbb4070) at 5.5/sql/sql_list.h:455
      #5  0x00000000005e9581 in List_iterator_fast<TABLE_LIST>::operator++ (this=0x7f78ebbb4070) at 5.5/sql/sql_list.h:569
      #6  0x000000000062cf23 in st_select_lex::save_prep_leaf_tables (this=0x7f78eb144648, thd=0x7f78ec150060) at 5.5/sql/sql_lex.cc:4142
      #7  0x000000000062cf78 in st_select_lex::save_prep_leaf_tables (this=0x7f78eb169810, thd=0x7f78ec150060) at 5.5/sql/sql_lex.cc:4152
      #8  0x000000000062ce44 in LEX::save_prep_leaf_tables (this=0x7f78eb169080) at 5.5/sql/sql_lex.cc:4115
      #9  0x00000000006eb182 in mysql_multi_update_prepare (thd=0x7f78ec150060) at 5.5/sql/sql_update.cc:1391
      #10 0x0000000000636ef6 in mysql_execute_command (thd=0x7f78ec150060) at 5.5/sql/sql_parse.cc:2868
      #11 0x0000000000656989 in Prepared_statement::execute (this=0x7f78eb134460, expanded_query=0x7f78ebbb4c90, open_cursor=false) at 5.5/sql/sql_prepare.cc:3928
      #12 0x0000000000655aa0 in Prepared_statement::execute_loop (this=0x7f78eb134460, expanded_query=0x7f78ebbb4c90, open_cursor=false, packet=0x0, packet_end=0x0) at 5.5/sql/sql_prepare.cc:3587
      #13 0x0000000000653bc4 in mysql_sql_stmt_execute (thd=0x7f78ec150060) at 5.5/sql/sql_prepare.cc:2737
      #14 0x000000000063578c in mysql_execute_command (thd=0x7f78ec150060) at 5.5/sql/sql_parse.cc:2244
      #15 0x000000000063f062 in mysql_parse (thd=0x7f78ec150060, rawbuf=0x7f78eb287078 "EXECUTE stmt", length=12, parser_state=0x7f78ebbb5620) at 5.5/sql/sql_parse.cc:5909
      #16 0x0000000000632ca5 in dispatch_command (command=COM_QUERY, thd=0x7f78ec150060, packet=0x7f78ec207061 "EXECUTE stmt", packet_length=12) at 5.5/sql/sql_parse.cc:1079
      #17 0x0000000000631e31 in do_command (thd=0x7f78ec150060) at 5.5/sql/sql_parse.cc:793
      #18 0x0000000000734f49 in do_handle_one_connection (thd_arg=0x7f78ec150060) at 5.5/sql/sql_connect.cc:1269
      #19 0x0000000000734cc3 in handle_one_connection (arg=0x7f78ec150060) at 5.5/sql/sql_connect.cc:1185
      #20 0x0000000000b6de45 in pfs_spawn_thread (arg=0x7f78ec171ca0) at 5.5/storage/perfschema/pfs.cc:1015
      #21 0x00007f78f229cb50 in start_thread (arg=<optimized out>) at pthread_create.c:304
      #22 0x00007f78f055295d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112

      Attachments

        Issue Links

          Activity

            valgrind shows it's reading memory that was allocated on statement's execution MEM_ROOT:

            ==9735== Invalid read of size 8
            ==9735==    at 0x5695D7: base_list_iterator::next_fast() (sql_list.h:455)
            ==9735==    by 0x5C3254: List_iterator_fast<TABLE_LIST>::operator++(int) (sql_list.h:569)
            ==9735==    by 0x607DAA: st_select_lex::save_prep_leaf_tables(THD*) (sql_lex.cc:4142)
            ==9735==    by 0x607DFF: st_select_lex::save_prep_leaf_tables(THD*) (sql_lex.cc:4152)
            ==9735==    by 0x607CCB: LEX::save_prep_leaf_tables() (sql_lex.cc:4115)
            ==9735==    by 0x6C8CC6: mysql_multi_update_prepare(THD*) (sql_update.cc:1391)
            ==9735==    by 0x612481: mysql_execute_command(THD*) (sql_parse.cc:2868)
            ==9735==    by 0x632196: Prepared_statement::execute(String*, bool) (sql_prepare.cc:3928)
            ==9735==    by 0x6312E3: Prepared_statement::execute_loop(String*, bool, unsigned char*, unsigned char*) (sql_prepare.cc:3587)
            ==9735==    by 0x62F42F: mysql_sql_stmt_execute(THD*) (sql_prepare.cc:2737)
            ==9735==    by 0x610D0F: mysql_execute_command(THD*) (sql_parse.cc:2244)
            ==9735==    by 0x61A64F: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:5909)
            ==9735==    by 0x60E218: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1079)
            ==9735==    by 0x60D3A1: do_command(THD*) (sql_parse.cc:793)
            ==9735==    by 0x71597E: do_handle_one_connection(THD*) (sql_connect.cc:1269)
            ==9735==    by 0x7156F8: handle_one_connection (sql_connect.cc:1185)
            ==9735==  Address 0x88f6598 is 40 bytes inside a block of size 48 free'd
            ==9735==    at 0x4A0662E: free (vg_replace_malloc.c:366)
            ==9735==    by 0xCD4209: my_free (my_malloc.c:119)
            ==9735==    by 0xCC5B81: free_root (my_alloc.c:366)
            ==9735==    by 0x60F766: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1493)
            ==9735==    by 0x60D3A1: do_command(THD*) (sql_parse.cc:793)
            ==9735==    by 0x71597E: do_handle_one_connection(THD*) (sql_connect.cc:1269)
            ==9735==    by 0x7156F8: handle_one_connection (sql_connect.cc:1185)
            ==9735==    by 0xC165CA: pfs_spawn_thread (pfs.cc:1015)
            ==9735==    by 0x3509C07D8F: start_thread (pthread_create.c:309)
            ==9735==    by 0x35098F0F5C: clone (clone.S:115)
            ==9735== 

            psergei Sergei Petrunia added a comment - valgrind shows it's reading memory that was allocated on statement's execution MEM_ROOT: ==9735== Invalid read of size 8 ==9735== at 0x5695D7: base_list_iterator::next_fast() (sql_list.h:455) ==9735== by 0x5C3254: List_iterator_fast<TABLE_LIST>::operator++(int) (sql_list.h:569) ==9735== by 0x607DAA: st_select_lex::save_prep_leaf_tables(THD*) (sql_lex.cc:4142) ==9735== by 0x607DFF: st_select_lex::save_prep_leaf_tables(THD*) (sql_lex.cc:4152) ==9735== by 0x607CCB: LEX::save_prep_leaf_tables() (sql_lex.cc:4115) ==9735== by 0x6C8CC6: mysql_multi_update_prepare(THD*) (sql_update.cc:1391) ==9735== by 0x612481: mysql_execute_command(THD*) (sql_parse.cc:2868) ==9735== by 0x632196: Prepared_statement::execute(String*, bool) (sql_prepare.cc:3928) ==9735== by 0x6312E3: Prepared_statement::execute_loop(String*, bool, unsigned char*, unsigned char*) (sql_prepare.cc:3587) ==9735== by 0x62F42F: mysql_sql_stmt_execute(THD*) (sql_prepare.cc:2737) ==9735== by 0x610D0F: mysql_execute_command(THD*) (sql_parse.cc:2244) ==9735== by 0x61A64F: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:5909) ==9735== by 0x60E218: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1079) ==9735== by 0x60D3A1: do_command(THD*) (sql_parse.cc:793) ==9735== by 0x71597E: do_handle_one_connection(THD*) (sql_connect.cc:1269) ==9735== by 0x7156F8: handle_one_connection (sql_connect.cc:1185) ==9735== Address 0x88f6598 is 40 bytes inside a block of size 48 free'd ==9735== at 0x4A0662E: free (vg_replace_malloc.c:366) ==9735== by 0xCD4209: my_free (my_malloc.c:119) ==9735== by 0xCC5B81: free_root (my_alloc.c:366) ==9735== by 0x60F766: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1493) ==9735== by 0x60D3A1: do_command(THD*) (sql_parse.cc:793) ==9735== by 0x71597E: do_handle_one_connection(THD*) (sql_connect.cc:1269) ==9735== by 0x7156F8: handle_one_connection (sql_connect.cc:1185) ==9735== by 0xC165CA: pfs_spawn_thread (pfs.cc:1015) ==9735== by 0x3509C07D8F: start_thread (pthread_create.c:309) ==9735== by 0x35098F0F5C: clone (clone.S:115) ==9735==

            Discussed with sanja.

            Rough idea of what happens:

            PREPARE stmt FROM 'UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM t3 )';

            For the subquery #2, select_lex->prep_leaf_list_state
            changes from UNINIT to READY.

            The query has thd->save_prep_leaf_list= FALSE, which
            causes LEX::save_prep_leaf_tables() to do nothing.

            UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM v3 );

            This changes thd->save_prep_leaf_list from FALSE to TRUE.

            This is done here: mysql_derived_merge:

             if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
                 thd->lex->sql_command == SQLCOM_DELETE_MULTI)
               thd->save_prep_leaf_list= TRUE;

            and the value is never restored back.

            EXECUTE stmt;

            Here, we attempt to use select_lex::leaf_tables and walk over freed memory.

            The first suspect is save_prep_leaf_list. Why does UPDATE change it and never puts it back? This looks like a bug.

            psergei Sergei Petrunia added a comment - Discussed with sanja . Rough idea of what happens: PREPARE stmt FROM 'UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM t3 )'; For the subquery #2, select_lex->prep_leaf_list_state changes from UNINIT to READY. The query has thd->save_prep_leaf_list= FALSE, which causes LEX::save_prep_leaf_tables() to do nothing. UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM v3 ); This changes thd->save_prep_leaf_list from FALSE to TRUE. This is done here: mysql_derived_merge: if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || thd->lex->sql_command == SQLCOM_DELETE_MULTI) thd->save_prep_leaf_list= TRUE; and the value is never restored back. EXECUTE stmt; Here, we attempt to use select_lex::leaf_tables and walk over freed memory. The first suspect is save_prep_leaf_list . Why does UPDATE change it and never puts it back? This looks like a bug.

            save_prep_leaf_list was introduced by 56eb6d7e69ecce856e2d54e2404157407cb7203b,

            Committer: Igor Babaev <igor@askmonty.org> Tue Jun 14 05:03:03 2011

            Fixed LP bug #794890.
            Changed the code that processing of multi-updates and multi-deletes
            with multitable views at the prepare stage.

            psergei Sergei Petrunia added a comment - save_prep_leaf_list was introduced by 56eb6d7e69ecce856e2d54e2404157407cb7203b , Committer: Igor Babaev <igor@askmonty.org> Tue Jun 14 05:03:03 2011 Fixed LP bug #794890. Changed the code that processing of multi-updates and multi-deletes with multitable views at the prepare stage.
            psergei Sergei Petrunia added a comment - http://lists.askmonty.org/pipermail/commits/2015-July/008211.html

            People

              psergei Sergei Petrunia
              elenst Elena Stepanova
              Votes:
              0 Vote for this issue
              Watchers:
              2 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.