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

SIGSEGV in Bitmap<64u>::merge on SELECT

Details

    Description

      USE test;
      SET SESSION sql_select_limit=0;
      CREATE TABLE t(b INT);
      CREATE TEMPORARY TABLE t(a INT);
      DROP TABLE IF EXISTS t;
      CREATE TABLE t2(a TEXT);
      SELECT * FROM t2 HAVING a IN (SELECT a FROM t);
      

      Leads to:

      10.5.3 64488a6f2dd6aa43462292b757e783cfba11a8c6

      Core was generated by `/test/MD050520-mariadb-10.5.3-linux-x86_64-opt/bin/mysqld --no-defaults --core-'.
      Program terminated with signal SIGSEGV, Segmentation fault.
      #0  __pthread_kill (threadid=<optimized out>, signo=signo@entry=11)
          at ../sysdeps/unix/sysv/linux/pthread_kill.c:57
      [Current thread is 1 (Thread 0x14642c359700 (LWP 49916))]
      (gdb) bt
      #0  __pthread_kill (threadid=<optimized out>, signo=signo@entry=11) at ../sysdeps/unix/sysv/linux/pthread_kill.c:57
      #1  0x000055a6d343e757 in my_write_core (sig=sig@entry=11) at /test/10.5_opt/mysys/stacktrace.c:518
      #2  0x000055a6d2e0081a in handle_fatal_signal (sig=11) at /test/10.5_opt/sql/signal_handler.cc:329
      #3  <signal handler called>
      #4  Bitmap<64u>::merge (map2=..., this=<optimized out>) at /test/10.5_opt/sql/sql_bitmap.h:211
      #5  add_key_field (join=join@entry=0x14640984a820, key_fields=key_fields@entry=0x14642c356f58, and_level=and_level@entry=0, cond=cond@entry=0x14640984bf08, field=field@entry=0x14640985c868, eq_func=eq_func@entry=true, value=0x14640984bfa0, usable_tables=18446744073709551615, sargables=0x14642c357028, row_col_no=0, num_values=1) at /test/10.5_opt/sql/sql_select.cc:5921
      #6  0x000055a6d2c3516c in add_key_equal_fields (join=join@entry=0x14640984a820, key_fields=key_fields@entry=0x14642c356f58, and_level=0, cond=cond@entry=0x14640984bf08, field_item=0x14640984a5a0, eq_func=eq_func@entry=true, val=0x14640984bfa0, usable_tables=18446744073709551615, sargables=0x14642c357028, row_col_no=0, num_values=1) at /test/10.5_opt/sql/sql_select.cc:6038
      #7  0x000055a6d2c3c3a7 in Item_bool_func2::add_key_fields_optimize_op (this=0x14640984bf08, join=0x14640984a820, key_fields=0x14642c356f58, and_level=0x14642c356f54, usable_tables=18446744073709551615, sargables=0x14642c357028, equal_func=true) at /test/10.5_opt/sql/sql_select.cc:6321
      #8  0x000055a6d2e477cf in Item_func_eq::add_key_fields (this=<optimized out>, join=<optimized out>, key_fields=<optimized out>, and_level=<optimized out>, usable_tables=<optimized out>, sargables=<optimized out>) at /test/10.5_opt/sql/item_cmpfunc.h:727
      #9  0x000055a6d2c3c9c3 in update_ref_and_keys (thd=0x146409812018, keyuse=keyuse@entry=0x14642c357030, join_tab=0x14640984b498, tables=1, cond=0x14640984bf08, normal_tables=18446744073709551615, sargables=0x14642c357028, select_lex=<optimized out>, select_lex=<optimized out>) at /test/10.5_opt/sql/sql_select.cc:6794
      #10 0x000055a6d2c61222 in JOIN::reoptimize (this=this@entry=0x14640984a820, added_where=<optimized out>, join_tables=join_tables@entry=1, save_to=save_to@entry=0x0) at /test/10.5_opt/sql/sql_select.cc:27926
      #11 0x000055a6d2d3b302 in JOIN::choose_subquery_plan (this=this@entry=0x14640984a820, join_tables=1) at /test/10.5_opt/sql/opt_subselect.cc:6616
      #12 0x000055a6d2c674b1 in make_join_statistics (keyuse_array=0x14640984ab10, tables_list=..., join=0x14640984a820) at /test/10.5_opt/sql/sql_select.cc:5589
      #13 JOIN::optimize_inner (this=this@entry=0x14640984a820) at /test/10.5_opt/sql/sql_select.cc:2260
      #14 0x000055a6d2c67acb in JOIN::optimize (this=this@entry=0x14640984a820) at /test/10.5_opt/sql/sql_select.cc:1606
      #15 0x000055a6d2bed525 in st_select_lex::optimize_unflattened_subqueries (this=0x1464098470f0, const_only=const_only@entry=false) at /test/10.5_opt/sql/sql_lex.cc:4779
      #16 0x000055a6d2d396b3 in JOIN::optimize_unflattened_subqueries (this=this@entry=0x14640984a018) at /test/10.5_opt/sql/opt_subselect.cc:5547
      #17 0x000055a6d2c61f2b in JOIN::optimize_stage2 (this=this@entry=0x14640984a018) at /test/10.5_opt/sql/sql_select.cc:3042
      #18 0x000055a6d2c6597d in JOIN::optimize_inner (this=this@entry=0x14640984a018) at /test/10.5_opt/sql/sql_select.cc:2286
      #19 0x000055a6d2c67acb in JOIN::optimize (this=this@entry=0x14640984a018) at /test/10.5_opt/sql/sql_select.cc:1606
      #20 0x000055a6d2c67bd1 in mysql_select (thd=thd@entry=0x146409812018, tables=0x1464098476e8, fields=..., conds=0x0, og_num=<optimized out>, order=0x0, group=0x0, having=0x1464098493f8, proc_param=0x0, select_options=2147748608, result=0x146409849ff0, unit=0x146409815e68, select_lex=0x1464098470f0) at /test/10.5_opt/sql/sql_select.cc:4655
      #21 0x000055a6d2c685e1 in handle_select (thd=thd@entry=0x146409812018, lex=lex@entry=0x146409815da0, result=result@entry=0x146409849ff0, setup_tables_done_option=setup_tables_done_option@entry=0) at /test/10.5_opt/sql/sql_select.cc:417
      #22 0x000055a6d2c0f1c1 in execute_sqlcom_select (thd=thd@entry=0x146409812018, all_tables=0x1464098476e8) at /test/10.5_opt/sql/sql_parse.cc:6172
      #23 0x000055a6d2c0b0e2 in mysql_execute_command (thd=thd@entry=0x146409812018) at /test/10.5_opt/sql/sql_parse.cc:3901
      #24 0x000055a6d2c1227c in mysql_parse (thd=0x146409812018, rawbuf=<optimized out>, length=46, parser_state=0x14642c3584d0, is_com_multi=<optimized out>, is_next_command=<optimized out>) at /test/10.5_opt/sql/sql_parse.cc:7957
      #25 0x000055a6d2c078a5 in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x146409812018, packet=packet@entry=0x14640983a019 "SELECT * FROM t2 HAVING a IN (SELECT a FROM t)", packet_length=packet_length@entry=46, is_com_multi=is_com_multi@entry=false, is_next_command=is_next_command@entry=false) at /test/10.5_opt/sql/sql_parse.cc:1839
      #26 0x000055a6d2c05b36 in do_command (thd=0x146409812018) at /test/10.5_opt/sql/sql_parse.cc:1358
      #27 0x000055a6d2cfa2ee in do_handle_one_connection (connect=<optimized out>, connect@entry=0x14642a0329b8, put_in_cache=put_in_cache@entry=true) at /test/10.5_opt/sql/sql_connect.cc:1422
      #28 0x000055a6d2cfa494 in handle_one_connection (arg=arg@entry=0x14642a0329b8) at /test/10.5_opt/sql/sql_connect.cc:1319
      #29 0x000055a6d30665ea in pfs_spawn_thread (arg=0x14642a04b018) at /test/10.5_opt/storage/perfschema/pfs.cc:2201
      #30 0x000014642b7806db in start_thread (arg=0x14642c359700) at pthread_create.c:463
      #31 0x000014642ab7e88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
      

      Bug confirmed present in:
      MariaDB: 10.1.45 (dbg), 10.1.45 (opt), 10.2.32 (dbg), 10.2.32 (opt), 10.3.23 (dbg), 10.3.23 (opt), 10.4.13 (dbg), 10.4.13 (opt), 10.5.2 (dbg), 10.5.2 (opt), 10.5.3 (dbg), 10.5.3 (opt)

      Bug confirmed not present in:
      MySQL: 5.5.62 (dbg), 5.5.62 (opt), 5.6.47 (dbg), 5.6.47 (opt), 5.7.29 (dbg), 5.7.29 (opt), 8.0.19 (dbg), 8.0.19 (opt)

      Attachments

        Issue Links

          Activity

            So lets start to write down some observations

            Lets take a look at the function
            Item_in_subselect::create_single_in_to_exists_cond

            Here we end up in this part of the code

              else
              {
                Item *item= (Item*)select_lex->item_list.head();
                if (item->type() != REF_ITEM ||
                    ((Item_ref*)item)->ref_type() != Item_ref::VIEW_REF)
                  item= item->real_item();
            

            We are taking the branch as we don't have a having clause, group by clause or aggregate function in the subquery.

            One thing that looked suspicious was that item_list does not remain updated after fix_fields and one should use JOIN::fields_list,
            but then going through more code in the function JOIN::optimize_inner, I see

             /*
                Needed in case optimizer short-cuts,
                set properly in make_aggr_tables_info()
              */
              fields= &select_lex->item_list;
            

            So these are the same list

            varun Varun Gupta (Inactive) added a comment - So lets start to write down some observations Lets take a look at the function Item_in_subselect::create_single_in_to_exists_cond Here we end up in this part of the code else { Item *item= (Item*)select_lex->item_list.head(); if (item->type() != REF_ITEM || ((Item_ref*)item)->ref_type() != Item_ref::VIEW_REF) item= item->real_item(); We are taking the branch as we don't have a having clause, group by clause or aggregate function in the subquery. One thing that looked suspicious was that item_list does not remain updated after fix_fields and one should use JOIN::fields_list, but then going through more code in the function JOIN::optimize_inner, I see /* Needed in case optimizer short-cuts, set properly in make_aggr_tables_info() */ fields= &select_lex->item_list; So these are the same list
            varun Varun Gupta (Inactive) added a comment - - edited

            Now coming back to the function where we create the equality when the IN->EXISTS transformation happen

                Item *item= (Item*)select_lex->item_list.head();
            

            (gdb) p (Item*) select_lex->item_list.head()
            $4 = (Item *) 0x62b000003428
            (gdb) p dbug_print_item((Item*) select_lex->item_list.head())
            $5 = 0x3965020 <dbug_item_print_buf> "t2.b"
            (gdb) p item->type()
            $6 = Item::REF_ITEM
            

            and then we have the code, where for REF items (except Item_direct_view_ref) we use real_item()

                if (item->type() != REF_ITEM ||
                    ((Item_ref*)item)->ref_type() != Item_ref::VIEW_REF)
                  item= item->real_item();
            

            I thing using real_item is incorrect here, we should just use the original item to create the equality because the ref item has the information like the item belongs to the parent select.
            This would make sure that the item t2.b will not be local to the subquery and hence we would not try to create a keyuse for the equi-join condition

            real_item does not make sense here because the ref item here are referring to the parent select.
            Even for cases where we have ref item in the subquery like in HAVING, GROUP BY etc are handled separately in the same function (the if branch)

            varun Varun Gupta (Inactive) added a comment - - edited Now coming back to the function where we create the equality when the IN->EXISTS transformation happen Item *item= (Item*)select_lex->item_list.head(); (gdb) p (Item*) select_lex->item_list.head() $4 = (Item *) 0x62b000003428 (gdb) p dbug_print_item((Item*) select_lex->item_list.head()) $5 = 0x3965020 <dbug_item_print_buf> "t2.b" (gdb) p item->type() $6 = Item::REF_ITEM and then we have the code, where for REF items (except Item_direct_view_ref) we use real_item() if (item->type() != REF_ITEM || ((Item_ref*)item)->ref_type() != Item_ref::VIEW_REF) item= item->real_item(); I thing using real_item is incorrect here, we should just use the original item to create the equality because the ref item has the information like the item belongs to the parent select. This would make sure that the item t2.b will not be local to the subquery and hence we would not try to create a keyuse for the equi-join condition real_item does not make sense here because the ref item here are referring to the parent select. Even for cases where we have ref item in the subquery like in HAVING, GROUP BY etc are handled separately in the same function (the if branch)

            Pushed a patch to the branch 10.1-mdev22498

            varun Varun Gupta (Inactive) added a comment - Pushed a patch to the branch 10.1-mdev22498

                /*
                  No need to use real_item for the item, as the ref items that are possible
                  in the subquery either belong to views or to the parent select.
                  For such case we need to refer to the reference and not to the original
                  item.
               */
            

            above is not exactly true, because one can use alias there, but I checked it works

            SELECT sum(a), t2.a aaa, t2.b FROM t2 HAVING aaa IN (SELECT aaa FROM t1);

            otherwise it is ok

            sanja Oleksandr Byelkin added a comment - /* No need to use real_item for the item, as the ref items that are possible in the subquery either belong to views or to the parent select. For such case we need to refer to the reference and not to the original item. */ above is not exactly true, because one can use alias there, but I checked it works SELECT sum(a), t2.a aaa, t2.b FROM t2 HAVING aaa IN (SELECT aaa FROM t1); otherwise it is ok

            Filter removed from runs

            Roel Roel Van de Paar added a comment - Filter removed from runs

            People

              varun Varun Gupta (Inactive)
              Roel Roel Van de Paar
              Votes:
              0 Vote for this issue
              Watchers:
              4 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.