Details

    Description

      Conjunction of cursor and "goto" statement in stored procedure cause crash with stack:
      sql/sp_rcontext.cc:452(sp_rcontext::pop_cursor(THD*))[0x55e353c86a13]
      sql/sp_head.cc:4288(sp_instr_cpop::execute(THD*, unsigned int*))[0x55e353c7755b]
      sql/sp_head.cc:1350(sp_head::execute(THD*, bool))[0x55e353c7b421]
      sql/sp_head.cc:2288(sp_head::execute_procedure(THD*, List<Item>*))[0x55e353c7c5d7]
      sql/sql_parse.cc:3022(do_execute_sp(THD*, sp_head*))[0x55e353cff46f]
      sql/sql_parse.cc:3261(Sql_cmd_call::execute(THD*))[0x55e353d00ba6]
      sql/sql_parse.cc:3272(Sql_cmd_call::execute(THD*))[0x55e353d013a7]
      sql/sql_parse.cc:6099(mysql_execute_command(THD*))[0x55e353d0a30e]
      sql/sp_head.cc:3607(sp_instr_stmt::exec_core(THD*, unsigned int*))[0x55e353c78e84]
      sql/sp_head.cc:3343(sp_lex_keeper::reset_lex_and_exec_core(THD*, unsigned int*, bool, sp_instr*))[0x55e353c7f434]
      sql/sp_head.cc:3514(sp_instr_stmt::execute(THD*, unsigned int*))[0x55e353c7fe59]
      sql/sp_head.cc:1350(sp_head::execute(THD*, bool))[0x55e353c7b421]
      sql/sp_head.cc:2288(sp_head::execute_procedure(THD*, List<Item>*))[0x55e353c7c5d7]
      sql/sql_parse.cc:3022(do_execute_sp(THD*, sp_head*))[0x55e353cff46f]
      sql/sql_parse.cc:5711(mysql_execute_command(THD*))[0x55e353d0852c]
      sql/sql_parse.cc:7910(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x55e353d10112]
      sql/sql_parse.cc:1907(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x55e353d12ed9]
      sql/sql_parse.cc:1360(do_command(THD*))[0x55e353d1473c]
      sql/sql_connect.cc:1412(do_handle_one_connection(CONNECT*))[0x55e353de44f4]
      sql/sql_connect.cc:1318(handle_one_connection)[0x55e353de45d4]
      perfschema/pfs.cc:1865(pfs_spawn_thread)[0x55e354398534]

      Attachments

        Activity

          alice Alice Sherepa added a comment - - edited

          Thanks a lot! Reproduced on debug version 10.3-10.4:

          CREATE TABLE t1 ( a varchar(6));
          delimiter //;
          set sql_mode=oracle;
           
          CREATE PROCEDURE sp1() IS 
          BEGIN 
          IF 1=2 THEN 
          BEGIN 
          	DECLARE CURSOR cur1 IS SELECT a FROM t1 ; 
          	BEGIN GOTO iac_err; END; 
          END; 
          END IF; 
           
          IF 1=1 THEN GOTO iac_err; END IF; 
          << iac_err >> RETURN ; 
          END//
           
          delimiter ;//
          call sp1();
          

          10.3 b6bb64e54a3e34a20cda3

          /git/10.3/sql/sp_rcontext.cc:445: void sp_rcontext::pop_cursors(THD*, size_t): Assertion `m_ccount >= count' failed.
           
          #3  <signal handler called>
          #4  0x00007ff1e8292428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
          #5  0x00007ff1e829402a in __GI_abort () at abort.c:89
          #6  0x00007ff1e828abd7 in __assert_fail_base (fmt=<optimized out>, assertion=assertion@entry=0x563a05eee5fd "m_ccount >= count", file=file@entry=0x563a05eee528 "/10.3/sql/sp_rcontext.cc", line=line@entry=445, function=function@entry=0x563a05eef060 <sp_rcontext::pop_cursors(THD*, unsigned long)::__PRETTY_FUNCTION__> "void sp_rcontext::pop_cursors(THD*, size_t)") at assert.c:92
          #7  0x00007ff1e828ac82 in __GI___assert_fail (assertion=0x563a05eee5fd "m_ccount >= count", file=0x563a05eee528 "/10.3/sql/sp_rcontext.cc", line=445, function=0x563a05eef060 <sp_rcontext::pop_cursors(THD*, unsigned long)::__PRETTY_FUNCTION__> "void sp_rcontext::pop_cursors(THD*, size_t)") at assert.c:101
          #8  0x0000563a051d9426 in sp_rcontext::pop_cursors (this=0x7ff198013000, thd=0x7ff198000b00, count=1) at /10.3/sql/sp_rcontext.cc:445
          #9  0x0000563a051caf49 in sp_instr_cpop::execute (this=0x7ff19806d6b0, thd=0x7ff198000b00, nextp=0x7ff1e18f8054) at /10.3/sql/sp_head.cc:4233
          #10 0x0000563a051c2b48 in sp_head::execute (this=0x7ff1980a30a8, thd=0x7ff198000b00, merge_da_on_success=true) at /10.3/sql/sp_head.cc:1356
          #11 0x0000563a051c5674 in sp_head::execute_procedure (this=0x7ff1980a30a8, thd=0x7ff198000b00, args=0x7ff198005780) at /10.3/sql/sp_head.cc:2296
          #12 0x0000563a052a51b2 in do_execute_sp (thd=0x7ff198000b00, sp=0x7ff1980a30a8) at /10.3/sql/sql_parse.cc:2991
          #13 0x0000563a052a5e24 in Sql_cmd_call::execute (this=0x7ff1980128f0, thd=0x7ff198000b00) at /10.3/sql/sql_parse.cc:3231
          #14 0x0000563a052afb9e in mysql_execute_command (thd=0x7ff198000b00) at /10.3/sql/sql_parse.cc:6023
          #15 0x0000563a052b532a in mysql_parse (thd=0x7ff198000b00, rawbuf=0x7ff198012818 "call pssgnumnew()", length=17, parser_state=0x7ff1e18f9460, is_com_multi=false, is_next_command=false) at /10.3/sql/sql_parse.cc:7829
          #16 0x0000563a052a1efd in dispatch_command (command=COM_QUERY, thd=0x7ff198000b00, packet=0x7ff19815fe11 "call pssgnumnew()", packet_length=17, is_com_multi=false, is_next_command=false) at /10.3/sql/sql_parse.cc:1855
          #17 0x0000563a052a080b in do_command (thd=0x7ff198000b00) at /10.3/sql/sql_parse.cc:1401
          #18 0x0000563a054182e2 in do_handle_one_connection (connect=0x563a0854e6e0) at /10.3/sql/sql_connect.cc:1403
          #19 0x0000563a0541801e in handle_one_connection (arg=0x563a0854e6e0) at /10.3/sql/sql_connect.cc:1308
          #20 0x0000563a05dc5390 in pfs_spawn_thread (arg=0x563a08498eb0) at /10.3/storage/perfschema/pfs.cc:1862
          #21 0x00007ff1e8ecf6ba in start_thread (arg=0x7ff1e18fa700) at pthread_create.c:333
          #22 0x00007ff1e836441d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
          

          alice Alice Sherepa added a comment - - edited Thanks a lot! Reproduced on debug version 10.3-10.4: CREATE TABLE t1 ( a varchar (6)); delimiter //; set sql_mode=oracle;   CREATE PROCEDURE sp1() IS BEGIN IF 1=2 THEN BEGIN DECLARE CURSOR cur1 IS SELECT a FROM t1 ; BEGIN GOTO iac_err; END ; END ; END IF ;   IF 1=1 THEN GOTO iac_err; END IF ; << iac_err >> RETURN ; END //   delimiter ;// call sp1(); 10.3 b6bb64e54a3e34a20cda3 /git/10.3/sql/sp_rcontext.cc:445: void sp_rcontext::pop_cursors(THD*, size_t): Assertion `m_ccount >= count' failed.   #3 <signal handler called> #4 0x00007ff1e8292428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54 #5 0x00007ff1e829402a in __GI_abort () at abort.c:89 #6 0x00007ff1e828abd7 in __assert_fail_base (fmt=<optimized out>, assertion=assertion@entry=0x563a05eee5fd "m_ccount >= count", file=file@entry=0x563a05eee528 "/10.3/sql/sp_rcontext.cc", line=line@entry=445, function=function@entry=0x563a05eef060 <sp_rcontext::pop_cursors(THD*, unsigned long)::__PRETTY_FUNCTION__> "void sp_rcontext::pop_cursors(THD*, size_t)") at assert.c:92 #7 0x00007ff1e828ac82 in __GI___assert_fail (assertion=0x563a05eee5fd "m_ccount >= count", file=0x563a05eee528 "/10.3/sql/sp_rcontext.cc", line=445, function=0x563a05eef060 <sp_rcontext::pop_cursors(THD*, unsigned long)::__PRETTY_FUNCTION__> "void sp_rcontext::pop_cursors(THD*, size_t)") at assert.c:101 #8 0x0000563a051d9426 in sp_rcontext::pop_cursors (this=0x7ff198013000, thd=0x7ff198000b00, count=1) at /10.3/sql/sp_rcontext.cc:445 #9 0x0000563a051caf49 in sp_instr_cpop::execute (this=0x7ff19806d6b0, thd=0x7ff198000b00, nextp=0x7ff1e18f8054) at /10.3/sql/sp_head.cc:4233 #10 0x0000563a051c2b48 in sp_head::execute (this=0x7ff1980a30a8, thd=0x7ff198000b00, merge_da_on_success=true) at /10.3/sql/sp_head.cc:1356 #11 0x0000563a051c5674 in sp_head::execute_procedure (this=0x7ff1980a30a8, thd=0x7ff198000b00, args=0x7ff198005780) at /10.3/sql/sp_head.cc:2296 #12 0x0000563a052a51b2 in do_execute_sp (thd=0x7ff198000b00, sp=0x7ff1980a30a8) at /10.3/sql/sql_parse.cc:2991 #13 0x0000563a052a5e24 in Sql_cmd_call::execute (this=0x7ff1980128f0, thd=0x7ff198000b00) at /10.3/sql/sql_parse.cc:3231 #14 0x0000563a052afb9e in mysql_execute_command (thd=0x7ff198000b00) at /10.3/sql/sql_parse.cc:6023 #15 0x0000563a052b532a in mysql_parse (thd=0x7ff198000b00, rawbuf=0x7ff198012818 "call pssgnumnew()", length=17, parser_state=0x7ff1e18f9460, is_com_multi=false, is_next_command=false) at /10.3/sql/sql_parse.cc:7829 #16 0x0000563a052a1efd in dispatch_command (command=COM_QUERY, thd=0x7ff198000b00, packet=0x7ff19815fe11 "call pssgnumnew()", packet_length=17, is_com_multi=false, is_next_command=false) at /10.3/sql/sql_parse.cc:1855 #17 0x0000563a052a080b in do_command (thd=0x7ff198000b00) at /10.3/sql/sql_parse.cc:1401 #18 0x0000563a054182e2 in do_handle_one_connection (connect=0x563a0854e6e0) at /10.3/sql/sql_connect.cc:1403 #19 0x0000563a0541801e in handle_one_connection (arg=0x563a0854e6e0) at /10.3/sql/sql_connect.cc:1308 #20 0x0000563a05dc5390 in pfs_spawn_thread (arg=0x563a08498eb0) at /10.3/storage/perfschema/pfs.cc:1862 #21 0x00007ff1e8ecf6ba in start_thread (arg=0x7ff1e18fa700) at pthread_create.c:333 #22 0x00007ff1e836441d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
          bar Alexander Barkov added a comment - - edited

          DROP PROCEDURE p1;
          DELIMITER //
          set sql_mode=oracle;
          CREATE PROCEDURE p1() IS 
            BEGIN 
              IF 1=2 THEN 
                BEGIN 
                  DECLARE
                    CURSOR cur1 IS SELECT a FROM t1 ; 
                  BEGIN
                    GOTO iac_err;
                  END;
                END;
              END IF; 
              IF 1=1 THEN GOTO iac_err; END IF; 
          << iac_err >>
            RETURN ; 
          END//
          DELIMITER ;
          SHOW PROCEDURE CODE p1;
          CALL p1;
          

          also crashes. Befor the crash, it prints the following procedure code:

          +-----+------------------------+
          | Pos | Instruction            |
          +-----+------------------------+
          |   0 | jump_if_not 5(5) 1 = 2 |
          |   1 | cpush cur1@0           |
          |   2 | jump 3                 |
          |   3 | cpop 1                 |
          |   4 | jump 8                 |
          |   5 | jump_if_not 8(8) 1 = 1 |
          |   6 | cpop 1                 |
          |   7 | jump 8                 |
          |   8 | preturn                |
          +-----+------------------------+
          

          The above code is wrong. The execution goes this way:

          • jump_if_not at position 0 jumps to 5
          • jump_if_not at position 5 does not jump
          • the cpop at position 6 does not have any cursors on the stack, hence the crash.

          It seems the cpop at position 6 should not be there.

          bar Alexander Barkov added a comment - - edited DROP PROCEDURE p1; DELIMITER // set sql_mode=oracle; CREATE PROCEDURE p1() IS BEGIN IF 1=2 THEN BEGIN DECLARE CURSOR cur1 IS SELECT a FROM t1 ; BEGIN GOTO iac_err; END ; END ; END IF ; IF 1=1 THEN GOTO iac_err; END IF ; << iac_err >> RETURN ; END // DELIMITER ; SHOW PROCEDURE CODE p1; CALL p1; also crashes. Befor the crash, it prints the following procedure code: +-----+------------------------+ | Pos | Instruction | +-----+------------------------+ | 0 | jump_if_not 5(5) 1 = 2 | | 1 | cpush cur1@0 | | 2 | jump 3 | | 3 | cpop 1 | | 4 | jump 8 | | 5 | jump_if_not 8(8) 1 = 1 | | 6 | cpop 1 | | 7 | jump 8 | | 8 | preturn | +-----+------------------------+ The above code is wrong. The execution goes this way: jump_if_not at position 0 jumps to 5 jump_if_not at position 5 does not jump the cpop at position 6 does not have any cursors on the stack, hence the crash. It seems the cpop at position 6 should not be there.

          The same problem is repeatable with this script, with an unconditional GOTO jump at the end:

          DROP PROCEDURE p1;
          DELIMITER //
          set sql_mode=oracle;
          CREATE PROCEDURE p1() IS 
            BEGIN 
              IF 1=2 THEN 
                BEGIN 
                  DECLARE
                    CURSOR cur1 IS SELECT a FROM t1 ; 
                  BEGIN
                    GOTO iac_err;
                  END;
                END;
              END IF; 
              GOTO iac_err;
          << iac_err >>
            RETURN ; 
          END//
          DELIMITER ;
          SHOW PROCEDURE CODE p1;
          

          +-----+------------------------+
          | Pos | Instruction            |
          +-----+------------------------+
          |   0 | jump_if_not 5(5) 1 = 2 |
          |   1 | cpush cur1@0           |
          |   2 | jump 3                 |
          |   3 | cpop 1                 |
          |   4 | jump 6                 |
          |   5 | cpop 1                 |
          |   6 | preturn                |
          +-----+------------------------+
          

          Notice, the cpop at position 5 looks wrong.

          bar Alexander Barkov added a comment - The same problem is repeatable with this script, with an unconditional GOTO jump at the end: DROP PROCEDURE p1; DELIMITER // set sql_mode=oracle; CREATE PROCEDURE p1() IS BEGIN IF 1=2 THEN BEGIN DECLARE CURSOR cur1 IS SELECT a FROM t1 ; BEGIN GOTO iac_err; END ; END ; END IF ; GOTO iac_err; << iac_err >> RETURN ; END // DELIMITER ; SHOW PROCEDURE CODE p1; +-----+------------------------+ | Pos | Instruction | +-----+------------------------+ | 0 | jump_if_not 5(5) 1 = 2 | | 1 | cpush cur1@0 | | 2 | jump 3 | | 3 | cpop 1 | | 4 | jump 6 | | 5 | cpop 1 | | 6 | preturn | +-----+------------------------+ Notice, the cpop at position 5 looks wrong.
          bar Alexander Barkov added a comment - - edited

          A similar crash happens with handlers instead of cursors:

          SET sql_mode=ORACLE;
          DROP PROCEDURE p1;
          DELIMITER //
          CREATE PROCEDURE p1() IS 
          BEGIN 
            IF 1=2 THEN 
              BEGIN 
                DECLARE
                  CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
                BEGIN
                  GOTO iac_err;
                END; 
              END; 
            END IF; 
            IF 1=1 THEN
              GOTO iac_err;
            END IF; 
          <<iac_err >>
            RETURN; 
          END//
          DELIMITER ;
          CALL p1;
          

          sp_rcontext.cc:459: void sp_rcontext::pop_handlers(size_t): Assertion `m_handlers.elements() >= count' failed.
          

          SHOW PROCEDURE CODE p1 displays this output:

          +-----+--------------------------+
          | Pos | Instruction              |
          +-----+--------------------------+
          |   0 | jump_if_not 9(9) 1 = 2   |
          |   1 | hpush_jump 4 0 CONTINUE  |
          |   2 | stmt 31 "SET @x2 = 1"    |
          |   3 | hreturn 0                |
          |   4 | hpop 1                   |
          |   5 | jump 12                  |
          |   6 | jump 12                  |
          |   7 | hpop 1                   |
          |   8 | jump 9                   |
          |   9 | jump_if_not 12(12) 1 = 1 |
          |  10 | hpop 1                   |
          |  11 | jump 12                  |
          |  12 | preturn                  |
          +-----+--------------------------+
          

          The hpop on the 10th position does not have any corresponding hpush commands, hence the crash.

          bar Alexander Barkov added a comment - - edited A similar crash happens with handlers instead of cursors: SET sql_mode=ORACLE; DROP PROCEDURE p1; DELIMITER // CREATE PROCEDURE p1() IS BEGIN IF 1=2 THEN BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1; BEGIN GOTO iac_err; END ; END ; END IF ; IF 1=1 THEN GOTO iac_err; END IF ; <<iac_err >> RETURN ; END // DELIMITER ; CALL p1; sp_rcontext.cc:459: void sp_rcontext::pop_handlers(size_t): Assertion `m_handlers.elements() >= count' failed. SHOW PROCEDURE CODE p1 displays this output: +-----+--------------------------+ | Pos | Instruction | +-----+--------------------------+ | 0 | jump_if_not 9(9) 1 = 2 | | 1 | hpush_jump 4 0 CONTINUE | | 2 | stmt 31 "SET @x2 = 1" | | 3 | hreturn 0 | | 4 | hpop 1 | | 5 | jump 12 | | 6 | jump 12 | | 7 | hpop 1 | | 8 | jump 9 | | 9 | jump_if_not 12(12) 1 = 1 | | 10 | hpop 1 | | 11 | jump 12 | | 12 | preturn | +-----+--------------------------+ The hpop on the 10th position does not have any corresponding hpush commands, hence the crash.
          bar Alexander Barkov added a comment - Hi Varun, Can you please review a fix for MDEV-20667 ? https://github.com/MariaDB/server/commit/599b92768b57a514360280dbdf810e7e3c985dec Thanks!

          People

            bar Alexander Barkov
            halfspawn Jérôme Brauge
            Votes:
            0 Vote for this issue
            Watchers:
            4 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.