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

Sp_handler::sp_drop_routine_internal() silently swallows a ha_delete_row() failure inside CREATE OR REPLACE FUNCTION/PROCEDURE

    XMLWordPrintable

Details

    • Bug
    • Status: Approved (View Workflow)
    • Major
    • Resolution: Unresolved
    • 10.11, 11.4
    • 11.4
    • Stored routines
    • None

    Description

      Sp_handler::sp_drop_routine_internal() (sql/sp.cc) deletes the existing mysql.proc row when CREATE OR REPLACE FUNCTION/PROCEDURE replaces a routine that already exists:

      int
      Sp_handler::sp_drop_routine_internal(THD *thd,
                                           const Database_qualified_name *name,
                                           TABLE *table) const
      {
        DBUG_ENTER("sp_drop_routine_internal");
       
        if (table->file->ha_delete_row(table->record[0]))
          DBUG_RETURN(SP_DELETE_ROW_FAILED);
        ...
      

      If ha_delete_row() fails, the function returns SP_DELETE_ROW_FAILED without ever calling my_error(). The only caller, Sp_handler::sp_create_routine(), doesn't push an error either:

      case SP_TYPE_FUNCTION:
      case SP_TYPE_PROCEDURE:
        if (sp_drop_routine_internal(thd, sp, table))
          goto done;     // sql/sp.cc:1286 — no my_error() on this path
      

      done: returns ret (still TRUE, i.e. failure) up through mysql_create_routine() → mysql_execute_command(). Nothing along that chain pushes an error into the Diagnostics_area, and mysql_parse() discards mysql_execute_command()'s return value (int error _attribute_((unused)). The statement therefore finishes with an empty Diagnostics_area (DA_EMPTY).

      Protocol::end_statement() (sql/protocol.cc) hits DBUG_ASSERT(0) on the DA_EMPTY case, then falls through to send_ok() regardless:

      case Diagnostics_area::DA_EMPTY:
      default:
        DBUG_ASSERT(0);
        error= send_ok(thd->server_status, 0, 0, 0, NULL);
        break;
      

      Impact:

      • Debug builds: the DBUG_ASSERT(0) aborts the server (SIGABRT) on a routine ha_delete_row() failure during CREATE OR REPLACE.
      • Release builds: DBUG_ASSERT is a no-op, so the server silently sends the client an OK for a statement that actually failed. The routine'sd never reinserted, and itsmysql.procs_priv grants are left dangling — with no error reported anywhere.

      ha_delete_row() can fail for ordinary operational reasons (disk full, I/O error, storage-engine
      lock-wait timeout, corrupted table) —l.

      Reproduction (debug build):

      Add a temporary fault-injection pointe_internal():

      DBUG_EXECUTE_IF("sp_drop_routine_inte
                      DBUG_RETURN(SP_DELETE_ROW_FAILED););
      

      Then:

      CREATE FUNCTION f1() RETURNS INT RETURN 1;
      SET @@session.debug_dbug="+d,sp_drop_
      CREATE OR REPLACE FUNCTION f1() RETURNS INT RETURN 2;
      

      Server crashes:
      mariadbd: sql/protocol.cc:618: void Pertion `0' failed.

      Suggested fix direction: sp_drop_rout_error(ER_SP_DROP_FAILED, MYF(0),type_str(), name->m_name.str) (or similar) before returning SP_DELETE_ROW_FAILED, mirroring the sibling
      ha_write_row() failure a few lines la/sp.cc:1475, which does callmy_error(ER_SP_ALREADY_EXISTS, ...)).

      Found while working on: MDEV-39993 (unrelated fix; this is a pre-existing, separate defect surfaced during code review of that patch, andut of scope for a scripts-onlychange).

      Attachments

        Issue Links

          Activity

            People

              bar Alexander Barkov
              sanja Oleksandr Byelkin
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:

                Time Tracking

                  Estimated:
                  Original Estimate - 0.25d
                  0.25d
                  Remaining:
                  Time Spent - 0.75h Remaining Estimate - 1.25h
                  1.25h
                  Logged:
                  Time Spent - 0.75h Remaining Estimate - 1.25h
                  0.75h

                  Git Integration

                    Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.