Commit b378ddb3 authored by Michael Widenius's avatar Michael Widenius

MDEV 22785 Crash with prepared statements and NEXTVAL()

The problem was that a PREARE followed by a non prepared statement
using DEFAULT NEXT_VALUE() could change table->next_local to point to
a not persitent memory aria. The next EXECUTE would then try to use
the wrong pointer, which could cause a crash.
Fixed by reseting the pointer to it's old value when doing EXECUTE.
parent c9851d35
...@@ -211,7 +211,7 @@ fi ...@@ -211,7 +211,7 @@ fi
max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max" max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max"
max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache" max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache"
max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent --without-plugin=plugin_file_key_management --with-plugin-rocksdb=dynamic --with-plugin-test_sql_discovery=DYNAMIC" max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent --without-plugin=plugin_file_key_management --with-plugin-rocksdb=dynamic --without-plugin-tokudb --with-plugin-test_sql_discovery=DYNAMIC"
all_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-innodb_plugin --with-libevent" all_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-innodb_plugin --with-libevent"
# #
......
...@@ -185,3 +185,13 @@ ALTER TABLE t1 add column d int default next value for s_not_exits; ...@@ -185,3 +185,13 @@ ALTER TABLE t1 add column d int default next value for s_not_exits;
ERROR 42S02: Table 'test.s_not_exits' doesn't exist ERROR 42S02: Table 'test.s_not_exits' doesn't exist
drop table t1; drop table t1;
drop sequence s1; drop sequence s1;
#
# MDEV 22785 Crash with prepared statements and NEXTVAL()
#
CREATE SEQUENCE s;
CREATE TABLE t1 (id int NOT NULL DEFAULT NEXTVAL(s), PRIMARY KEY (id));
PREPARE stmt FROM " INSERT INTO t1 () values ()";
INSERT INTO t1 () values ();
EXECUTE stmt;
DROP TABLE t1;
DROP SEQUENCE s;
...@@ -123,3 +123,15 @@ ALTER TABLE t1 add column c int; ...@@ -123,3 +123,15 @@ ALTER TABLE t1 add column c int;
ALTER TABLE t1 add column d int default next value for s_not_exits; ALTER TABLE t1 add column d int default next value for s_not_exits;
drop table t1; drop table t1;
drop sequence s1; drop sequence s1;
--echo #
--echo # MDEV 22785 Crash with prepared statements and NEXTVAL()
--echo #
CREATE SEQUENCE s;
CREATE TABLE t1 (id int NOT NULL DEFAULT NEXTVAL(s), PRIMARY KEY (id));
PREPARE stmt FROM " INSERT INTO t1 () values ()";
INSERT INTO t1 () values ();
EXECUTE stmt;
# Cleanup
DROP TABLE t1;
DROP SEQUENCE s;
...@@ -4450,13 +4450,13 @@ bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db, ...@@ -4450,13 +4450,13 @@ bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db,
} }
static bool internal_table_exists(TABLE_LIST *global_list, static TABLE_LIST *internal_table_exists(TABLE_LIST *global_list,
const char *table_name) const char *table_name)
{ {
do do
{ {
if (global_list->table_name.str == table_name) if (global_list->table_name.str == table_name)
return 1; return global_list;
} while ((global_list= global_list->next_global)); } while ((global_list= global_list->next_global));
return 0; return 0;
} }
...@@ -4471,13 +4471,23 @@ add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx, ...@@ -4471,13 +4471,23 @@ add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx,
do do
{ {
TABLE_LIST *tmp __attribute__((unused));
DBUG_PRINT("info", ("table name: %s", tables->table_name.str)); DBUG_PRINT("info", ("table name: %s", tables->table_name.str));
/* /*
Skip table if already in the list. Can happen with prepared statements Skip table if already in the list. Can happen with prepared statements
*/ */
if (tables->next_local && if ((tmp= internal_table_exists(global_table_list,
internal_table_exists(global_table_list, tables->table_name.str)) tables->table_name.str)))
{
/*
Use the original value for the next local, used by the
original prepared statement. We cannot trust the original
next_local value as it may have been changed by a previous
statement using the same table.
*/
tables->next_local= tmp;
continue; continue;
}
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST)); TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
if (!tl) if (!tl)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment