mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 02:30:06 +01:00
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.
This commit is contained in:
parent
c9851d35ad
commit
b378ddb3d3
4 changed files with 38 additions and 6 deletions
|
@ -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;
|
||||||
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;
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
|
|
Loading…
Add table
Reference in a new issue