Skip to content
/ server Public

MDEV-38716: Server crashes in TABLE::evaluate_update_default_function#4609

Merged
bnestere merged 1 commit intomainfrom
main-MDEV-38716
Feb 4, 2026
Merged

MDEV-38716: Server crashes in TABLE::evaluate_update_default_function#4609
bnestere merged 1 commit intomainfrom
main-MDEV-38716

Conversation

@bnestere
Copy link
Contributor

@bnestere bnestere commented Feb 2, 2026

This patch fixes two issues:

Problem (1)
A regression from MDEV-36290 would cause the server to crash when one uses TIMESTAMP or DATETIME types with option ON UPDATE. The root cause of this is actually from problem (2) described below, MDEV-36290 simply forced the bug to be revealed.

Problem (2)
After a table is rebuilt (i.e. via ALTER TABLE .. FORCE), any fields which use ON UPDATE lose the update trigger after the ALTER. This is because recreated fields (i.e those in alter_info->create_list) had no checks to ensure their representation in the target table's default_fields list. The intent is provided by the following code comment:

/*
  Update the set of auto-update fields to contain only the new fields
  added to the table. Only these fields should be updated automatically.
  Old fields keep their current values, and therefore should not be
  present in the set of autoupdate fields.
*/

However, fields with trigger-based default values were left unconsidered.

Linking back to problem (1), the crash happened because of the following MDEV-36290 changes:

diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 13ed810cac2..5cc74785ef7 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -12737,7 +12737,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
     }
   }
   if (dfield_ptr)
-    *dfield_ptr= NULL;
+  {
+    if (dfield_ptr == to->default_field)
+      to->default_field= 0; // No default fields left
+    else
+      *dfield_ptr= NULL; // Mark end of default field pointers
+  }

That is, the destination table's default_field becomes nullified when no default_field changes exist. However, because ON UPDATE default_fields were not moved to the destination table, the server would crash with a segfault when updating the records in the post-ALTER table (in TABLE::evaluate_update_default_function()) because it would de-reference the nullified pointer in default_field.

The fix for these problems is the same. The default_field information is copied from these recreated fields when default values are used later by ON UPDATE options.

Note a number of tests currently fail from this change, which seem to rely on losing ON UPDATE options. I don't see that behavior documented anywhere, so it seems to me these tests rely on bugged behavior. But before fixing these tests, I'd like the general idea reviewed.

@bnestere bnestere requested a review from montywi February 2, 2026 19:58
@bnestere bnestere added MariaDB Corporation Replication Patches involved in replication labels Feb 2, 2026
@bnestere bnestere force-pushed the main-MDEV-38716 branch 5 times, most recently from 21d37d4 to 5d9df52 Compare February 4, 2026 19:46
This patch fixes two issues:

Problem (1)
A regression from MDEV-36290 would cause the server to crash when one
uses TIMESTAMP or DATETIME types with option ON UPDATE. The root cause
of this is actually from problem (2) described below, MDEV-36290 simply
forced the bug to be revealed.

Problem (2)
After a table is rebuilt (i.e. via ALTER TABLE .. FORCE), any fields
which use ON UPDATE lose the update trigger after the ALTER. This is
because recreated fields (i.e those in alter_info->create_list) had no
checks to ensure their representation in the target table's
default_fields list. The intent is provided by the following code
comment:

/*
  Update the set of auto-update fields to contain only the new fields
  added to the table. Only these fields should be updated automatically.
  Old fields keep their current values, and therefore should not be
  present in the set of autoupdate fields.
*/

However, fields with trigger-based default values were left
unconsidered.

Linking back to problem (1), the crash happened because of the
following MDEV-36290 changes:

diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 13ed810..5cc7478 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -12737,7 +12737,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
     }
   }
   if (dfield_ptr)
-    *dfield_ptr= NULL;
+  {
+    if (dfield_ptr == to->default_field)
+      to->default_field= 0; // No default fields left
+    else
+      *dfield_ptr= NULL; // Mark end of default field pointers
+  }

That is, the destination table's default_field becomes nullified when
no default_field changes exist. However, because ON UPDATE
default_fields were not moved to the destination table, the server
would crash with a segfault when updating the records in the
post-ALTER table (in TABLE::evaluate_update_default_function()) because
it would de-reference the nullified pointer in default_field.

The fix for these problems is the same. ON UPDATE based default_fields
are added back to the destination table after the actual data copy.
Note this must be done after the data copy for fields which have both
DEFAULT and ON UPDATE set for timestamps.

Additionally, this patch removes the set/reset of
table->s->default_fields from TABLE::evaluate_update_default_function()
because it is no longer used when updating default fields. The
functions that use default_field use the NULL terminator at the end
of the list to stop iteration.

This patch adds a test case to main.temp_table to test the case of
a table with a field column with a NULL default value but
ON UPDATE CURRENT_TIMESTAMP. Existing MTR tests have cases for
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP (i.e. any test
which deals with upgrades, e.g. main.upgrade_mdev_24363 and
main.mysql_upgrade_mysql_json_with_plugin_loaded).

Reviewed-by: Monty <monty@mariadb.com>
Signed-off-by: Brandon Nesterenko <brandon.nesterenko@mariadb.com>
@bnestere bnestere merged commit fa36b26 into main Feb 4, 2026
15 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

MariaDB Corporation Replication Patches involved in replication

Development

Successfully merging this pull request may close these issues.

2 participants