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

Crash: Prepared Statement with a '?' parameter inside a re-used CTE

    XMLWordPrintable

    Details

      Description

      I don't have a testcase, I only have a customer's core file.

      As far as I was able to investigate, the following has happened:

      1. There is a big query with nested SELECTs and non-recursive CTEs. Some CTEs are used multiple times.

      2. The query is submitted to server as a Prepared Statement. The prepared statement has many '?' parameters.

      3. [At least] one of the parameters is inside in a CTE that's reused and it used like so:

         WHERE 
            table.key= ?
      

      We crash in optimize_keyuse(), when we are trying to process a KEYUSE element created from the above equality.

      We crash somewhere here:

       
          if (keyuse->used_tables &
      	(map= (keyuse->used_tables & ~join->const_table_map &
      	       ~OUTER_REF_TABLE_BIT)))
          {
            uint n_tables= my_count_bits(map);
            if (n_tables == 1)			// Only one table
            {
              Table_map_iterator it(map);
              int tablenr= it.next_bit();
              DBUG_ASSERT(tablenr != Table_map_iterator::BITMAP_END);
      	TABLE *tmp_table=join->table[tablenr];
              if (tmp_table) // already created
                keyuse->ref_table_rows= MY_MAX(tmp_table->file->stats.records, 100);
            }
      

      The cause is that the keyuse has:

      keyuse->used_tables = PARAM_TABLE_BIT
      keyuse->val = Item_param
      

      With PARAM_TABLE_BIT, the "if (n_tables == 1)" branch is taken, and we get a tablenr value, but join->table[tablenr] is not pointing to a valid TABLE object hence we get a poorly-reproducible crash.

      We should not get {{ keyuse->used_tables = PARAM_TABLE_BIT}}. We do, because

      $keyuse->val->state == Item_param::NO_VALUE
      

      (which also shouldn't be happening).

      There is Prepared_statement::param_array which is an array of "primary" parameter instances, and

      $keyuse->val != $prepared_statement->param_array[$i] for any value of $i.
      

      However, I can find $keyuse->val in

      $prepared_statement->param_array[$a].m_clones.m_array[$b]
      

      That is, it is a "secondary" Item_param object that was created for a CTE.

      Further, I observe that

      • The "primary" Item_param objects from $prepared_statement->param_array[i] all have state=Item_param::SHORT_DATA_VALUE or other similar states
      • The "secondary" Item_param objects from "m_clones" arrays all have state=Item_param::NO_VALUE.

        Attachments

          Activity

            People

            Assignee:
            psergey Sergei Petrunia
            Reporter:
            psergey Sergei Petrunia
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: