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

Crash in SET STATEMENT FOR EXECUTE

    XMLWordPrintable

    Details

      Description

      I create a table and insert some data using PREPARE followed by SET STATEMENT..EXECUTE

      DROP TABLE IF EXISTS t1;
      CREATE TABLE t1 (a INT);
      PREPARE stmt FROM 'INSERT INTO t1 VALUES (@@max_sort_length)';
      SET STATEMENT max_sort_length=2048 FOR EXECUTE stmt;
      SELECT * FROM t1;
      

      Now I add a trigger on the table and re-execute the same SET STATEMENT..EXECUTE:

      CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=NEW.a + 1;
      SET STATEMENT max_sort_length=2048 FOR EXECUTE stmt;
      

      It crashes on assert:

      #3  0x00007ffff57e62d2 in __GI___assert_fail (
          assertion=0x55555642c1d8 "thd->free_list == free_list_state", 
          file=0x55555642b9c8 "/home/bar/maria-git/server-10.1/sql/sql_prepare.cc", 
          line=3885, 
          function=0x55555642c8e0 <Prepared_statement::execute_loop(String*, bool, unsigned char*, unsigned char*)::__PRETTY_FUNCTION__> "bool Prepared_statement::execute_loop(String*, bool, uchar*, uchar*)") at assert.c:101
      #4  0x0000555555a70637 in Prepared_statement::execute_loop (
          this=0x7ffece5dc870, expanded_query=0x7ffff7f78960, open_cursor=false, 
          packet=0x0, packet_end=0x0)
          at /home/bar/maria-git/server-10.1/sql/sql_prepare.cc:3885
      #5  0x0000555555a6e799 in mysql_sql_stmt_execute (thd=0x7ffed7e4c070)
          at /home/bar/maria-git/server-10.1/sql/sql_prepare.cc:3033
      

      There is a problem in Prepared_statement::execute_loop:

      1. The call for Prepared_statement::execute() notices that t1's metadata has changed and returns an error. Before returning, it calls Prepared_statement::cleanup_stmt(), which includes a call for thd->cleanup_after_query() which calls Query_arena::free_items(). Therefore, all items created while parsing in the variable initialization part of SET STATEMENT, e.g. Item_int corresponding to 2048, are freed and thd->free_list changes to NULL.
      2. Prepared_statement::execute_loop() calls reprepare() and jumps to the label reexecute.
      3. This assert fails:

      DBUG_ASSERT(thd->free_list == free_list_state);
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              bar Alexander Barkov
              Reporter:
              bar Alexander Barkov
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: