[Commits] ba1c6577a36: MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order...
revision-id: ba1c6577a36b078a41289f6259880ce77fe28711 (mariadb-10.4.23-65-gba1c6577a36) parent(s): aec856073df12e95b68667587bfd8e469b60e7d4 author: Sergei Petrunia committer: Sergei Petrunia timestamp: 2022-04-21 22:45:31 +0300 message: MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order... When doing condition pushdown from HAVING into WHERE, Item_equal::create_pushable_equalities() calls item->set_extraction_flag(IMMUTABLE_FL) for constant items. Then, Item::cleanup_excluding_immutables_processor() checks for this flag to see if it should call item->cleanup() or leave the item as-is. The failure happens when a constant item has a non-constant one inside it, like: (tbl.col=0 AND impossible_cond) item->walk(cleanup_excluding_immutables_processor) works in a bottom-up way so it 1. will call Item_func_eq(tbl.col=0)->cleanup() 2. will not call Item_cond_and->cleanup (as the AND is constant) This creates an item tree where a fixed Item has an un-fixed Item inside it which eventually causes an assertion failure. Fixed by introducing this rule: instead of just calling item->set_extraction_flag(IMMUTABLE_FL); we call Item::walk() to set the flag for all sub-items of the item. --- mysql-test/main/having_cond_pushdown.result | 15 +++++++++++++++ mysql-test/main/having_cond_pushdown.test | 10 ++++++++++ sql/item.h | 6 ++++++ sql/item_cmpfunc.cc | 12 +++++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result index 9b124296e3d..9a9ed2b9213 100644 --- a/mysql-test/main/having_cond_pushdown.result +++ b/mysql-test/main/having_cond_pushdown.result @@ -4924,3 +4924,18 @@ SELECT a FROM t1 GROUP BY a HAVING a = ( SELECT MIN(c) FROM t2 ); a 2 DROP TABLE t1,t2; +# +# MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order or Assertion `fixed == 1' +# +CREATE TABLE t1 (i int NOT NULL); +SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL); +i +SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0); +i +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0); +i +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +DROP TABLE t1; diff --git a/mysql-test/main/having_cond_pushdown.test b/mysql-test/main/having_cond_pushdown.test index fc75122615c..270eac2a46f 100644 --- a/mysql-test/main/having_cond_pushdown.test +++ b/mysql-test/main/having_cond_pushdown.test @@ -1440,3 +1440,13 @@ eval EXPLAIN FORMAT=JSON $q; eval $q; DROP TABLE t1,t2; + +--echo # +--echo # MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order or Assertion `fixed == 1' +--echo # + +CREATE TABLE t1 (i int NOT NULL); +SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL); +SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0); +SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0); +DROP TABLE t1; diff --git a/sql/item.h b/sql/item.h index 9182b578cdb..af6f350216d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1938,6 +1938,12 @@ class Item: public Value_source, return 0; } + virtual bool set_extraction_flag_processor(void *arg) + { + set_extraction_flag(*(int*)arg); + return 0; + } + /** Check db/table_name if they defined in item and match arg values diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 15f1766b2e6..0ec20efdf27 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -7533,7 +7533,17 @@ bool Item_equal::create_pushable_equalities(THD *thd, if (!eq || equalities->push_back(eq, thd->mem_root)) return true; if (!clone_const) - right_item->set_extraction_flag(IMMUTABLE_FL); + { + /* + Also set IMMUTABLE_FL for any sub-items of the right_item. + This is needed to prevent Item::cleanup_excluding_immutables_processor + from peforming cleanup of the sub-items and so creating an item tree + where a fixed item has non-fixed items inside it. + */ + int new_flag= IMMUTABLE_FL; + right_item->walk(&Item::set_extraction_flag_processor, false, + (void*)&new_flag); + } } while ((item=it++))
participants (1)
-
psergey