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

MySQL Bug#13996639 CRASH IN ITEM_REF::FIX_FIELDS ON EXEC OF STORED FUNCTION WITH ONLY_FULL_GROUP_BY

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Cannot Reproduce
    • Affects Version/s: 10.0.9
    • Fix Version/s: N/A
    • Component/s: None
    • Labels:
      None

      Description

      The following revision doesn't seem to be merged into 10.0. Found while analyzing result difference in ps_ddl1.test:

      revno: 4591.1.70
      committer: Guilhem Bichot <guilhem.bichot@oracle.com>
      branch nick: 5.6-3
      timestamp: Sat 2012-11-24 15:45:56 +0100
      message:
        fix for Bug#13996639 CRASH IN ITEM_REF::FIX_FIELDS ON EXEC OF STORED
        FUNCTION WITH ONLY_FULL_GROUP_BY. See per-file comments.
      
        mysql-test/r/ps_ddl1.result:
          side affect of the bugfix; this is a good change, as the removed comment says.
        sql/sql_lex.cc:
          LEX starts clean
        sql/sql_optimizer.cc:
          If optimize () fails, tag the Lex as "broken"
        sql/sql_parse.cc:
          At first execution of:
           SELECT stored_func()
          this happens:
          1) body of stored_func is read from mysql.proc
          2) body is parsed (sp_compile()) (for each substatement a LEX and some
          Items are created)
          3) parsing went ok so parse trees are cached (sp_cache_insert())
          4) substatement starts executing (SELECT with a NOT IN (subq))
          4.1) Item_in_subselect::fix_fields():
            if (!(res= engine->prepare()))
            {
                (*ref)= substitution;
          engine->prepare() calls JOIN::prepare() on subq, which calls
          resolve_subquery() which starts IN2EXISTS transformation: adds
          conditions (using some new Item_ref) to the subquery's WHERE, creates
          Item_in_optimizer and puts it in 'substitution'. After
          resolve_subquery(), JOIN::prepare() of subq fails in:
      
              my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
                         ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
              DBUG_RETURN(-1);
      
          So far, so good.
          Thus engine->prepare() fails. Thus we don't do:
            (*ref)= substitution;
          i.e. the parent of the subquery continues to have its WHERE point to
          Item_in_subselect. At this stage we have a broken parse tree, because
          subq has been transformed but parent query points to pre-transform
          subq. This mess is not rolled back (IN2EXISTS is a complex transform
          which does not use change_item_tree()).
          ER_MIX_OF_GROUP_FUNC_AND_FIELDS is sent to client.
          So far, so good.
      
          At 2nd execution of:
           SELECT stored_func()
          this happens:
          1) cached parse trees of stored_func is read from cache
          2) but this is the broken parse tree!
          3) as the Item_ref depends on Item_in_optimizer::fix_fields() to set
          its '*ref', and as Item_in_optimizer was not stored in parent query,
          Item_in_optimizer::fix_fields() is not called, so
          Item_ref::fix_fields() crashes.
      
          Summary: first execution broke Item_in_subselect/LEX, 2nd execution reused it.
      
          Solution: first execution marks the fact that it
          broke LEX; 2nd execution sees the mark and asks for a
          reprepare, which creates new parse trees, and thus works as the first
          execution.
          A new member m_broken is added to class LEX. It is set to "true" when
          JOIN:: prepare () or JOIN:: optimize () fail, because it is possible
          that those functions were doing transformations. It is set to "false"
          when the Lex is initialized.
        sql/sql_resolver.cc:
          If prepare () fails, tag the Lex as "broken"
      

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

              Hide
              serg Sergei Golubchik added a comment -

              MariaDB doesn't seem to be vulnerable, I mean, there's no crash in this case.

              Show
              serg Sergei Golubchik added a comment - MariaDB doesn't seem to be vulnerable, I mean, there's no crash in this case.

                People

                • Assignee:
                  serg Sergei Golubchik
                  Reporter:
                  svoj Sergey Vojtovich
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  2 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:

                    Time Tracking

                    Estimated:
                    Original Estimate - Not Specified
                    Not Specified
                    Remaining:
                    Remaining Estimate - 0 minutes
                    0m
                    Logged:
                    Time Spent - 1 hour
                    1h