[Commits] aa9bd40: MDEV-10824 - Crash in CREATE OR REPLACE TABLE t1 AS SELECT spfunc()

Sergey Vojtovich svoj at mariadb.org
Mon Oct 24 14:47:26 EEST 2016


revision-id: aa9bd40f8067e1421ad71d2ada367544a6db78ca (mariadb-10.0.27-8-gaa9bd40)
parent(s): 4dfb6a3f54cfb26535636197cc5fa70fe5bacc2e
committer: Sergey Vojtovich
timestamp: 2016-10-24 15:26:11 +0400
message:

MDEV-10824 - Crash in CREATE OR REPLACE TABLE t1 AS SELECT spfunc()

Code flow hit incorrect branch while closing table instances before removal.
This branch expects thread to hold open table instance, whereas CREATE OR
REPLACE doesn't actually hold open table instance.

Before CREATE OR REPLACE TABLE it was impossible to hit this condition in
LTM_PRELOCKED mode, thus the problem didn't expose itself during DROP TABLE
or DROP DATABASE.

Fixed by adjusting condition to take into account LTM_PRELOCKED mode, which can
be set during CREATE OR REPLACE TABLE.

---
 mysql-test/r/create_or_replace.result | 11 +++++++++++
 mysql-test/t/AAA.test                 | 24 ++++++++++++++++++++++++
 mysql-test/t/create_or_replace.test   | 12 ++++++++++++
 sql/sql_parse.cc                      | 12 ------------
 sql/sql_table.cc                      |  3 ++-
 5 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/mysql-test/r/create_or_replace.result b/mysql-test/r/create_or_replace.result
index 3a894e9..a43dc2e 100644
--- a/mysql-test/r/create_or_replace.result
+++ b/mysql-test/r/create_or_replace.result
@@ -442,3 +442,14 @@ KILL QUERY con_id;
 ERROR 70100: Query execution was interrupted
 drop table t1;
 DROP TABLE t2;
+#
+# MDEV-10824 - Crash in CREATE OR REPLACE TABLE t1 AS SELECT spfunc()
+#
+CREATE TABLE t1(a INT);
+CREATE FUNCTION f1() RETURNS VARCHAR(16383) RETURN 'test';
+CREATE OR REPLACE TABLE t1 AS SELECT f1();
+LOCK TABLE t1 WRITE;
+CREATE OR REPLACE TABLE t1 AS SELECT f1();
+UNLOCK TABLES;
+DROP FUNCTION f1;
+DROP TABLE t1;
diff --git a/mysql-test/t/AAA.test b/mysql-test/t/AAA.test
new file mode 100644
index 0000000..22e22dd
--- /dev/null
+++ b/mysql-test/t/AAA.test
@@ -0,0 +1,24 @@
+CREATE TABLE t1(a INT);
+DELIMITER $$;
+CREATE FUNCTION f2() RETURNS VARCHAR(16383) RETURN 'test';
+CREATE FUNCTION f1() RETURNS VARCHAR(16383)
+BEGIN
+  INSERT INTO t1 VALUES(1);
+  RETURN 'test';
+END;
+$$
+CREATE PROCEDURE p1() CREATE OR REPLACE TABLE t1 AS SELECT f2();
+$$
+DELIMITER ;$$
+
+CALL p1;
+
+#CREATE OR REPLACE TABLE t1 AS SELECT f1();
+LOCK TABLE t1 WRITE;
+#CREATE OR REPLACE TABLE t1 AS SELECT f1();
+UNLOCK TABLES;
+
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
diff --git a/mysql-test/t/create_or_replace.test b/mysql-test/t/create_or_replace.test
index 7bba2b3..b37417f 100644
--- a/mysql-test/t/create_or_replace.test
+++ b/mysql-test/t/create_or_replace.test
@@ -386,3 +386,15 @@ drop table t1;
 # Cleanup
 #
 DROP TABLE t2;
+
+--echo #
+--echo # MDEV-10824 - Crash in CREATE OR REPLACE TABLE t1 AS SELECT spfunc()
+--echo #
+CREATE TABLE t1(a INT);
+CREATE FUNCTION f1() RETURNS VARCHAR(16383) RETURN 'test';
+CREATE OR REPLACE TABLE t1 AS SELECT f1();
+LOCK TABLE t1 WRITE;
+CREATE OR REPLACE TABLE t1 AS SELECT f1();
+UNLOCK TABLES;
+DROP FUNCTION f1;
+DROP TABLE t1;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index cbf723c..70511fc 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2858,12 +2858,6 @@ case SQLCOM_PREPARE:
     }
 
     /*
-      For CREATE TABLE we should not open the table even if it exists.
-      If the table exists, we should either not create it or replace it
-    */
-    lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
-
-    /*
       If we are a slave, we should add OR REPLACE if we don't have
       IF EXISTS. This will help a slave to recover from
       CREATE TABLE OR EXISTS failures by dropping the table and
@@ -8225,12 +8219,6 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
   if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info, create_table->db))
     goto err;
 
-  /*
-    For CREATE TABLE we should not open the table even if it exists.
-    If the table exists, we should either not create it or replace it
-  */
-  lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
-
   error= FALSE;
 
 err:
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 7cf31ee..050a338 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2464,7 +2464,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
       if (table_type && table_type != view_pseudo_hton)
         ha_lock_engine(thd, table_type);
 
-      if (thd->locked_tables_mode)
+      if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
+          thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)
       {
         if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED))
         {


More information about the commits mailing list