maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #09916
MDEV-10702 Crash in SET STATEMENT FOR EXECUTE
Hello Sergei,
Please review a patch for mdev-10702.diff
Thanks!
diff --git a/mysql-test/r/ps_ddl.result b/mysql-test/r/ps_ddl.result
index dec0d12..fc18322 100644
--- a/mysql-test/r/ps_ddl.result
+++ b/mysql-test/r/ps_ddl.result
@@ -2542,3 +2542,32 @@ EXECUTE stmt3;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
DROP TEMPORARY TABLES tm, t1;
+#
+# Start of 10.1 tests
+#
+#
+# MDEV-10702 Crash in SET STATEMENT FOR EXECUTE
+#
+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;
+a
+2048
+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;
+SELECT * FROM t1;
+a
+2048
+1025
+DROP TRIGGER tr1;
+SET STATEMENT max_sort_length=2048 FOR EXECUTE stmt;
+SELECT * FROM t1;
+a
+2048
+1025
+1024
+DROP TABLE t1;
+#
+# End of 10.1 tests
+#
diff --git a/mysql-test/t/ps_ddl.test b/mysql-test/t/ps_ddl.test
index 21355ca..90226d3 100644
--- a/mysql-test/t/ps_ddl.test
+++ b/mysql-test/t/ps_ddl.test
@@ -2259,3 +2259,27 @@ EXECUTE stmt3;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
DROP TEMPORARY TABLES tm, t1;
+
+--echo #
+--echo # Start of 10.1 tests
+--echo #
+
+--echo #
+--echo # MDEV-10702 Crash in SET STATEMENT FOR EXECUTE
+--echo #
+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;
+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;
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+SET STATEMENT max_sort_length=2048 FOR EXECUTE stmt;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of 10.1 tests
+--echo #
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 0db1daa..c0d5460 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -3030,7 +3030,30 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt));
+ /*
+ thd->free_list can already have some Items,
+ e.g. for a query like this:
+ SET STATEMENT max_sort_length=2048 FOR EXECUTE stmt;
+ thd->free_list contains a pointer to Item_int corresponding to 2048.
+
+ If Prepared_statement::execute() notices that the table metadata for "t1"
+ has changed since PREPARE, it returns an error asking the calling
+ Prepared_statement::execute_loop() to re-prepare the statement.
+ Before returning the error, Prepared_statement::execute()
+ calls Prepared_statement::cleanup_stmt(),
+ which calls thd->cleanup_after_query(),
+ which calls Query_arena::free_items().
+
+ We hide Items created while parsing the "SET STATEMENT" part of the query,
+ so they don't get freed before re-prepare.
+ See MDEV-10702 Crash in SET STATEMENT FOR EXECUTE
+ */
+ Item *free_list_backup= thd->free_list;
+ thd->free_list= NULL;
(void) stmt->execute_loop(&expanded_query, FALSE, NULL, NULL);
+ thd->free_list= free_list_backup;
+ thd->free_items(); // Now it's OK to free the "SET STATEMENT" Items.
+
stmt->lex->restore_set_statement_var();
DBUG_VOID_RETURN;
}