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

Crash when pushing condition with CHARSET()/COERCIBILITY() into derived table

Details

    • Bug
    • Status: Closed (View Workflow)
    • Critical
    • Resolution: Fixed
    • 11.1.2, 11.2.2, 10.4(EOL), 10.5, 10.6, 10.11, 11.0(EOL), 11.1(EOL), 11.2(EOL), 11.3(EOL)
    • 10.5.26, 10.6.19, 10.11.9, 11.1.6, 11.2.5, 11.4.3
    • Optimizer, Server
    • None
    • Server version: 11.1.2-MariaDB-1:11.1.2+maria~ubu2204 source revision: 9bc25d98209df6810f7a7d5e7dd3ae677a313ab5
      key_buffer_size=134217728
      read_buffer_size=131072
      max_used_connections=1
      max_threads=153
      thread_count=1

    Description

      I first run the following statements to create tables.

      create table t1 (`c1` bigint, key (`c1`));
      insert into t1 values (-2);
      create table t2 ( `c2` double unsigned );
      insert into t2 values (12.991);
      

      After creating tables, I repeat executing the following statement through the MariaDB CLI.

      SELECT f6 FROM (SELECT DISTINCT `c1` AS `f6` FROM `t1`) AS `t1`
               JOIN (SELECT CHARSET(`c2`) AS `f5` FROM `t2`) AS `t3`
                    ON (EXISTS (SELECT `c2` FROM `t2`)) AND
                       (NOT ((CHARSET(`f5`)) NOT BETWEEN `f6` AND `f6`));
      

      After repeating several times (maybe 20 times), I lost the connection to the server.

      Or try to run the following EXPLAIN query twice, I can get the same error.

      EXPLAIN SELECT f6 FROM (SELECT DISTINCT `c1` AS `f6` FROM `t1`) AS `t1`
               JOIN (SELECT CHARSET(`c2`) AS `f5` FROM `t2`) AS `t3`
                    ON (EXISTS (SELECT `c2` FROM `t2`)) AND
                       (NOT ((CHARSET(`f5`)) NOT BETWEEN `f6` AND `f6`));
      

      The following trace is gotten from the log.

      stack_bottom = 0x7f4c90082c38 thread_stack 0x49000
      Printing to addr2line failed
      mariadbd(my_print_stacktrace+0x32)[0x563dd110a7c2]
      mariadbd(handle_fatal_signal+0x488)[0x563dd0be3cf8]
      /lib/x86_64-linux-gnu/libc.so.6(+0x42520)[0x7f4ca74bd520]
      mariadbd(_Z15optimize_keyuseP4JOINP16st_dynamic_array+0x148)[0x563dd09b5088]
      mariadbd(+0x8ad551)[0x563dd09eb551]
      mariadbd(_ZN4JOIN14optimize_innerEv+0x1322)[0x563dd09f07e2]
      mariadbd(_ZN4JOIN8optimizeEv+0xda)[0x563dd09f0e2a]
      mariadbd(+0x7ec60c)[0x563dd092a60c]
      mariadbd(_Z27mysql_handle_single_derivedP3LEXP10TABLE_LISTj+0x95)[0x563dd0929e35]
      mariadbd(_ZN4JOIN14optimize_innerEv+0xb27)[0x563dd09effe7]
      mariadbd(_ZN4JOIN8optimizeEv+0xda)[0x563dd09f0e2a]
      mariadbd(_Z12mysql_selectP3THDP10TABLE_LISTR4ListI4ItemEPS4_jP8st_orderS9_S7_S9_yP13select_resultP18st_select_lex_unitP13st_select_lex+0xd1)[0x563dd09f0f21]
      mariadbd(_Z13handle_selectP3THDP3LEXP13select_resulty+0x154)[0x563dd09f1774]
      mariadbd(+0x826f55)[0x563dd0964f55]
      mariadbd(_Z21mysql_execute_commandP3THDb+0x419e)[0x563dd0973f0e]
      mariadbd(_Z11mysql_parseP3THDPcjP12Parser_state+0x1e7)[0x563dd0975237]
      mariadbd(_Z16dispatch_command19enum_server_commandP3THDPcjb+0x14bd)[0x563dd0977a1d]
      mariadbd(_Z10do_commandP3THDb+0x138)[0x563dd0979818]
      mariadbd(_Z24do_handle_one_connectionP7CONNECTb+0x3bf)[0x563dd0aa13af]
      mariadbd(handle_one_connection+0x5d)[0x563dd0aa16fd]
      mariadbd(+0xcd1906)[0x563dd0e0f906]
      /lib/x86_64-linux-gnu/libc.so.6(+0x94ac3)[0x7f4ca750fac3]
      /lib/x86_64-linux-gnu/libc.so.6(+0x126a40)[0x7f4ca75a1a40]
      Trying to get some variables.
      Some pointers may be invalid and cause the dump to abort.
      

      Attachments

        Issue Links

          Activity

            oleg.smirnov Oleg Smirnov added a comment -

            The idea discussed during a meeting: move args[0]->charset_for_protocol() call to the preparation phase (fix_fields()) and remember the charset returned:

            String *Item_func_charset::val_str(String *str)
            {
              DBUG_ASSERT(fixed());
              uint dummy_errors;
             
              CHARSET_INFO *cs= args[0]->charset_for_protocol();
              null_value= 0;
              str->copy(cs->cs_name.str, cs->cs_name.length,
                        &my_charset_latin1, collation.collation, &dummy_errors);
              return str;
            }
            

            So we can safely set used_tables() to return 0 and avoid referring to arguments (args[0]) during the execution phase (call to val_str() is made during the execution).

            oleg.smirnov Oleg Smirnov added a comment - The idea discussed during a meeting: move args [0] ->charset_for_protocol() call to the preparation phase ( fix_fields() ) and remember the charset returned: String *Item_func_charset::val_str(String *str) { DBUG_ASSERT(fixed()); uint dummy_errors;   CHARSET_INFO *cs= args[0]->charset_for_protocol(); null_value= 0; str->copy(cs->cs_name.str, cs->cs_name.length, &my_charset_latin1, collation.collation, &dummy_errors); return str; } So we can safely set used_tables() to return 0 and avoid referring to arguments (args [0] ) during the execution phase (call to val_str() is made during the execution).
            oleg.smirnov Oleg Smirnov added a comment -

            sanja, can you please review the PR?

            oleg.smirnov Oleg Smirnov added a comment - sanja , can you please review the PR ?

            Hi oleg.smirnov,

            the patch is OK to push.

            I have just one small suggestion: Please change the data type of the new member from:

            CHARSET_INFO *m_cached_charset_info;
            

            to

            LEX_CSTRING m_cached_charset_info;
            

            to avoid strlen() evaluation per row by evaluating it during fix_length_and_dec() instead.

            Note, starting from 10.6 CHARSET_INFO was modified:

              const char *csname;
            

            was changed to:

              LEX_CSTRING cs_name;
            

            So starting from 10.6 strlen() won't be needed even in fix_length_and_dec().

            bar Alexander Barkov added a comment - Hi oleg.smirnov , the patch is OK to push. I have just one small suggestion: Please change the data type of the new member from: CHARSET_INFO *m_cached_charset_info; to LEX_CSTRING m_cached_charset_info; to avoid strlen() evaluation per row by evaluating it during fix_length_and_dec() instead. Note, starting from 10.6 CHARSET_INFO was modified: const char *csname; was changed to: LEX_CSTRING cs_name; So starting from 10.6 strlen() won't be needed even in fix_length_and_dec().
            oleg.smirnov Oleg Smirnov added a comment - - edited

            Good point, bar! Implemented your suggestion and pushed to 10.5 (commit)

            oleg.smirnov Oleg Smirnov added a comment - - edited Good point, bar ! Implemented your suggestion and pushed to 10.5 ( commit )

            Note for the changelog: if a query used a derived table DT (a CTE or a
            mergeable VIEW would work as well) and the WHERE clause compared columns
            of DT with the value of CHARSET() or COERCIBILITY() function, the query
            could produce wrong result or crash. The cause was incorrect processing
            of these functions by derived condition pushdown optimization (
            https://mariadb.com/kb/en/condition-pushdown-into-derived-table-optimization/)

            psergei Sergei Petrunia added a comment - Note for the changelog: if a query used a derived table DT (a CTE or a mergeable VIEW would work as well) and the WHERE clause compared columns of DT with the value of CHARSET() or COERCIBILITY() function, the query could produce wrong result or crash. The cause was incorrect processing of these functions by derived condition pushdown optimization ( https://mariadb.com/kb/en/condition-pushdown-into-derived-table-optimization/ )

            People

              oleg.smirnov Oleg Smirnov
              John Jove John Jove
              Votes:
              0 Vote for this issue
              Watchers:
              7 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.