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

Slave SQL Thread Overflow on Malformed Table_map_log_event

    XMLWordPrintable

Details

    • Can result in hang or crash
    • Q3/2026 Replic. Development

    Description

      A replication source can overflow a heap buffer on its replica by sending a
      Table_map event that declares an over-long database or table name.

      The table name and database name are allocated length NAME_LEN+1

        if (!(memory= my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
                                      &table_list, (uint) sizeof(RPL_TABLE_LIST),
                                      &db_mem, (uint) NAME_LEN + 1,
                                      &tname_mem, (uint) NAME_LEN + 1,
                                      NullS)))
      

      Table_map_log_event::do_apply_event() copies the names of the table
      and database directly into this memory without bounds checking:

        db_mem_length=    strmov(db_mem, m_dbnam) - db_mem;
        tname_mem_length= strmov(tname_mem, m_tblnam) - tname_mem;
      

      NAME_LEN is 192, so each block is requested at 193 bytes and rounded to
      200 by my_multi_malloc. A declared length of 255 therefore writes 256
      bytes into 200. db_mem is the middle block, so overflowing it corrupts
      tname_mem inside the same allocation; tname_mem is the last block, so
      overflowing it writes 56 bytes past the end of the region.

      A second defect makes the overflow unbounded rather than 56 bytes.
      strncpy(m_dbnam, ptr_dblen + 1, m_dblen + 1)
      (sql/log_event.cc:3754) does not terminate when none of the source bytes
      is zero. With both lengths at 255 the ALIGN_SIZE rounding leaves
      m_dbnam, m_tblnam and m_coltype contiguous with no intervening
      zero byte, so strmov runs through all three and past the end of
      m_memory until it meets a zero somewhere in the heap.

      The same missing terminator lets Table_map_log_event::pack_info()
      (sql/log_event_server.cc:6161) read past m_memory through a %s,
      disclosing heap bytes through SHOW BINLOG EVENTS and SHOW RELAYLOG EVENTS.

      To reproduce:

      Patch file:

      --- a/sql/log_event_server.cc
      +++ b/sql/log_event_server.cc
      @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ...)
         DBUG_ASSERT(tbl->s->table_name.str[tbl->s->table_name.length] == 0);
       
      +  DBUG_EXECUTE_IF("corrupt_table_map_tbllen",
      +  {
      +    char *nam= (char*) thd->alloc(256);
      +    memset(nam, 'a', 255);
      +    nam[255]= 0;
      +    m_tblnam= nam;
      +    m_tbllen= 255;
      +  });
      +
         binlog_type_info_array= ...
       
      @@ Table_map_log_event::write_data_body()
      -  DBUG_ASSERT(m_tbllen <= MY_MIN(NAME_LEN, 255));
      +  DBUG_ASSERT(m_tbllen <= MY_MIN(NAME_LEN, 255) ||
      +              DBUG_EVALUATE_IF("corrupt_table_map_tbllen", 1, 0));
      

      Test file:

      --source include/have_debug.inc
      --source include/have_binlog_format_row.inc
      --source include/master-slave.inc
       
      --connection master
      create table t1 (a int);
      set @@session.debug_dbug= "+d,corrupt_table_map_tbllen";
      insert into t1 values (1);
      set @@session.debug_dbug= "";
      --source include/save_master_gtid.inc
       
      # do_apply_event() copies the 256-byte name into a 193-byte block. The sync
      # below only holds the test open; the replica dies in the strmov.
      --connection slave
      --source include/sync_with_master_gtid.inc
      

      Attachments

        Issue Links

          Activity

            People

              bnestere Brandon Nesterenko
              bnestere Brandon Nesterenko
              Brandon Nesterenko Brandon Nesterenko
              Kristian Nielsen Kristian Nielsen
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Time Tracking

                  Estimated:
                  Original Estimate - 1d
                  1d
                  Remaining:
                  Time Spent - 1h Remaining Estimate - 7h
                  7h
                  Logged:
                  Time Spent - 1h Remaining Estimate - 7h
                  1h

                  Git Integration

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