Details
Description
The following test case causes a crash of the server:
create table t1 (a int) engine=myisam; |
insert into t1 values (3), (7), (1); |
select a from t1 where a in (values (7) union values (8)); |
"mysqld" received signal SIGSEGV, Segmentation fault.
|
0x0000555555d7a212 in st_select_lex_unit::optimize (this=0x7fff90013f80) at /home/igor/maria-git/10.3-mdev-22786/sql/sql_union.cc:1430:
|
|
1428 sl->join->select_options=
|
1429 (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
|
1430 sl->options & ~OPTION_FOUND_ROWS : sl->options |
|
The crash happens for the following reason.
The function Item_subselect::fix_fields contains the loop:
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
{
if (sl->tvc)
{
wrap_tvc_into_select(thd, sl);
}
}
that is supposed to look trough all union operands at the top level of the processed IN/ALL/ANY subquery and wrap each table value constructor into a select:
<values ...> => select * from (<value...>) t
This transformation allows us to use all optimizations applied to multi-select IN subqueries.
Apparently this transformation changes the selects of the union. If a TVC is transformed then it is substituted for a <wrapping select> in the union chain. To get the next element in the chain we should have used
<wrapping select> ->next_select() instead of sl ->next_select() that returns 0. As a result the loop ends prematurely and any TVC following the first one in the chain is not wrapped into select.
For the reported test case we have after the above loop:
select a from t1 where a in (select * from (values (7)) tvc_0 union values (8));
Such queries are not expected by the optimizer phase and cause crashes.