Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
5.5(EOL), 10.0(EOL), 10.1(EOL), 10.2(EOL), 10.3(EOL), 10.4(EOL), 10.5
-
None
Description
create table t1 (id int); |
insert into t1 values (1),(2),(1); #not important for the test |
|
create table t2 (pk int, c0 int) ; |
create view v2 as select * from t2; |
insert into t2 values (1,-1); #not important for the test |
|
create procedure sp1() update (t1 join v2 on v2.c0 = t1.c1) set v2.pk = 1; #--there is no column c1 in t1 |
|
--error 1054
|
call sp1;
|
call sp1;
|
crash on debug/non-debug builds, with MyIsam/InnoDB
10.2 afc5bac49d48b6fd13d |
210209 15:29:54 [ERROR] mysqld got signal 11 ;
|
|
Server version: 10.2.37-MariaDB-debug-log
|
|
sql/signal_handler.cc:209(handle_fatal_signal)[0x55d2c693d568]
|
/lib/x86_64-linux-gnu/libpthread.so.0(+0x12730)[0x7f9a9d78b730]
|
sql/sql_update.cc:1201(unsafe_key_update(List<TABLE_LIST>, unsigned long long))[0x55d2c6578bd2]
|
sql/sql_update.cc:1420(Multiupdate_prelocking_strategy::handle_end(THD*))[0x55d2c657a4f5]
|
sql/sql_base.cc:4192(open_tables(THD*, DDL_options_st const&, TABLE_LIST**, unsigned int*, unsigned int, Prelocking_strategy*))[0x55d2c61b70d2]
|
sql/sql_base.h:250(open_tables(THD*, TABLE_LIST**, unsigned int*, unsigned int, Prelocking_strategy*))[0x55d2c656ed73]
|
sql/sql_update.cc:1547(mysql_multi_update_prepare(THD*))[0x55d2c657b3c3]
|
sql/sql_parse.cc:4071(mysql_execute_command(THD*))[0x55d2c62dd1d0]
|
sql/sp_head.cc:3332(sp_instr_stmt::exec_core(THD*, unsigned int*))[0x55d2c611af62]
|
sql/sp_head.cc:3095(sp_lex_keeper::reset_lex_and_exec_core(THD*, unsigned int*, bool, sp_instr*))[0x55d2c6119b1d]
|
sql/sp_head.cc:3248(sp_instr_stmt::execute(THD*, unsigned int*))[0x55d2c611a80d]
|
sql/sp_head.cc:1326(sp_head::execute(THD*, bool))[0x55d2c610e778]
|
sql/sp_head.cc:2202(sp_head::execute_procedure(THD*, List<Item>*))[0x55d2c611345f]
|
sql/sql_parse.cc:2981(do_execute_sp(THD*, sp_head*))[0x55d2c62d5b48]
|
sql/sql_parse.cc:5599(mysql_execute_command(THD*))[0x55d2c62e9660]
|
sql/sql_parse.cc:7763(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x55d2c62f81d8]
|
sql/sql_parse.cc:1830(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x55d2c62cef06]
|
sql/sql_parse.cc:1381(do_command(THD*))[0x55d2c62cb92b]
|
sql/sql_connect.cc:1336(do_handle_one_connection(CONNECT*))[0x55d2c66740f2]
|
sql/sql_connect.cc:1242(handle_one_connection)[0x55d2c66739b3]
|
perfschema/pfs.cc:1871(pfs_spawn_thread)[0x55d2c7b0d822]
|
nptl/pthread_create.c:487(start_thread)[0x7f9a9d780fa3]
|
x86_64/clone.S:97(clone)[0x7f9a9d1044cf]
|
|
Query (0x625000101990): update (t1 join v2 on v2.c0 = t1.c1) set v2.pk = 1
|
|
Attachments
Issue Links
- is duplicated by
-
MDEV-17435 Server crashes inst_select_lex::get_free_table_map upon attempt to update view through 2nd execution of SP
-
- Closed
-
- relates to
-
MDEV-16940 Server crashes in unsafe_key_update upon attempt to update view through 2nd execution of SP
-
- Closed
-
-
MDEV-21630 Server crashes in mysql_derived_prepare on 2nd execution of SP with views, ASAN: heap-use-after-free in mysql_derived_prepare
-
- Confirmed
-
Here's how the server is brought to the reported crash.
When executing the first call of sp1() the function Multiupdate_prelocking_strategy::handle_end() comes to the code:
if (select_lex->handle_derived(thd->lex, DT_MERGE))
DBUG_RETURN(1);
if (thd->lex->save_prep_leaf_tables())
that merges the specification of the view v2 into
with the function mysql_derived_merge().
When doing this the function checks the validity of on expression v2.c0 = t1.c1 after having merged the select of v2 into the join of the update statement. When the function discovers that t1.c1 refers to non-existing field it reports an error and returns to Multiupdate_prelocking_strategy::handle_end() that quits immediately without calling save_prep_leaf_tables().
After this we have:
v2->merged == true
thd->lex->prep_leaf_list_state != SAVED
<select_for_update>->first_cond_optimization == true.
When executing the second call of sp1() Multiupdate_prelocking_strategy::handle_end() comes to the code
if (mysql_handle_derived(lex, DT_INIT) ||
mysql_handle_derived(lex, DT_MERGE_FOR_INSERT) ||
mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(1);
if (setup_tables_and_check_access(thd, &select_lex->context,
&select_lex->top_join_list, table_list, select_lex->leaf_tables,
FALSE, UPDATE_ACL, SELECT_ACL, FALSE))
DBUG_RETURN(1);
The call of mysql_handle_derived(lex, DT_PREPARE) does not assign v2->table anything because v2 has been merged. The following call of setup_tables_and_check_access() sees that
<select_for_update>->first_cond_optimization == true
<select_for_update>->prep_leaf_list_state != SELECT_LEX::SAVED
and build the list <select_for_update>->leaf_tables as containing t1,v2.
The call select_for_update->handle_derived(thd->lex, DT_MERGE) does not do anything because v2 is merged.
Now we come to the call of unsafe_key_update() with the list of t1,v2 as the the first parameter and the valueof v2->table == NULL. The attempt to get v2->table->map causes a crash.