| Bug #37904 | SELECT FROM dual WHERE in-subquery causes server crash | ||
|---|---|---|---|
| Submitted: | 6 Jul 2008 15:59 | Modified: | 7 Sep 2008 22:21 |
| Reporter: | Davi Arnaut (OCA) | Email Updates: | |
| Status: | Duplicate | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S2 (Serious) |
| Version: | 6.0 | OS: | Any |
| Assigned to: | Assigned Account | CPU Architecture: | Any |
| Tags: | =any, =some, crash, IN, subquery | ||
[6 Jul 2008 17:46]
MySQL Verification Team
Thank you for the bug report. Attempting backtrace. You can use the following information to find out where mysqld died. If you see no messages after this, something went terribly wrong... 00000001403B3A37 mysqld.exe!convert_subq_to_sj()[sql_select.cc:3246] 00000001403B48F8 mysqld.exe!JOIN::flatten_subqueries()[sql_select.cc:3442] 00000001403B30FE mysqld.exe!mysql_select()[sql_select.cc:2980] 00000001403A9664 mysqld.exe!handle_select()[sql_select.cc:302] 0000000140364AAB mysqld.exe!execute_sqlcom_select()[sql_parse.cc:4847] 000000014035B100 mysqld.exe!mysql_execute_command()[sql_parse.cc:2015] 0000000140367238 mysqld.exe!mysql_parse()[sql_parse.cc:5815] 0000000140358F39 mysqld.exe!dispatch_command()[sql_parse.cc:1053] 00000001403584C3 mysqld.exe!do_command()[sql_parse.cc:724] 0000000140319FD6 mysqld.exe!handle_one_connection()[sql_connect.cc:1153] 00000001405603C5 mysqld.exe!pthread_start()[my_winthread.c:86] 00000001408F2635 mysqld.exe!_callthreadstart()[thread.c:295] 00000001408F2607 mysqld.exe!_threadstart()[thread.c:277] 00000000779FCDCD kernel32.dll!BaseThreadInitThunk() 0000000077B4C6E1 ntdll.dll!RtlUserThreadStart() Trying to get some variables. Some pointers may be invalid and cause the dump to abort... thd->query at 0000000004222F00=SELECT 1 FROM DUAL WHERE 1 = SOME (SELECT 1 FROM t1) thd->thread_id=1 thd->killed=NOT_KILLED
[19 Jul 2008 13:00]
Sergey Petrunya
Changed to a more precise synopsis.
[7 Sep 2008 22:21]
Sergey Petrunya
The same issue as BUG#36896. Changing status to duplicate.

Description: Selecting from a dummy table (FROM DUAL) with a subquery comparison using the IN, =ANY or =SOME predicates causes a server crash. How to repeat: CREATE TABLE t1 (a INT); SELECT 1 FROM DUAL WHERE 1 = SOME (SELECT 1 FROM t1); # OR SELECT 1 FROM DUAL WHERE 1 ANY (SELECT 1 FROM t1); Suggested fix: The code in sql_select.cc around lines 3246 and 3248 looks pretty strange. It seems the for loop is used to reach the last leaf tables in the parent and it connects the last one with the leaf tables of the subquery. 3246├> for (tl= parent_lex->leaf_tables; tl->next_leaf; tl= tl->next_leaf); 3247│ tl->next_leaf= subq_lex->leaf_tables; 3248│ last_leaf= tl; The problem appears to be that the case where there are no leaf tables in the parent query is not robustly handled. Someone should review this code, it has a few TODO notes. === modified file 'sql/sql_select.cc' --- sql/sql_select.cc 2008-06-28 11:00:59 +0000 +++ sql/sql_select.cc 2008-07-06 15:57:29 +0000 @@ -3228,7 +3228,7 @@ bool convert_subq_to_sj(JOIN *parent_joi st_select_lex *subq_lex= subq_pred->unit->first_select(); nested_join->join_list.empty(); List_iterator_fast<TABLE_LIST> li(subq_lex->top_join_list); - TABLE_LIST *tl, *last_leaf; + TABLE_LIST *tl; while ((tl= li++)) { tl->embedding= sj_nest; @@ -3243,17 +3243,22 @@ bool convert_subq_to_sj(JOIN *parent_joi NOTE: We actually insert them at the front! That's because the order is reversed in this list. */ - for (tl= parent_lex->leaf_tables; tl->next_leaf; tl= tl->next_leaf); - tl->next_leaf= subq_lex->leaf_tables; - last_leaf= tl; + for (tl= parent_lex->leaf_tables; tl && tl->next_leaf; tl= tl->next_leaf); + + if (tl) + tl->next_leaf= subq_lex->leaf_tables; + else + parent_lex->leaf_tables= subq_lex->leaf_tables; /* Same as above for next_local chain (a theory: a next_local chain always starts with ::leaf_tables because view's tables are inserted after the view) */ - for (tl= parent_lex->leaf_tables; tl->next_local; tl= tl->next_local); - tl->next_local= subq_lex->leaf_tables; + for (tl= parent_lex->leaf_tables; tl && tl->next_local; tl= tl->next_local); + + if (tl) + tl->next_local= subq_lex->leaf_tables; /* A theory: no need to re-connect the next_global chain */