Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions mysql-test/main/subselect_extra.result
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,41 @@ a b
DROP VIEW v2;
DROP TABLE t1,t2;
set optimizer_switch= @tmp_subselect_extra_derived;
#
# MDEV-35565 Server crashes simplifying group by <subquery>
#
create table t1 (a int) engine=myisam;
insert into t1 values (1),(2);
create table t2 (b int) engine=myisam;
insert into t2 values (1),(2);
# output from these sorts of queries are unstable, test only that it
# outputs a sensible error message and doesn't crash
select * from t1, t2 where b in
(select (select a from t1 order by b) as d from t1 group by (select d));
ERROR 21000: Subquery returns more than 1 row
drop table t1, t2;
create table fact (id int, primary key (id));
insert into fact values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table dim (id int, attr int, fromdate date,
primary key (id, fromdate), key (attr, fromdate));
insert into dim
select id, id, date_add('2009-06-22', interval id day) from fact;
insert into dim
select id, id+1, date_add('2008-06-22', interval id day) from fact;
create view v as
select f.id, d.attr
from fact f
left join dim d
on d.id = f.id and
d.fromdate = (select max(fromdate) from dim where id = f.id);
explain extended select id from v where attr between 4 and 6;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY d range PRIMARY,attr attr 5 NULL 6 100.00 Using index condition
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 test.d.id 1 100.00 Using where; Using index
3 DEPENDENT SUBQUERY dim ref PRIMARY PRIMARY 4 test.f.id 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`fact` `f` join `test`.`dim` `d` where `f`.`id` = `d`.`id` and `d`.`attr` between 4 and 6 and `d`.`fromdate` = <expr_cache><`f`.`id`>((/* select#3 */ select max(`test`.`dim`.`fromdate`) from `test`.`dim` where `test`.`dim`.`id` = `f`.`id`))
drop view v;
drop table fact, dim;
# end of 10.11 tests
42 changes: 42 additions & 0 deletions mysql-test/main/subselect_extra.test
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,45 @@ DROP VIEW v2;
DROP TABLE t1,t2;

set optimizer_switch= @tmp_subselect_extra_derived;

--echo #
--echo # MDEV-35565 Server crashes simplifying group by <subquery>
--echo #

create table t1 (a int) engine=myisam;
insert into t1 values (1),(2);

create table t2 (b int) engine=myisam;
insert into t2 values (1),(2);

--echo # output from these sorts of queries are unstable, test only that it
--echo # outputs a sensible error message and doesn't crash
--error 1242
select * from t1, t2 where b in
(select (select a from t1 order by b) as d from t1 group by (select d));

drop table t1, t2;

create table fact (id int, primary key (id));
insert into fact values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

create table dim (id int, attr int, fromdate date,
primary key (id, fromdate), key (attr, fromdate));
insert into dim
select id, id, date_add('2009-06-22', interval id day) from fact;
insert into dim
select id, id+1, date_add('2008-06-22', interval id day) from fact;

create view v as
select f.id, d.attr
from fact f
left join dim d
on d.id = f.id and
d.fromdate = (select max(fromdate) from dim where id = f.id);

explain extended select id from v where attr between 4 and 6;

drop view v;
drop table fact, dim;

--echo # end of 10.11 tests
38 changes: 38 additions & 0 deletions mysql-test/main/subselect_extra_no_semijoin.result
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,44 @@ a b
DROP VIEW v2;
DROP TABLE t1,t2;
set optimizer_switch= @tmp_subselect_extra_derived;
#
# MDEV-35565 Server crashes simplifying group by <subquery>
#
create table t1 (a int) engine=myisam;
insert into t1 values (1),(2);
create table t2 (b int) engine=myisam;
insert into t2 values (1),(2);
# output from these sorts of queries are unstable, test only that it
# outputs a sensible error message and doesn't crash
select * from t1, t2 where b in
(select (select a from t1 order by b) as d from t1 group by (select d));
ERROR 21000: Subquery returns more than 1 row
drop table t1, t2;
create table fact (id int, primary key (id));
insert into fact values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table dim (id int, attr int, fromdate date,
primary key (id, fromdate), key (attr, fromdate));
insert into dim
select id, id, date_add('2009-06-22', interval id day) from fact;
insert into dim
select id, id+1, date_add('2008-06-22', interval id day) from fact;
create view v as
select f.id, d.attr
from fact f
left join dim d
on d.id = f.id and
d.fromdate = (select max(fromdate) from dim where id = f.id);
explain extended select id from v where attr between 4 and 6;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY d range PRIMARY,attr attr 5 NULL 6 100.00 Using index condition
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 test.d.id 1 100.00 Using where; Using index
3 DEPENDENT SUBQUERY dim ref PRIMARY PRIMARY 4 test.f.id 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`fact` `f` join `test`.`dim` `d` where `f`.`id` = `d`.`id` and `d`.`attr` between 4 and 6 and `d`.`fromdate` = <expr_cache><`f`.`id`>((/* select#3 */ select max(`test`.`dim`.`fromdate`) from `test`.`dim` where `test`.`dim`.`id` = `f`.`id`))
drop view v;
drop table fact, dim;
# end of 10.11 tests
set optimizer_switch= @subselect_extra_no_sj_tmp;
set @optimizer_switch_for_subselect_extra_test=null;
#
Expand Down
17 changes: 8 additions & 9 deletions sql/item_subselect.cc
Original file line number Diff line number Diff line change
Expand Up @@ -476,15 +476,14 @@ class Field_fixer: public Field_enumerator
st_select_lex *new_parent; /* Select we're in */
void visit_field(Item_field *item) override
{
//for (TABLE_LIST *tbl= new_parent->leaf_tables; tbl; tbl= tbl->next_local)
//{
// if (tbl->table == field->table)
// {
used_tables|= item->field->table->map;
// return;
// }
//}
//used_tables |= OUTER_REF_TABLE_BIT;
st_select_lex *cmp= new_parent;
while (cmp->merged_into)
cmp= cmp->merged_into;
if (item->field->table->pos_in_table_list &&
(item->field->table->pos_in_table_list->select_lex == cmp))
used_tables|= item->field->table->map;
else
used_tables|= OUTER_REF_TABLE_BIT;
}
Comment on lines 478 to 487

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

In visit_field, item->field can be NULL if the field is not yet resolved (e.g., during certain error paths or early optimization phases). Additionally, item->field->table could potentially be NULL in some contexts. Dereferencing these pointers without a prior check can lead to a server crash.

To prevent potential null pointer dereferences, please add defensive checks for item->field and item->field->table before accessing their members.

  {
    if (item->field && item->field->table)
    {
      st_select_lex *cmp= new_parent;
      while (cmp && cmp->merged_into)
        cmp= cmp->merged_into;
      if (cmp && item->field->table->pos_in_table_list &&
          (item->field->table->pos_in_table_list->select_lex == cmp))
        used_tables|= item->field->table->map;
      else
        used_tables|= OUTER_REF_TABLE_BIT;
    }
  }

};

Expand Down