Skip to content

Commit 2cd98c9

Browse files
committed
MDEV-23809: Server crash in JOIN_CACHE::free or ...
The problem was caused by use of COLLATION(AVG('x')). This is an item whose value is a constant. Name Resolution code called convert_const_to_int() which removed AVG('x'). However, the item representing COLLATION(...) still had with_sum_func=1. This inconsistent state confused the code that handles grouping and DISTINCT: JOIN::get_best_combination() decided to use one temporary table and allocated one JOIN_TAB for it, but then JOIN::make_aggr_tables_info() attempted to use two and made writes beyond the end of the JOIN::join_tab array. The fix: - Do not replace constant expressions which contain aggregate functions. - Add JOIN::dbug_join_tab_array_size to catch attempts to use more JOIN_TAB objects than we've allocated.
1 parent f9ec9b6 commit 2cd98c9

File tree

5 files changed

+69
-1
lines changed

5 files changed

+69
-1
lines changed

mysql-test/main/func_group.result

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,5 +2523,30 @@ DROP TABLE t2;
25232523
DROP VIEW v1;
25242524
DROP TABLE t1;
25252525
#
2526+
# MDEV-23809: Server crash in JOIN_CACHE::free or ...
2527+
#
2528+
CREATE TABLE t1 (a INT);
2529+
INSERT INTO t1 VALUES (1),(2);
2530+
SELECT DISTINCT CASE CONVERT(EXPORT_SET(0, COLLATION(BENCHMARK(1, BIT_OR(0))),0),TIME) WHEN a THEN 1 END AS f FROM t1;
2531+
f
2532+
NULL
2533+
Warnings:
2534+
Warning 1292 Truncated incorrect time value: '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0'
2535+
DROP TABLE t1;
2536+
CREATE TABLE t1 (a VARCHAR(8) NULL, b BIGINT);
2537+
INSERT INTO t1 (a,b) VALUES (NULL,NULL),('foo',NULL);
2538+
SELECT DISTINCT STRCMP((b > COLLATION(STDDEV_SAMP(15750))), a) AS f FROM t1;
2539+
f
2540+
NULL
2541+
DROP TABLE t1;
2542+
CREATE TABLE t1 (a BIGINT) AS SELECT 1 AS v3 UNION SELECT FALSE ;
2543+
SELECT DISTINCT a IN ( COLLATION (AVG ('x'))) FROM t1 ;
2544+
a IN ( COLLATION (AVG ('x')))
2545+
NULL
2546+
Warnings:
2547+
Warning 1292 Truncated incorrect DOUBLE value: 'x'
2548+
Warning 1292 Truncated incorrect DOUBLE value: 'x'
2549+
DROP TABLE t1;
2550+
#
25262551
# End of 10.3 tests
25272552
#

mysql-test/main/func_group.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,25 @@ DROP TABLE t2;
17561756
DROP VIEW v1;
17571757
DROP TABLE t1;
17581758

1759+
--echo #
1760+
--echo # MDEV-23809: Server crash in JOIN_CACHE::free or ...
1761+
--echo #
1762+
1763+
CREATE TABLE t1 (a INT);
1764+
INSERT INTO t1 VALUES (1),(2);
1765+
SELECT DISTINCT CASE CONVERT(EXPORT_SET(0, COLLATION(BENCHMARK(1, BIT_OR(0))),0),TIME) WHEN a THEN 1 END AS f FROM t1;
1766+
DROP TABLE t1;
1767+
1768+
1769+
CREATE TABLE t1 (a VARCHAR(8) NULL, b BIGINT);
1770+
INSERT INTO t1 (a,b) VALUES (NULL,NULL),('foo',NULL);
1771+
SELECT DISTINCT STRCMP((b > COLLATION(STDDEV_SAMP(15750))), a) AS f FROM t1;
1772+
DROP TABLE t1;
1773+
1774+
CREATE TABLE t1 (a BIGINT) AS SELECT 1 AS v3 UNION SELECT FALSE ;
1775+
SELECT DISTINCT a IN ( COLLATION (AVG ('x'))) FROM t1 ;
1776+
DROP TABLE t1;
1777+
17591778
--echo #
17601779
--echo # End of 10.3 tests
17611780
--echo #

sql/item_cmpfunc.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,18 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item,
340340
field_item->field_type() != MYSQL_TYPE_YEAR)
341341
return 1;
342342

343-
if ((*item)->const_item() && !(*item)->is_expensive())
343+
/*
344+
Replace (*item) with its value if the item can be computed.
345+
346+
Do not replace items that contain aggregate functions:
347+
There can be such items that are constants, e.g. COLLATION(AVG(123)),
348+
but this function is called at Name Resolution phase.
349+
Removing aggregate functions may confuse query plan generation code, e.g.
350+
the optimizer might conclude that the query doesn't need to do grouping
351+
at all.
352+
*/
353+
if ((*item)->const_item() && !(*item)->is_expensive() &&
354+
!(*item)->with_sum_func)
344355
{
345356
TABLE *table= field->table;
346357
Sql_mode_save sql_mode(thd);

sql/sql_select.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,9 @@ JOIN::optimize_inner()
15961596
DEBUG_SYNC(thd, "before_join_optimize");
15971597

15981598
THD_STAGE_INFO(thd, stage_optimizing);
1599+
#ifndef DBUG_OFF
1600+
dbug_join_tab_array_size= 0;
1601+
#endif
15991602

16001603
set_allowed_join_cache_types();
16011604
need_distinct= TRUE;
@@ -2740,6 +2743,9 @@ int JOIN::optimize_stage2()
27402743
{
27412744
if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB))))
27422745
DBUG_RETURN(1);
2746+
#ifndef DBUG_OFF
2747+
dbug_join_tab_array_size= 1;
2748+
#endif
27432749
need_tmp= 1;
27442750
}
27452751
if (make_aggr_tables_info())
@@ -3044,6 +3050,7 @@ bool JOIN::make_aggr_tables_info()
30443050
{
30453051
aggr_tables++;
30463052
curr_tab= join_tab + exec_join_tab_cnt();
3053+
DBUG_ASSERT(curr_tab - join_tab < dbug_join_tab_array_size);
30473054
bzero((void*)curr_tab, sizeof(JOIN_TAB));
30483055
curr_tab->ref.key= -1;
30493056
if (only_const_tables())
@@ -3172,6 +3179,7 @@ bool JOIN::make_aggr_tables_info()
31723179

31733180
curr_tab++;
31743181
aggr_tables++;
3182+
DBUG_ASSERT(curr_tab - join_tab < dbug_join_tab_array_size);
31753183
bzero((void*)curr_tab, sizeof(JOIN_TAB));
31763184
curr_tab->ref.key= -1;
31773185

@@ -9781,6 +9789,10 @@ bool JOIN::get_best_combination()
97819789

97829790
fix_semijoin_strategies_for_picked_join_order(this);
97839791

9792+
#ifndef DBUG_OFF
9793+
dbug_join_tab_array_size= top_join_tab_count + aggr_tables;
9794+
#endif
9795+
97849796
if (inject_splitting_cond_for_all_tables_with_split_opt())
97859797
DBUG_RETURN(TRUE);
97869798

sql/sql_select.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,7 @@ class JOIN :public Sql_alloc
12651265

12661266
#ifndef DBUG_OFF
12671267
void dbug_verify_sj_inner_tables(uint n_positions) const;
1268+
uint dbug_join_tab_array_size;
12681269
#endif
12691270

12701271
/* We also maintain a stack of join optimization states in * join->positions[] */

0 commit comments

Comments
 (0)