← Back to team overview

maria-developers team mailing list archive

Re: [Commits] 9f8a458: MDEV-7846: Server crashes in Item_subselect::fix_fields or fails with Thread stack overrun

 

Hi Sanja,

It is very difficult to understand this patch.  What is the exact meaning of
left_expr_orig?  It is declared but has no comments.

It is interesting that convert_subq_to_sj has got new code to handle scalar
comparison case ( foo IN (SELECT bar ...)), while there is no handling for 
tuple comparison  ( (foo1,foo2) IN (SELECT bar1,bar2 ..)).  Is this
intentional?

On Thu, Apr 23, 2015 at 08:09:00PM +0200, sanja@xxxxxxxxxxx wrote:
> revision-id: 9f8a458fb2d07298810bb5d9824ce728017bfb32
> parent(s): e540d023e2ec6f37efc9ab695ccdfd4a6744ad64
> committer: Oleksandr Byelkin
> branch nick: server
> timestamp: 2015-04-23 20:08:57 +0200
> message:
> 
> MDEV-7846: Server crashes in Item_subselect::fix_fields or fails with Thread stack overrun
> 
> Substitute into transformed subselects original left expression and than register its change in case it was substituted.
> 
> ---
>  mysql-test/r/subselect.result             | 28 +++++++++++++++++++++++++
>  mysql-test/r/subselect_no_mat.result      | 28 +++++++++++++++++++++++++
>  mysql-test/r/subselect_no_opts.result     | 28 +++++++++++++++++++++++++
>  mysql-test/r/subselect_no_scache.result   | 28 +++++++++++++++++++++++++
>  mysql-test/r/subselect_no_semijoin.result | 28 +++++++++++++++++++++++++
>  mysql-test/t/subselect.test               | 34 +++++++++++++++++++++++++++++++
>  sql/item_cmpfunc.cc                       |  8 ++++----
>  sql/item_subselect.cc                     |  8 +++-----
>  sql/item_subselect.h                      |  1 +
>  sql/opt_subselect.cc                      |  4 +++-
>  10 files changed, 185 insertions(+), 10 deletions(-)
> 
> diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
> index 0ab2d48..cf52ba2 100644
> --- a/mysql-test/r/subselect.result
> +++ b/mysql-test/r/subselect.result
> @@ -7053,3 +7053,31 @@ WHERE h.host in (SELECT host FROM mysql.user)
>  ) AS sq
>  FROM mysql.host h GROUP BY h.host;
>  sq
> +#
> +# MDEV-7846:Server crashes in Item_subselect::fix
> +#_fields or fails with Thread stack overrun
> +#
> +CREATE TABLE t1 (column1 INT) ENGINE=MyISAM;
> +INSERT INTO t1 VALUES (3),(9);
> +CREATE TABLE t2 (column2 INT) ENGINE=MyISAM;
> +INSERT INTO t2 VALUES (1),(4);
> +CREATE TABLE t3 (column3 INT) ENGINE=MyISAM;
> +INSERT INTO t3 VALUES (6),(8);
> +CREATE TABLE t4 (column4 INT) ENGINE=MyISAM;
> +INSERT INTO t4 VALUES (2),(5);
> +PREPARE stmt FROM "
> +SELECT ( 
> +  SELECT MAX( table1.column1 ) AS field1 
> +  FROM t1 AS table1
> +  WHERE table3.column3 IN ( SELECT table2.column2 AS field2 FROM t2 AS table2 ) 
> +) AS sq
> +FROM t3 AS table3, t4 AS table4 GROUP BY sq
> +";
> +EXECUTE stmt;
> +sq
> +NULL
> +EXECUTE stmt;
> +sq
> +NULL
> +deallocate prepare stmt;
> +drop table t1,t2,t3,t4;
> diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
> index 5780351..73a69e9 100644
> --- a/mysql-test/r/subselect_no_mat.result
> +++ b/mysql-test/r/subselect_no_mat.result
> @@ -7050,6 +7050,34 @@ WHERE h.host in (SELECT host FROM mysql.user)
>  ) AS sq
>  FROM mysql.host h GROUP BY h.host;
>  sq
> +#
> +# MDEV-7846:Server crashes in Item_subselect::fix
> +#_fields or fails with Thread stack overrun
> +#
> +CREATE TABLE t1 (column1 INT) ENGINE=MyISAM;
> +INSERT INTO t1 VALUES (3),(9);
> +CREATE TABLE t2 (column2 INT) ENGINE=MyISAM;
> +INSERT INTO t2 VALUES (1),(4);
> +CREATE TABLE t3 (column3 INT) ENGINE=MyISAM;
> +INSERT INTO t3 VALUES (6),(8);
> +CREATE TABLE t4 (column4 INT) ENGINE=MyISAM;
> +INSERT INTO t4 VALUES (2),(5);
> +PREPARE stmt FROM "
> +SELECT ( 
> +  SELECT MAX( table1.column1 ) AS field1 
> +  FROM t1 AS table1
> +  WHERE table3.column3 IN ( SELECT table2.column2 AS field2 FROM t2 AS table2 ) 
> +) AS sq
> +FROM t3 AS table3, t4 AS table4 GROUP BY sq
> +";
> +EXECUTE stmt;
> +sq
> +NULL
> +EXECUTE stmt;
> +sq
> +NULL
> +deallocate prepare stmt;
> +drop table t1,t2,t3,t4;
>  set optimizer_switch=default;
>  select @@optimizer_switch like '%materialization=on%';
>  @@optimizer_switch like '%materialization=on%'
> diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
> index 4bea029..1512e39 100644
> --- a/mysql-test/r/subselect_no_opts.result
> +++ b/mysql-test/r/subselect_no_opts.result
> @@ -7048,4 +7048,32 @@ WHERE h.host in (SELECT host FROM mysql.user)
>  ) AS sq
>  FROM mysql.host h GROUP BY h.host;
>  sq
> +#
> +# MDEV-7846:Server crashes in Item_subselect::fix
> +#_fields or fails with Thread stack overrun
> +#
> +CREATE TABLE t1 (column1 INT) ENGINE=MyISAM;
> +INSERT INTO t1 VALUES (3),(9);
> +CREATE TABLE t2 (column2 INT) ENGINE=MyISAM;
> +INSERT INTO t2 VALUES (1),(4);
> +CREATE TABLE t3 (column3 INT) ENGINE=MyISAM;
> +INSERT INTO t3 VALUES (6),(8);
> +CREATE TABLE t4 (column4 INT) ENGINE=MyISAM;
> +INSERT INTO t4 VALUES (2),(5);
> +PREPARE stmt FROM "
> +SELECT ( 
> +  SELECT MAX( table1.column1 ) AS field1 
> +  FROM t1 AS table1
> +  WHERE table3.column3 IN ( SELECT table2.column2 AS field2 FROM t2 AS table2 ) 
> +) AS sq
> +FROM t3 AS table3, t4 AS table4 GROUP BY sq
> +";
> +EXECUTE stmt;
> +sq
> +NULL
> +EXECUTE stmt;
> +sq
> +NULL
> +deallocate prepare stmt;
> +drop table t1,t2,t3,t4;
>  set @optimizer_switch_for_subselect_test=null;
> diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
> index fdb3b12..26cea1f 100644
> --- a/mysql-test/r/subselect_no_scache.result
> +++ b/mysql-test/r/subselect_no_scache.result
> @@ -7059,6 +7059,34 @@ WHERE h.host in (SELECT host FROM mysql.user)
>  ) AS sq
>  FROM mysql.host h GROUP BY h.host;
>  sq
> +#
> +# MDEV-7846:Server crashes in Item_subselect::fix
> +#_fields or fails with Thread stack overrun
> +#
> +CREATE TABLE t1 (column1 INT) ENGINE=MyISAM;
> +INSERT INTO t1 VALUES (3),(9);
> +CREATE TABLE t2 (column2 INT) ENGINE=MyISAM;
> +INSERT INTO t2 VALUES (1),(4);
> +CREATE TABLE t3 (column3 INT) ENGINE=MyISAM;
> +INSERT INTO t3 VALUES (6),(8);
> +CREATE TABLE t4 (column4 INT) ENGINE=MyISAM;
> +INSERT INTO t4 VALUES (2),(5);
> +PREPARE stmt FROM "
> +SELECT ( 
> +  SELECT MAX( table1.column1 ) AS field1 
> +  FROM t1 AS table1
> +  WHERE table3.column3 IN ( SELECT table2.column2 AS field2 FROM t2 AS table2 ) 
> +) AS sq
> +FROM t3 AS table3, t4 AS table4 GROUP BY sq
> +";
> +EXECUTE stmt;
> +sq
> +NULL
> +EXECUTE stmt;
> +sq
> +NULL
> +deallocate prepare stmt;
> +drop table t1,t2,t3,t4;
>  set optimizer_switch=default;
>  select @@optimizer_switch like '%subquery_cache=on%';
>  @@optimizer_switch like '%subquery_cache=on%'
> diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
> index cb6d35d..4c6f037 100644
> --- a/mysql-test/r/subselect_no_semijoin.result
> +++ b/mysql-test/r/subselect_no_semijoin.result
> @@ -7048,5 +7048,33 @@ WHERE h.host in (SELECT host FROM mysql.user)
>  ) AS sq
>  FROM mysql.host h GROUP BY h.host;
>  sq
> +#
> +# MDEV-7846:Server crashes in Item_subselect::fix
> +#_fields or fails with Thread stack overrun
> +#
> +CREATE TABLE t1 (column1 INT) ENGINE=MyISAM;
> +INSERT INTO t1 VALUES (3),(9);
> +CREATE TABLE t2 (column2 INT) ENGINE=MyISAM;
> +INSERT INTO t2 VALUES (1),(4);
> +CREATE TABLE t3 (column3 INT) ENGINE=MyISAM;
> +INSERT INTO t3 VALUES (6),(8);
> +CREATE TABLE t4 (column4 INT) ENGINE=MyISAM;
> +INSERT INTO t4 VALUES (2),(5);
> +PREPARE stmt FROM "
> +SELECT ( 
> +  SELECT MAX( table1.column1 ) AS field1 
> +  FROM t1 AS table1
> +  WHERE table3.column3 IN ( SELECT table2.column2 AS field2 FROM t2 AS table2 ) 
> +) AS sq
> +FROM t3 AS table3, t4 AS table4 GROUP BY sq
> +";
> +EXECUTE stmt;
> +sq
> +NULL
> +EXECUTE stmt;
> +sq
> +NULL
> +deallocate prepare stmt;
> +drop table t1,t2,t3,t4;
>  set @optimizer_switch_for_subselect_test=null;
>  set @join_cache_level_for_subselect_test=NULL;
> diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
> index 3eb056d..00ab48b 100644
> --- a/mysql-test/t/subselect.test
> +++ b/mysql-test/t/subselect.test
> @@ -5930,3 +5930,37 @@ SELECT
>      WHERE h.host in (SELECT host FROM mysql.user)
>    ) AS sq
>  FROM mysql.host h GROUP BY h.host;
> +
> +
> +--echo #
> +--echo # MDEV-7846:Server crashes in Item_subselect::fix
> +--echo #_fields or fails with Thread stack overrun
> +--echo #
> +CREATE TABLE t1 (column1 INT) ENGINE=MyISAM;
> +INSERT INTO t1 VALUES (3),(9);
> +
> +CREATE TABLE t2 (column2 INT) ENGINE=MyISAM;
> +
> +INSERT INTO t2 VALUES (1),(4);
> +
> +CREATE TABLE t3 (column3 INT) ENGINE=MyISAM;
> +INSERT INTO t3 VALUES (6),(8);
> +
> +CREATE TABLE t4 (column4 INT) ENGINE=MyISAM;
> +INSERT INTO t4 VALUES (2),(5);
> +
> +
> +PREPARE stmt FROM "
> +SELECT ( 
> +  SELECT MAX( table1.column1 ) AS field1 
> +  FROM t1 AS table1
> +  WHERE table3.column3 IN ( SELECT table2.column2 AS field2 FROM t2 AS table2 ) 
> +) AS sq
> +FROM t3 AS table3, t4 AS table4 GROUP BY sq
> +";
> +
> +EXECUTE stmt;
> +EXECUTE stmt;
> +
> +deallocate prepare stmt;
> +drop table t1,t2,t3,t4;
> diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
> index 51a38f0..29fff8e 100644
> --- a/sql/item_cmpfunc.cc
> +++ b/sql/item_cmpfunc.cc
> @@ -1455,12 +1455,12 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
>         next execution we need to copy args[1]->left_expr again.
>      */
>      ref0= &(((Item_in_subselect *)args[1])->left_expr);
> -    args[0]= ref0[0];
>    }
> -  if ((!args[0]->fixed && args[0]->fix_fields(thd, ref0)) ||
> -      (!cache && !(cache= Item_cache::get_cache(ref0[0]))))
> +  if ((!(*ref0)->fixed && (*ref0)->fix_fields(thd, ref0)) ||
> +      (!cache && !(cache= Item_cache::get_cache(*ref0))))
>      DBUG_RETURN(1);
> -  args[0]= ref0[0];
> +  if (args[0] != (*ref0))
> +    current_thd->change_item_tree(args, (*ref0));
>    DBUG_PRINT("info", ("actual fix fields"));
>  
>    cache->setup(args[0]);
> diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
> index 4c11808..e04f5ff 100644
> --- a/sql/item_subselect.cc
> +++ b/sql/item_subselect.cc
> @@ -1360,7 +1360,7 @@ Item_in_subselect::Item_in_subselect(Item * left_exp,
>    upper_item(0)
>  {
>    DBUG_ENTER("Item_in_subselect::Item_in_subselect");
> -  left_expr= left_exp;
> +  left_expr_orig= left_expr= left_exp;
>    func= &eq_creator;
>    init(select_lex, new select_exists_subselect(this));
>    max_columns= UINT_MAX;
> @@ -1384,7 +1384,7 @@ Item_allany_subselect::Item_allany_subselect(Item * left_exp,
>    :Item_in_subselect(), func_creator(fc), all(all_arg)
>  {
>    DBUG_ENTER("Item_allany_subselect::Item_allany_subselect");
> -  left_expr= left_exp;
> +  left_expr_orig= left_expr= left_exp;
>    func= func_creator(all_arg);
>    init(select_lex, new select_exists_subselect(this));
>    max_columns= 1;
> @@ -2584,15 +2584,13 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
>    arena= thd->activate_stmt_arena_if_needed(&backup);
>    if (!optimizer)
>    {
> -    result= (!(optimizer= new Item_in_optimizer(left_expr, this)));
> +    result= (!(optimizer= new Item_in_optimizer(left_expr_orig, this)));
>      if (result)
>        goto out;
>    }
>  
>    thd->lex->current_select= current->return_after_parsing();
>    result= optimizer->fix_left(thd, optimizer->arguments());
> -  /* fix_fields can change reference to left_expr, we need reassign it */
> -  left_expr= optimizer->arguments()[0];
>    thd->lex->current_select= current;
>  
>    if (changed)
> diff --git a/sql/item_subselect.h b/sql/item_subselect.h
> index 592e771..930bd66 100644
> --- a/sql/item_subselect.h
> +++ b/sql/item_subselect.h
> @@ -449,6 +449,7 @@ class Item_in_subselect :public Item_exists_subselect
>                                      Item **having_item);
>  public:
>    Item *left_expr;
> +  Item *left_expr_orig;
>    /* Priority of this predicate in the convert-to-semi-join-nest process. */
>    int sj_convert_priority;
>    /*
> diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
> index 5b1a7f2..1363be0 100644
> --- a/sql/opt_subselect.cc
> +++ b/sql/opt_subselect.cc
> @@ -1593,7 +1593,9 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
>    {
>      nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr);
>      Item_func_eq *item_eq=
> -      new Item_func_eq(subq_pred->left_expr, subq_lex->ref_pointer_array[0]);
> +      new Item_func_eq(subq_pred->left_expr_orig, subq_lex->ref_pointer_array[0]);
> +    if (subq_pred->left_expr_orig != subq_pred->left_expr)
> +      thd->change_item_tree(item_eq->arguments(), subq_pred->left_expr);
>      item_eq->in_equality_no= 0;
>      sj_nest->sj_on_expr= and_items(sj_nest->sj_on_expr, item_eq);
>    }
> _______________________________________________
> commits mailing list
> commits@xxxxxxxxxxx
> https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits

-- 
BR
 Sergei
-- 
Sergei Petrunia, Software Developer
MariaDB Corporation | Skype: sergefp | Blog: http://s.petrunia.net/blog




Follow ups