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

Unchecked get_clone() in ALTER of partitioned table crashes on out-of-memory

    XMLWordPrintable

Details

    • Can result in hang or crash
    • Q4/2026 Server Maintenance

    Description

      partition_info::get_clone() returns NULL when allocation fails. Most callers check it:

      if (!(tab_part_info= tab_part_info->get_clone(thd)))
        DBUG_RETURN(TRUE);
      

      Three callers in sql_partition.cc do not, and dereference the result right away. Out-of-memory during the ALTER crashes the server instead of failing the statement with ER_OUT_OF_RESOURCES.

      Function Statement Since
      prep_alter_part_table() ALTER ... PARTITION BY SYSTEM_TIME with a changed INTERVAL MDEV-27328, 10.9.1
      prep_alter_part_table() ALTER ... ADD PARTITION under LOCK TABLES MDEV-14817, 10.3.4
      handle_alter_part_error() any failed fast ALTER of partitions MySQL legacy, every call since Bug#19784790, 10.5.3

      prep_alter_part_table(), SYSTEM_TIME INTERVAL

      /* If interval is changed we can not do fast alter */
      tab_part_info= tab_part_info->get_clone(thd);
      ...
      *tab_part_info->vers_info= *part_info->vers_info;
      

      prep_alter_part_table(), ADD PARTITION under LOCK TABLES

      saved_part_info= tab_part_info->get_clone(thd);
      thd->mem_root= old_root;
      saved_part_info->read_partitions= tab_part_info->read_partitions;
      

      handle_alter_part_error()

      The clone here is made only to keep the DDL log entries (list, execute_entry) after the table is closed, because closing the table frees lpt->part_info. Besides the missing NULL check, the branch where DDL log recovery fails is wrong:

      write_log_completed(lpt, FALSE);   // releases entries via lpt->part_info
      release_log_entries(part_info);    // releases the same entries via the clone
      

      • write_log_completed() reads lpt->part_info, which the table close may already have freed.
      • The entries are released twice. A released entry gets next_active_log_entry= 0x1, so the second release follows that pointer and crashes.

      This branch is currently unreachable: ddl_log_execute_entry() always returns false. It is still wrong and will crash once recovery can report failure.

      How to repeat

      Needs a debug build and an injection point right before get_clone() that turns on simulate_out_of_memory, so the clone's allocation fails. The fix adds one named prep_alter_part_table_get_clone_oom.

      --source include/have_debug.inc
      --source include/have_partition.inc
       
      create table t1 (x int) with system versioning
      partition by system_time interval 1 hour partitions 3;
      set @@debug_dbug= '+d,prep_alter_part_table_get_clone_oom';
      --error ER_OUT_OF_RESOURCES
      alter table t1 partition by system_time interval 2 hour;
      set @@debug_dbug= default;
      drop table t1;
       
      create table t1 (x int) partition by range (x)
      (partition p0 values less than (10));
      lock tables t1 write;
      set @@debug_dbug= '+d,prep_alter_part_table_get_clone_oom';
      --error ER_OUT_OF_RESOURCES
      alter table t1 add partition (partition p1 values less than (20));
      set @@debug_dbug= default;
      unlock tables;
      drop table t1;
      

      Without the fix both ALTERs crash with a NULL pointer dereference in prep_alter_part_table().

      Fix

      • prep_alter_part_table(): check the get_clone() result like the other callers do.
      • handle_alter_part_error(): keep a copy of DDL_LOG_STATE instead of cloning part_info. Nothing is allocated, so nothing can fail. Pass it to write_log_completed() and release_log_entries(), which now take DDL_LOG_STATE *. The first call releases the entries and clears the pointers, so the second call does nothing.

      Attachments

        Issue Links

          Activity

            People

              midenok Aleksey Midenkov
              midenok Aleksey Midenkov
              Oleksandr Byelkin Oleksandr Byelkin
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - 2d 2h 34m
                  2d 2h 34m
                  Remaining:
                  Remaining Estimate - 0d
                  0d
                  Logged:
                  Time Spent - 1h 5m Time Not Required
                  1h 5m

                  Git Integration

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