[MDEV-10702] Crash in SET STATEMENT FOR EXECUTE Created: 2016-08-30  Updated: 2018-08-31  Resolved: 2016-09-09

Status: Closed
Project: MariaDB Server
Component/s: Prepared Statements
Affects Version/s: 10.1, 10.2
Fix Version/s: 10.1.18, 10.2.2

Type: Bug Priority: Major
Reporter: Alexander Barkov Assignee: Alexander Barkov
Resolution: Fixed Votes: 0
Labels: Compatibility

Issue Links:
Blocks
blocks MDEV-10709 Expressions as parameters to Dynamic SQL Closed

 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);



 Comments   
Comment by Michael Widenius [ 2016-09-08 ]

Review done. Found some small issues that was fixed and reviewed again.

Generated at Thu Feb 08 07:44:16 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.