Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-25636

Bug report: abortion in sql/sql_parse.cc:6294

Details

    Description

      I used my fuzzing tool to test Mariadb , and found a bug that can result in an abortion. This bug looks similar to MDEV-25634, but is call stack is different from MDEV-25634. Please check whether it is the repeated one.

      Mariadb installation:
      1) cd mariadb-10.5.9
      2) mkdir build; cd build
      3) cmake -DWITH_ASAN=ON -DWITH_ASAN_SCOPE=ON -DWITH_DEBUG=ON ../
      4) make -j8 && sudo make install

      How to Repeat:
      export ASAN_OPTIONS=detect_leaks=0
      /usr/local/mysql/bin/mysqld_safe &
      /usr/local/mysql/bin/mysql -uroot -p123456(your password)
      MariaDB> drop database if exists test_db;
      MariaDB> create database test_db;
      MariaDB> source fuzz.sql;

      I have simplified the content of fuzz.sql, and I hope fuzz.sql can help you reproduce the bug and fix it. In addition, I attach the abortion report (which has its stack trace).

      Attachments

        Issue Links

          Activity

            psergei Sergei Petrunia added a comment - - edited

            ... the failure in subselect4.test exposes another issue. It can be observed as
            follows:

            set storage_engine=myisam;
            CREATE TABLE t2 (c int , a int, b int);
            INSERT INTO t2 VALUES (10,7,0);
            CREATE TABLE t3 (a int, b int) ;
            INSERT INTO t3 VALUES (5,0),(7,0);
            CREATE TABLE t4 (a int);
            INSERT INTO t4 VALUES (2),(8);
            

            set @@optimizer_switch='semijoin=off,in_to_exists=on,materialization=off,subquery_cache=off';
            explain format=json 
            SELECT * FROM t2 
            WHERE
              t2.b IN (SELECT b 
                       FROM t3 
                       WHERE 
                         t3.a = t2.a AND 
                          a < SOME (SELECT * FROM t4)
                       )
              OR ( t2.c > 242 );
            

            | {
              "query_block": {
                "select_id": 1,
                "const_condition": "<in_optimizer>(0,<exists>(subquery#2))",
                "table": {
                  "table_name": "t2",
                  "access_type": "system",
                  "rows": 1,
                  "filtered": 100
                },
                "subqueries": [
                  {
                    "query_block": {
                      "select_id": 2,
                      "const_condition": "<nop>(<in_optimizer>(7,(subquery#3) > <cache>(t3.a)))",
                      "table": {
                        "table_name": "t3",
                        "access_type": "ALL",
                        "rows": 2,
                        "filtered": 100,
                        "attached_condition": "<cache>(0) = t3.b and t3.a = 7"
                      },
                      "subqueries": [
                        {
                          "query_block": {
                            "select_id": 3,
                            "table": {
                              "table_name": "t4",
                              "access_type": "ALL",
                              "rows": 2,
                              "filtered": 100
                            }
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            } |
            

            Note these lines:

                      "const_condition": "<nop>(<in_optimizer>(7,(subquery#3) > <cache>(t3.a)))",
            

            followed by:

                      "table": {
                        "table_name": "t3",
            

            That is, the const_condition has references to t3.a while table t3 is a non-constant table.

            The select itself happens to produce a correct result:

            +------+------+------+
            | c    | a    | b    |
            +------+------+------+
            |   10 |    7 |    0 |
            +------+------+------+
            

            psergei Sergei Petrunia added a comment - - edited ... the failure in subselect4.test exposes another issue. It can be observed as follows: set storage_engine=myisam; CREATE TABLE t2 (c int , a int , b int ); INSERT INTO t2 VALUES (10,7,0); CREATE TABLE t3 (a int , b int ) ; INSERT INTO t3 VALUES (5,0),(7,0); CREATE TABLE t4 (a int ); INSERT INTO t4 VALUES (2),(8); set @@optimizer_switch= 'semijoin=off,in_to_exists=on,materialization=off,subquery_cache=off' ; explain format=json SELECT * FROM t2 WHERE t2.b IN ( SELECT b FROM t3 WHERE t3.a = t2.a AND a < SOME ( SELECT * FROM t4) ) OR ( t2.c > 242 ); | { "query_block": { "select_id": 1, "const_condition": "<in_optimizer>(0,<exists>(subquery#2))", "table": { "table_name": "t2", "access_type": "system", "rows": 1, "filtered": 100 }, "subqueries": [ { "query_block": { "select_id": 2, "const_condition": "<nop>(<in_optimizer>(7,(subquery#3) > <cache>(t3.a)))", "table": { "table_name": "t3", "access_type": "ALL", "rows": 2, "filtered": 100, "attached_condition": "<cache>(0) = t3.b and t3.a = 7" }, "subqueries": [ { "query_block": { "select_id": 3, "table": { "table_name": "t4", "access_type": "ALL", "rows": 2, "filtered": 100 } } } ] } } ] } } | Note these lines: "const_condition": "<nop>(<in_optimizer>(7,(subquery#3) > <cache>(t3.a)))", followed by: "table": { "table_name": "t3", That is, the const_condition has references to t3.a while table t3 is a non-constant table. The select itself happens to produce a correct result: +------+------+------+ | c | a | b | +------+------+------+ | 10 | 7 | 0 | +------+------+------+

            <nop>(<in_optimizer>(7,(subquery#3) > <cache>(t3.a)))
            

            This represents the

            t3.a < SOME (SELECT t4.a FROM t4)
            

            Initially it was

            <nop>(<in_optimizer>(t3.a,t3.a < any (subquery#3)))
            

            But the parent subquery has t3.a = t2.a and t2.a is an outer reference to constant table t2 with t2.a=7.

            Equality substitution in the subquery has substituted one use of "t3.a" with 7 but not the other.

            psergei Sergei Petrunia added a comment - <nop>(<in_optimizer>(7,(subquery#3) > <cache>(t3.a))) This represents the t3.a < SOME ( SELECT t4.a FROM t4) Initially it was <nop>(<in_optimizer>(t3.a,t3.a < any (subquery#3))) But the parent subquery has t3.a = t2.a and t2.a is an outer reference to constant table t2 with t2.a=7. Equality substitution in the subquery has substituted one use of "t3.a" with 7 but not the other.

            The

            t3.a < any (subquery#3)
            

            is represented by an Item_allany_subselect.
            For this item, the used_tables() becomes incorrect here:

              #0  Item_subselect::used_tables (this=0x62b000003818) at /home/psergey/dev-git/10.2-cl/sql/item_subselect.cc:970
              #1  0x0000555556328802 in Used_tables_and_const_cache::used_tables_and_const_cache_join (this=0x62b000005fe0, item=0x62b000003818) at /home/psergey/dev-git/10.2-cl/sql/item.h:4241
              #2  0x0000555556328967 in Used_tables_and_const_cache::used_tables_and_const_cache_update_and_join (this=0x62b000005fe0, item=0x62b000003818) at /home/psergey/dev-git/10.2-cl/sql/item.h:4247
              #3  0x00005555563289d0 in Used_tables_and_const_cache::used_tables_and_const_cache_update_and_join (this=0x62b000005fe0, argc=2, argv=0x62b000005fc8) at /home/psergey/dev-git/10.2-cl/sql/item.h:4258
              #4  0x000055555632c482 in Item_func::update_used_tables (this=0x62b000005f38) at /home/psergey/dev-git/10.2-cl/sql/item_func.h:144
              #5  0x0000555556328954 in Used_tables_and_const_cache::used_tables_and_const_cache_update_and_join (this=0x62b000003b28, item=0x62b000005f38) at /home/psergey/dev-git/10.2-cl/sql/item.h:4246
              #6  0x00005555563289d0 in Used_tables_and_const_cache::used_tables_and_const_cache_update_and_join (this=0x62b000003b28, argc=1, argv=0x62b000003b10) at /home/psergey/dev-git/10.2-cl/sql/item.h:4258
              #7  0x000055555632c482 in Item_func::update_used_tables (this=0x62b000003a80) at /home/psergey/dev-git/10.2-cl/sql/item_func.h:144
              #8  0x000055555653a3d5 in Item_func::build_equal_items (this=0x62b000003a80, thd=0x62a00009c270, inherited=0x62b000003c50, link_item_fields=false, cond_equal_ref=0x0) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:13734
              #9  0x0000555556538efe in Item_cond_and::build_equal_items (this=0x62b000003b68, thd=0x62a00009c270, inherited=0x62b000003c50, link_item_fields=true, cond_equal_ref=0x62b000005520) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:13589
              #10 0x000055555653a7d9 in build_equal_items (join=0x62b0000050e8, cond=0x62b000003b68, inherited=0x0, join_list=0x62b000000ec0, ignore_on_conds=false, cond_equal_ref=0x62b000005520, link_equal_fields=true) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:13835
              #11 0x0000555556543ef7 in optimize_cond (join=0x62b0000050e8, conds=0x62b000003b68, join_list=0x62b000000ec0, ignore_on_conds=false, cond_value=0x62b0000053f8, cond_equal=0x62b000005520, flags=1) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:15519
              #12 0x00005555564da163 in JOIN::optimize_inner (this=0x62b0000050e8) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:1382
              #13 0x00005555564d740c in JOIN::optimize (this=0x62b0000050e8) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:1127
              #14 0x0000555556407394 in st_select_lex::optimize_unflattened_subqueries (this=0x62a0000a05a8, const_only=false) at /home/psergey/dev-git/10.2-cl/sql/sql_lex.cc:3865
              #15 0x00005555568b3d91 in JOIN::optimize_unflattened_subqueries (this=0x62b000004560) at /home/psergey/dev-git/10.2-cl/sql/opt_subselect.cc:5326
              #16 0x00005555564e14e5 in JOIN::optimize_inner (this=0x62b000004560) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:2089
              #17 0x00005555564d740c in JOIN::optimize (this=0x62b000004560) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:1127
              #18 0x00005555564f2b70 in mysql_select (thd=0x62a00009c270, tables=0x62b0000005b0, wild_num=1, fields=..., conds=0x62b000004240, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2147748612, result=0x62b000004480, unit=0x62a00009fe68, select_lex=0x62a0000a05a8) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:3835
              #19 0x0000555556591014 in mysql_explain_union (thd=0x62a00009c270, unit=0x62a00009fe68, result=0x62b000004480) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:25373
              #20 0x00005555564411fb in execute_sqlcom_select (thd=0x62a00009c270, all_tables=0x62b0000005b0) at /home/psergey/dev-git/10.2-cl/sql/sql_parse.cc:6213
              #21 0x000055555642d1cc in mysql_execute_command (thd=0x62a00009c270) at /home/psergey/dev-git/10.2-cl/sql/sql_parse.cc:3585
              #22 0x000055555644af53 in mysql_parse (thd=0x62a00009c270, rawbuf=0x62b000000290 "explain format=json SELECT * FROM t2 WHERE t2.b IN (SELECT b FROM t3 WHERE t3.a = t2.a AND a < SOME (SELECT * FROM t4))    OR ( t2.c > 242 )", length=140, parser_state=0x7fffc525ad60, is_com_multi=false, is_next_command=false) at /home/psergey/dev-git/10.2-cl/sql/sql_parse.cc:7796
            

            Here, we have

            (gdb) p this->used_tables()
              $284 = 0
            

            But

            (gdb) p this->left_expr->used_tables()
              $286 = 1
            

            psergei Sergei Petrunia added a comment - The t3.a < any (subquery#3) is represented by an Item_allany_subselect. For this item, the used_tables() becomes incorrect here: #0 Item_subselect::used_tables (this=0x62b000003818) at /home/psergey/dev-git/10.2-cl/sql/item_subselect.cc:970 #1 0x0000555556328802 in Used_tables_and_const_cache::used_tables_and_const_cache_join (this=0x62b000005fe0, item=0x62b000003818) at /home/psergey/dev-git/10.2-cl/sql/item.h:4241 #2 0x0000555556328967 in Used_tables_and_const_cache::used_tables_and_const_cache_update_and_join (this=0x62b000005fe0, item=0x62b000003818) at /home/psergey/dev-git/10.2-cl/sql/item.h:4247 #3 0x00005555563289d0 in Used_tables_and_const_cache::used_tables_and_const_cache_update_and_join (this=0x62b000005fe0, argc=2, argv=0x62b000005fc8) at /home/psergey/dev-git/10.2-cl/sql/item.h:4258 #4 0x000055555632c482 in Item_func::update_used_tables (this=0x62b000005f38) at /home/psergey/dev-git/10.2-cl/sql/item_func.h:144 #5 0x0000555556328954 in Used_tables_and_const_cache::used_tables_and_const_cache_update_and_join (this=0x62b000003b28, item=0x62b000005f38) at /home/psergey/dev-git/10.2-cl/sql/item.h:4246 #6 0x00005555563289d0 in Used_tables_and_const_cache::used_tables_and_const_cache_update_and_join (this=0x62b000003b28, argc=1, argv=0x62b000003b10) at /home/psergey/dev-git/10.2-cl/sql/item.h:4258 #7 0x000055555632c482 in Item_func::update_used_tables (this=0x62b000003a80) at /home/psergey/dev-git/10.2-cl/sql/item_func.h:144 #8 0x000055555653a3d5 in Item_func::build_equal_items (this=0x62b000003a80, thd=0x62a00009c270, inherited=0x62b000003c50, link_item_fields=false, cond_equal_ref=0x0) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:13734 #9 0x0000555556538efe in Item_cond_and::build_equal_items (this=0x62b000003b68, thd=0x62a00009c270, inherited=0x62b000003c50, link_item_fields=true, cond_equal_ref=0x62b000005520) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:13589 #10 0x000055555653a7d9 in build_equal_items (join=0x62b0000050e8, cond=0x62b000003b68, inherited=0x0, join_list=0x62b000000ec0, ignore_on_conds=false, cond_equal_ref=0x62b000005520, link_equal_fields=true) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:13835 #11 0x0000555556543ef7 in optimize_cond (join=0x62b0000050e8, conds=0x62b000003b68, join_list=0x62b000000ec0, ignore_on_conds=false, cond_value=0x62b0000053f8, cond_equal=0x62b000005520, flags=1) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:15519 #12 0x00005555564da163 in JOIN::optimize_inner (this=0x62b0000050e8) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:1382 #13 0x00005555564d740c in JOIN::optimize (this=0x62b0000050e8) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:1127 #14 0x0000555556407394 in st_select_lex::optimize_unflattened_subqueries (this=0x62a0000a05a8, const_only=false) at /home/psergey/dev-git/10.2-cl/sql/sql_lex.cc:3865 #15 0x00005555568b3d91 in JOIN::optimize_unflattened_subqueries (this=0x62b000004560) at /home/psergey/dev-git/10.2-cl/sql/opt_subselect.cc:5326 #16 0x00005555564e14e5 in JOIN::optimize_inner (this=0x62b000004560) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:2089 #17 0x00005555564d740c in JOIN::optimize (this=0x62b000004560) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:1127 #18 0x00005555564f2b70 in mysql_select (thd=0x62a00009c270, tables=0x62b0000005b0, wild_num=1, fields=..., conds=0x62b000004240, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2147748612, result=0x62b000004480, unit=0x62a00009fe68, select_lex=0x62a0000a05a8) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:3835 #19 0x0000555556591014 in mysql_explain_union (thd=0x62a00009c270, unit=0x62a00009fe68, result=0x62b000004480) at /home/psergey/dev-git/10.2-cl/sql/sql_select.cc:25373 #20 0x00005555564411fb in execute_sqlcom_select (thd=0x62a00009c270, all_tables=0x62b0000005b0) at /home/psergey/dev-git/10.2-cl/sql/sql_parse.cc:6213 #21 0x000055555642d1cc in mysql_execute_command (thd=0x62a00009c270) at /home/psergey/dev-git/10.2-cl/sql/sql_parse.cc:3585 #22 0x000055555644af53 in mysql_parse (thd=0x62a00009c270, rawbuf=0x62b000000290 "explain format=json SELECT * FROM t2 WHERE t2.b IN (SELECT b FROM t3 WHERE t3.a = t2.a AND a < SOME (SELECT * FROM t4)) OR ( t2.c > 242 )", length=140, parser_state=0x7fffc525ad60, is_com_multi=false, is_next_command=false) at /home/psergey/dev-git/10.2-cl/sql/sql_parse.cc:7796 Here, we have (gdb) p this->used_tables() $284 = 0 But (gdb) p this->left_expr->used_tables() $286 = 1

            Looking at what Item_allany_subselect has for used_tables and update_used_tables:

              $287 = (const Item_allany_subselect * const) 0x62b000003818
            (gdb) p this->update_used_tables
              $288 = {void (Item_in_subselect * const)} 0x555556c9c798 <Item_in_subselect::update_used_tables()>
            (gdb) p this->used_tables
              $289 = {table_map (const Item_subselect * const)} 0x555556c819c0 <Item_subselect::used_tables() const>
            

            Item_in_subselect's update_used_tables takes the left expression into account:

            void Item_in_subselect::update_used_tables()
            {
              Item_subselect::update_used_tables();
              left_expr->update_used_tables();
              //used_tables_cache |= left_expr->used_tables();
              used_tables_cache= Item_subselect::used_tables() | left_expr->used_tables();
            }
            

            But then we use ancestor's used_tables();

            table_map Item_subselect::used_tables() const
            {
              return (table_map) ((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN)? 
                                  used_tables_cache : 0L);
            }
            

            which makes an assumption that engine->uncacheable()? --> used_tables()=0.
            This is not the case for Item_allany_subselect representing t3.a < any (subquery#3).

            psergei Sergei Petrunia added a comment - Looking at what Item_allany_subselect has for used_tables and update_used_tables: $287 = (const Item_allany_subselect * const) 0x62b000003818 (gdb) p this->update_used_tables $288 = {void (Item_in_subselect * const)} 0x555556c9c798 <Item_in_subselect::update_used_tables()> (gdb) p this->used_tables $289 = {table_map (const Item_subselect * const)} 0x555556c819c0 <Item_subselect::used_tables() const> Item_in_subselect's update_used_tables takes the left expression into account: void Item_in_subselect::update_used_tables() { Item_subselect::update_used_tables(); left_expr->update_used_tables(); //used_tables_cache |= left_expr->used_tables(); used_tables_cache= Item_subselect::used_tables() | left_expr->used_tables(); } But then we use ancestor's used_tables(); table_map Item_subselect::used_tables() const { return (table_map) ((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN)? used_tables_cache : 0L); } which makes an assumption that engine->uncacheable()? --> used_tables()=0. This is not the case for Item_allany_subselect representing t3.a < any (subquery#3) .

            57fe50eab9ff01590ec3396dca0de9081ef0ef00 OK to push (but check buioldbot yourself)

            sanja Oleksandr Byelkin added a comment - 57fe50eab9ff01590ec3396dca0de9081ef0ef00 OK to push (but check buioldbot yourself)

            People

              psergei Sergei Petrunia
              Zuming Jiang Zuming Jiang
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.