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

Crash with union of my_decimal type in ORDER BY clause

Details

    Description

      Steps to reproduce:

      CREATE TABLE v0 ( v1 INTEGER ) ;
      INSERT INTO v0 ( v1 ) VALUES ( 8 ) ;
      UPDATE v0 SET v1 = 1 ORDER BY ( SELECT 1.1 UNION SELECT -1 );
      

      sigaction.c:0(__restore_rt)[0x7f5b729fc870]
      sql/my_decimal.h:132(my_decimal::operator=(my_decimal const&))[0x55e7157e1e30]
      sql/my_decimal.h:354(my_decimal2decimal(my_decimal const*, my_decimal*))[0x55e7157e2011]
      sql/my_decimal.cc:207(my_decimal::to_binary(unsigned char*, int, unsigned short, unsigned int) const)[0x55e715a84a04]
      sql/filesort.cc:1321(Type_handler_decimal_result::make_sort_key_part(unsigned char*, Item*, SORT_FIELD_ATTR const*, Sort_param*) const)[0x55e7158e8810]
      sql/filesort.cc:3030(make_sortkey(Sort_param*, unsigned char*))[0x55e7158ecfe6]
      sql/filesort.cc:1352(make_sortkey(Sort_param*, unsigned char*, unsigned char*, bool))[0x55e7158e8933]
      sql/filesort.cc:969(find_all_keys(THD*, Sort_param*, SQL_SELECT*, SORT_INFO*, st_io_cache*, st_io_cache*, Bounded_queue<unsigned char, unsigned char>*, unsigned long long*))[0x55e7158e7592]
      sql/filesort.cc:357(filesort(THD*, TABLE*, Filesort*, Filesort_tracker*, JOIN*, unsigned long long))[0x55e7158e53fb]
      sql/sql_update.cc:796(mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, bool, unsigned long long*, unsigned long long*))[0x55e7156b1588]
      sql/sql_parse.cc:4399(mysql_execute_command(THD*))[0x55e71557ebb4]
      sql/sql_parse.cc:8016(mysql_parse(THD*, char*, unsigned int, Parser_state*))[0x55e71558ad79]
      sql/sql_parse.cc:1899(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool))[0x55e7155773a8]
      sql/sql_parse.cc:1406(do_command(THD*, bool))[0x55e715575d6b]
      sql/sql_connect.cc:1410(do_handle_one_connection(CONNECT*, bool))[0x55e71572ca46]
      sql/sql_connect.cc:1314(handle_one_connection)[0x55e71572c7b1]
      perfschema/pfs.cc:2203(pfs_spawn_thread)[0x55e715c4180a]
      pthread_create.c:0(start_thread)[0x7f5b729f2259]
      :0(__GI___clone)[0x7f5b7259d5e3]
      

      Attachments

        Issue Links

          Activity

            cvicentiu Vicențiu Ciorbaru created issue -
            alice Alice Sherepa made changes -
            Field Original Value New Value
            Affects Version/s 5.5 [ 15800 ]
            Affects Version/s 10.0 [ 16000 ]
            Affects Version/s 10.2 [ 14601 ]
            Affects Version/s 10.3 [ 22126 ]
            Affects Version/s 10.4 [ 22408 ]
            Affects Version/s 10.5 [ 23123 ]
            Affects Version/s 10.1 [ 16100 ]
            alice Alice Sherepa made changes -
            Fix Version/s 10.2 [ 14601 ]
            Fix Version/s 10.3 [ 22126 ]
            Fix Version/s 10.4 [ 22408 ]
            Fix Version/s 10.5 [ 23123 ]
            Fix Version/s 10.6 [ 24028 ]
            alice Alice Sherepa made changes -
            Status Open [ 1 ] Confirmed [ 10101 ]
            alice Alice Sherepa added a comment -

            Repeatable on 5.5-10.6
            on non-debug build:

            210623  8:59:06 [ERROR] mysqld got signal 11 ;
            Server version: 10.5.10-MariaDB
             
            mysys/stacktrace.c:213(my_print_stacktrace)[0x5562338ee4d7]
            ??:0(__restore_rt)[0x7f1697ec1730]
            sql/my_decimal.h:128(my_decimal::to_binary(unsigned char*, int, int, unsigned int) const)[0x556233a125c4]
            sql/filesort.cc:1309(Type_handler_decimal_result::make_sort_key_part(unsigned char*, Item*, SORT_FIELD_ATTR const*, Sort_param*) const)[0x5562338e97fb]
            sql/filesort.cc:3016(make_sortkey)[0x5562338eabc7]
            sql/filesort.cc:958(find_all_keys)[0x5562338ed03d]
            sql/sql_update.cc:794(mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, bool, unsigned long long*, unsigned long long*))[0x5562337991e1]
            sql/sql_parse.cc:4481(mysql_execute_command(THD*))[0x5562336e89c0]
            sql/sql_parse.cc:8099(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x5562336eaefc]
            sql/sql_parse.cc:1951(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x5562336ed93a]
            sql/sql_parse.cc:1375(do_command(THD*))[0x5562336eec6f]
            sql/sql_connect.cc:1410(do_handle_one_connection(CONNECT*, bool))[0x5562337dbb12]
            sql/sql_connect.cc:1318(handle_one_connection)[0x5562337dbdd4]
            perfschema/pfs.cc:2204(pfs_spawn_thread)[0x556233b68c4d]
            nptl/pthread_create.c:487(start_thread)[0x7f1697eb6fa3]
            x86_64/clone.S:97(clone)[0x7f1697ad94cf]
             
            Query (0x7f1648011e10): UPDATE v0 SET v1 = 1 ORDER BY ( SELECT 1.1 UNION SELECT -1 )
            

            alice Alice Sherepa added a comment - Repeatable on 5.5-10.6 on non-debug build: 210623 8:59:06 [ERROR] mysqld got signal 11 ; Server version: 10.5.10-MariaDB   mysys/stacktrace.c:213(my_print_stacktrace)[0x5562338ee4d7] ??:0(__restore_rt)[0x7f1697ec1730] sql/my_decimal.h:128(my_decimal::to_binary(unsigned char*, int, int, unsigned int) const)[0x556233a125c4] sql/filesort.cc:1309(Type_handler_decimal_result::make_sort_key_part(unsigned char*, Item*, SORT_FIELD_ATTR const*, Sort_param*) const)[0x5562338e97fb] sql/filesort.cc:3016(make_sortkey)[0x5562338eabc7] sql/filesort.cc:958(find_all_keys)[0x5562338ed03d] sql/sql_update.cc:794(mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, bool, unsigned long long*, unsigned long long*))[0x5562337991e1] sql/sql_parse.cc:4481(mysql_execute_command(THD*))[0x5562336e89c0] sql/sql_parse.cc:8099(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x5562336eaefc] sql/sql_parse.cc:1951(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x5562336ed93a] sql/sql_parse.cc:1375(do_command(THD*))[0x5562336eec6f] sql/sql_connect.cc:1410(do_handle_one_connection(CONNECT*, bool))[0x5562337dbb12] sql/sql_connect.cc:1318(handle_one_connection)[0x5562337dbdd4] perfschema/pfs.cc:2204(pfs_spawn_thread)[0x556233b68c4d] nptl/pthread_create.c:487(start_thread)[0x7f1697eb6fa3] x86_64/clone.S:97(clone)[0x7f1697ad94cf]   Query (0x7f1648011e10): UPDATE v0 SET v1 = 1 ORDER BY ( SELECT 1.1 UNION SELECT -1 )
            alice Alice Sherepa made changes -
            Assignee Sergei Petrunia [ psergey ]
            alice Alice Sherepa made changes -
            Comment [ Repeatable on 5.5-10.6
            on non-debug build:

            {noformat}
            210623 8:59:06 [ERROR] mysqld got signal 11 ;
            Server version: 10.5.10-MariaDB

            mysys/stacktrace.c:213(my_print_stacktrace)[0x5562338ee4d7]
            ??:0(__restore_rt)[0x7f1697ec1730]
            sql/my_decimal.h:128(my_decimal::to_binary(unsigned char*, int, int, unsigned int) const)[0x556233a125c4]
            sql/filesort.cc:1309(Type_handler_decimal_result::make_sort_key_part(unsigned char*, Item*, SORT_FIELD_ATTR const*, Sort_param*) const)[0x5562338e97fb]
            sql/filesort.cc:3016(make_sortkey)[0x5562338eabc7]
            sql/filesort.cc:958(find_all_keys)[0x5562338ed03d]
            sql/sql_update.cc:794(mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, bool, unsigned long long*, unsigned long long*))[0x5562337991e1]
            sql/sql_parse.cc:4481(mysql_execute_command(THD*))[0x5562336e89c0]
            sql/sql_parse.cc:8099(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x5562336eaefc]
            sql/sql_parse.cc:1951(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x5562336ed93a]
            sql/sql_parse.cc:1375(do_command(THD*))[0x5562336eec6f]
            sql/sql_connect.cc:1410(do_handle_one_connection(CONNECT*, bool))[0x5562337dbb12]
            sql/sql_connect.cc:1318(handle_one_connection)[0x5562337dbdd4]
            perfschema/pfs.cc:2204(pfs_spawn_thread)[0x556233b68c4d]
            nptl/pthread_create.c:487(start_thread)[0x7f1697eb6fa3]
            x86_64/clone.S:97(clone)[0x7f1697ad94cf]

            Query (0x7f1648011e10): UPDATE v0 SET v1 = 1 ORDER BY ( SELECT 1.1 UNION SELECT -1 )
            {noformat}

            ]
            alice Alice Sherepa made changes -
            alice Alice Sherepa made changes -
            serg Sergei Golubchik made changes -
            Workflow MariaDB v3 [ 122941 ] MariaDB v4 [ 144374 ]
            serg Sergei Golubchik made changes -
            Priority Major [ 3 ] Blocker [ 1 ]
            psergei Sergei Petrunia made changes -
            Assignee Sergei Petrunia [ psergey ] Oleg Smirnov [ JIRAUSER50405 ]
            oleg.smirnov Oleg Smirnov made changes -
            Status Confirmed [ 10101 ] In Progress [ 3 ]
            oleg.smirnov Oleg Smirnov added a comment - - edited

            1. The cause of the crash is NULL value of dec_val pointer retrieved in this function:

            10.5 filesort.cc lines 1302-1318

            void
            Type_handler_decimal_result::make_sort_key_part(uchar *to, Item *item,
                                                        const SORT_FIELD_ATTR *sort_field,
                                                        Sort_param *param) const
            {
              my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
              if (item->maybe_null())
              {
                if (item->null_value)
                {
                  memset(to, 0, sort_field->length + 1);
                  return;
                }
                *to++= 1;
              }
              dec_val->to_binary(to, item->max_length - (item->decimals ? 1 : 0),
                                 item->decimals);
            }
            

            dec_val isn't analyzed for NULL so dec_val->to_binary() is called and that leads to the crash.

            And the cause of NULL value is the failure to execute a single row subselect due to more than one row in the result:

            10.5 sql_class.cc lines 3673-3689

            int select_singlerow_subselect::send_data(List<Item> &items)
            {
              DBUG_ENTER("select_singlerow_subselect::send_data");
              Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
              if (it->assigned())
              {
                my_message(ER_SUBQUERY_NO_1_ROW, ER_THD(thd, ER_SUBQUERY_NO_1_ROW),
                           MYF(current_thd->lex->ignore ? ME_JUST_WARNING : 0));
                DBUG_RETURN(1);
              }
            

            Looking for the ways to process this situation correctly.

            2. Does it make any sense to evaluate ORDER BY for an UPDATE that does not have a LIMIT clause? Maybe we can eliminate such ORDER BY at an early stage?

            oleg.smirnov Oleg Smirnov added a comment - - edited 1. The cause of the crash is NULL value of dec_val pointer retrieved in this function: 10.5 filesort.cc lines 1302-1318 void Type_handler_decimal_result::make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const { my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf); if (item->maybe_null()) { if (item->null_value) { memset(to, 0, sort_field->length + 1); return; } *to++= 1; } dec_val->to_binary(to, item->max_length - (item->decimals ? 1 : 0), item->decimals); } dec_val isn't analyzed for NULL so dec_val->to_binary() is called and that leads to the crash. And the cause of NULL value is the failure to execute a single row subselect due to more than one row in the result: 10.5 sql_class.cc lines 3673-3689 int select_singlerow_subselect::send_data(List<Item> &items) { DBUG_ENTER("select_singlerow_subselect::send_data"); Item_singlerow_subselect *it= (Item_singlerow_subselect *)item; if (it->assigned()) { my_message(ER_SUBQUERY_NO_1_ROW, ER_THD(thd, ER_SUBQUERY_NO_1_ROW), MYF(current_thd->lex->ignore ? ME_JUST_WARNING : 0)); DBUG_RETURN(1); } Looking for the ways to process this situation correctly. 2. Does it make any sense to evaluate ORDER BY for an UPDATE that does not have a LIMIT clause? Maybe we can eliminate such ORDER BY at an early stage?
            oleg.smirnov Oleg Smirnov added a comment -

            3. I pushed the fix to bb-10.2-MDEV-25994 but this code was changed in 10.5, so merging may be non-trivial.

            oleg.smirnov Oleg Smirnov added a comment - 3. I pushed the fix to bb-10.2- MDEV-25994 but this code was changed in 10.5, so merging may be non-trivial.
            oleg.smirnov Oleg Smirnov added a comment -

            Buildbot tests have succeded (https://buildbot.askmonty.org/buildbot/grid?category=main&branch=bb-10.2-MDEV-25994), so I'm passing this to review.

            oleg.smirnov Oleg Smirnov added a comment - Buildbot tests have succeded ( https://buildbot.askmonty.org/buildbot/grid?category=main&branch=bb-10.2-MDEV-25994 ), so I'm passing this to review.
            oleg.smirnov Oleg Smirnov made changes -
            Assignee Oleg Smirnov [ JIRAUSER50405 ] Sergei Petrunia [ psergey ]
            Status In Progress [ 3 ] In Review [ 10002 ]

            I see one more problem in Type_handler_decimal_result::make_sort_key:

            (gdb) p dbug_print_item(item)
              $31 = 0x5555570e2b80 <dbug_item_print_buf> "(subquery#2)"
            (gdb) p item->maybe_null
              $32 = false
            (gdb) p item->null_value
              $33 = true
            (gdb) p item
              $34 = (Item_singlerow_subselect *) 0x7fff6c0155a0
            
            

            That is, Item_singlerow_subselect has maybe_null=FALSE, but after val_decimal() it has null_value=TRUE...

            psergei Sergei Petrunia added a comment - I see one more problem in Type_handler_decimal_result::make_sort_key: (gdb) p dbug_print_item(item) $31 = 0x5555570e2b80 <dbug_item_print_buf> "(subquery#2)" (gdb) p item->maybe_null $32 = false (gdb) p item->null_value $33 = true (gdb) p item $34 = (Item_singlerow_subselect *) 0x7fff6c0155a0 That is, Item_singlerow_subselect has maybe_null=FALSE, but after val_decimal() it has null_value=TRUE...

            Trying to debug a different query:

            select 1.0 +( SELECT 1.1 UNION SELECT -1 ) from v0;
            ERROR 1242 (21000): Subquery returns more than 1 row
            

            Internally, the same happens:
            Item_singlerow_subselect has maybe_null=false, null_value=true.
            These properties are passed over to Item_func_plus.

            Then, there is a check for thd->is_error(), after which the query execution is aborted.

            psergei Sergei Petrunia added a comment - Trying to debug a different query: select 1.0 +( SELECT 1.1 UNION SELECT -1 ) from v0; ERROR 1242 (21000): Subquery returns more than 1 row Internally, the same happens: Item_singlerow_subselect has maybe_null=false, null_value=true. These properties are passed over to Item_func_plus. Then, there is a check for thd->is_error(), after which the query execution is aborted.

            A proposed alternative patch:

            diff --git a/sql/filesort.cc b/sql/filesort.cc
            index 8b019caf8f5..6b9e8af6323 100644
            --- a/sql/filesort.cc
            +++ b/sql/filesort.cc
            @@ -1118,7 +1118,7 @@ Type_handler::make_sort_key_longlong(uchar *to,
                                                  longlong value) const
             
             {
            -  if (maybe_null)
            + // if (maybe_null)
               {
                 if (null_value)
                 {
            @@ -1147,7 +1147,7 @@ Type_handler_decimal_result::make_sort_key(uchar *to, Item *item,
                                                        Sort_param *param) const
             {
               my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
            -  if (item->maybe_null)
            +  //if (item->maybe_null)
               {
                 if (item->null_value)
                 {
            @@ -1168,7 +1168,7 @@ Type_handler_real_result::make_sort_key(uchar *to, Item *item,
                                                     Sort_param *param) const
             {
               double value= item->val_result();
            -  if (item->maybe_null)
            +  //if (item->maybe_null)
               {
                 if (item->null_value)
                 {
            

            The idea is to follow the approach in other places and handle the case when item->null_value==true even for items that have maybe_null==false. (I'm not sure if I've fixed all places in make_sort_key code)

            psergei Sergei Petrunia added a comment - A proposed alternative patch: diff --git a/sql/filesort.cc b/sql/filesort.cc index 8b019caf8f5..6b9e8af6323 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1118,7 +1118,7 @@ Type_handler::make_sort_key_longlong(uchar *to, longlong value) const { - if (maybe_null) + // if (maybe_null) { if (null_value) { @@ -1147,7 +1147,7 @@ Type_handler_decimal_result::make_sort_key(uchar *to, Item *item, Sort_param *param) const { my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf); - if (item->maybe_null) + //if (item->maybe_null) { if (item->null_value) { @@ -1168,7 +1168,7 @@ Type_handler_real_result::make_sort_key(uchar *to, Item *item, Sort_param *param) const { double value= item->val_result(); - if (item->maybe_null) + //if (item->maybe_null) { if (item->null_value) { The idea is to follow the approach in other places and handle the case when item->null_value==true even for items that have maybe_null==false . (I'm not sure if I've fixed all places in make_sort_key code)

            Oleg's patch:

            • makes Type_handler_XX::make_sort_key() return bool.
            • Makes the implementations return true when the underlying item has maybe_null=false && null_value=true (TODO: is this the only case where they return true?)

            if make_sort_key() returns true only on error... well, one can check for error condition by looking at thd->is_error() ...

            psergei Sergei Petrunia added a comment - Oleg's patch: makes Type_handler_XX::make_sort_key() return bool. Makes the implementations return true when the underlying item has maybe_null=false && null_value=true (TODO: is this the only case where they return true?) if make_sort_key() returns true only on error... well, one can check for error condition by looking at thd->is_error() ...

            Take-aways from the call: it seems the best way forward is to make Item_singlerow_subselect NULLable when appropriate

            psergei Sergei Petrunia added a comment - Take-aways from the call: it seems the best way forward is to make Item_singlerow_subselect NULLable when appropriate
            psergei Sergei Petrunia added a comment - https://github.com/MariaDB/server/commit/baec17bc033cb9be02428e2089046df9f530754a
            psergei Sergei Petrunia made changes -
            Status In Review [ 10002 ] Stalled [ 10000 ]
            psergei Sergei Petrunia added a comment - sanja , please review the second patch variant: https://github.com/MariaDB/server/commit/baec17bc033cb9be02428e2089046df9f530754a
            psergei Sergei Petrunia made changes -
            Assignee Sergei Petrunia [ psergey ] Oleksandr Byelkin [ sanja ]
            Status Stalled [ 10000 ] In Review [ 10002 ]

            OK to push.

            sanja Oleksandr Byelkin added a comment - OK to push.
            sanja Oleksandr Byelkin made changes -
            Assignee Oleksandr Byelkin [ sanja ] Sergei Petrunia [ psergey ]
            Status In Review [ 10002 ] Stalled [ 10000 ]
            psergei Sergei Petrunia made changes -
            Fix Version/s 10.2.44 [ 27514 ]
            Fix Version/s 10.3.35 [ 27512 ]
            Fix Version/s 10.4.25 [ 27510 ]
            Fix Version/s 10.5.16 [ 27508 ]
            Fix Version/s 10.6.8 [ 27506 ]
            Fix Version/s 10.7.4 [ 27504 ]
            Fix Version/s 10.8.3 [ 27502 ]
            Fix Version/s 10.9.1 [ 27114 ]
            Fix Version/s 10.2 [ 14601 ]
            Fix Version/s 10.3 [ 22126 ]
            Fix Version/s 10.4 [ 22408 ]
            Fix Version/s 10.5 [ 23123 ]
            Fix Version/s 10.6 [ 24028 ]
            Resolution Fixed [ 1 ]
            Status Stalled [ 10000 ] Closed [ 6 ]
            oleg.smirnov Oleg Smirnov added a comment - - edited

            And what do you think about my comment #2:
            "2. Does it make any sense to evaluate ORDER BY for an UPDATE that does not have a LIMIT clause? Maybe we can eliminate such ORDER BY at an early stage?"

            oleg.smirnov Oleg Smirnov added a comment - - edited And what do you think about my comment #2 : "2. Does it make any sense to evaluate ORDER BY for an UPDATE that does not have a LIMIT clause? Maybe we can eliminate such ORDER BY at an early stage?"
            sanja Oleksandr Byelkin made changes -
            alice Alice Sherepa made changes -
            alice Alice Sherepa made changes -
            alice Alice Sherepa made changes -
            alice Alice Sherepa made changes -
            alice Alice Sherepa made changes -

            People

              psergei Sergei Petrunia
              cvicentiu Vicențiu Ciorbaru
              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.