From 8b93a931d2b1f17cd4150598dff01070b98cb228 Mon Sep 17 00:00:00 2001 From: PranavKTiwari Date: Wed, 22 Jul 2026 18:26:55 +0530 Subject: [PATCH] MDEV-39609 - SIGSEGV in process_i_s_table_temporary_tables after failed ALTER TABLE on temporary TIMESTAMP table with CHECK constraint Problem: SELECT * FROM information_schema.tables crashed with a SIGSEGV in process_i_s_table_temporary_tables() after a failed strict-mode ALTER TABLE on a TEMPORARY table with a zero-default TIMESTAMP column and a CHECK constraint. Cause: The failed ALTER marks the temp table needs_reopen. On reopen, Sql_mode_save_for_frm_handling relaxed only parser flags, not the strict/zero-date ones, so evaluating the stored zero TIMESTAMP default was escalated to ER_WRONG_VALUE. open_temporary_table() then failed, leaving the TMP_TABLE_SHARE in temporary_tables with an empty all_tmp_tables. The I_S iteration walked into that empty share and dereferenced a NULL TABLE. Regression in 11.4. Fix: Broadened Sql_mode_save_for_frm_handling to also clear MODE_STRICT_TRANS_TABLES, MODE_STRICT_ALL_TABLES, MODE_NO_ZERO_DATE, and MODE_NO_ZERO_IN_DATE while parsing FRM-stored defaults/expressions. Reopening an already-validated temp table now succeeds in any sql_mode, so the empty share is never created and the crash is gone; strictness still applies when new values are written. --- mysql-test/main/reopen_temp_table.result | 28 +++++++++++++++++++ mysql-test/main/reopen_temp_table.test | 34 ++++++++++++++++++++++++ sql/sql_class.h | 15 ++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/reopen_temp_table.result b/mysql-test/main/reopen_temp_table.result index ef215366db7ae..f1d24673b1cfd 100644 --- a/mysql-test/main/reopen_temp_table.result +++ b/mysql-test/main/reopen_temp_table.result @@ -243,3 +243,31 @@ f b NULL 1 NULL 2 drop table t1; +# +# Start of 11.4 tests +# +# +# MDEV-39609 - SIGSEGV in process_i_s_table_temporary_tables after failed ALTER TABLE on temporary TIMESTAMP table with CHECK constraint +# +CREATE TEMPORARY TABLE t (c INT KEY) ENGINE=INNODB; +ALTER TABLE t MODIFY c TIMESTAMP; +ALTER TABLE t ADD CHECK(c=0); +ALTER TABLE t ADD INDEX idx1 (c); +SET SESSION sql_mode='TRADITIONAL'; +ALTER TABLE t ROW_FORMAT=COMPRESSED; +ERROR HY000: InnoDB refuses to write tables with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +ALTER TABLE t ANALYZE PARTITION p2; +ERROR HY000: Partition management on a not partitioned table is not possible +SELECT table_schema, table_name, table_type, engine, temporary +FROM information_schema.tables WHERE table_name='t'; +table_schema table_name table_type engine temporary +test t TEMPORARY InnoDB Y +INSERT INTO t VALUES (0); +ERROR 22007: Incorrect datetime value: '0' for column `test`.`t`.`c` at row 1 +INSERT INTO t VALUES ('0000-00-00 00:00:00'); +ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column `test`.`t`.`c` at row 1 +SET SESSION sql_mode=DEFAULT; +DROP TEMPORARY TABLE t; +# +# End of 11.4 tests +# diff --git a/mysql-test/main/reopen_temp_table.test b/mysql-test/main/reopen_temp_table.test index 3d621fbbc56f4..2d639032c0277 100644 --- a/mysql-test/main/reopen_temp_table.test +++ b/mysql-test/main/reopen_temp_table.test @@ -226,3 +226,37 @@ alter table t1 change if exists a b int, algorithm=inplace; check table t1; select * from t1; drop table t1; + +--echo # +--echo # Start of 11.4 tests +--echo # + +--echo # +--echo # MDEV-39609 - SIGSEGV in process_i_s_table_temporary_tables after failed ALTER TABLE on temporary TIMESTAMP table with CHECK constraint +--echo # + +CREATE TEMPORARY TABLE t (c INT KEY) ENGINE=INNODB; +ALTER TABLE t MODIFY c TIMESTAMP; +ALTER TABLE t ADD CHECK(c=0); +ALTER TABLE t ADD INDEX idx1 (c); +SET SESSION sql_mode='TRADITIONAL'; + +--error ER_UNSUPPORTED_COMPRESSED_TABLE +ALTER TABLE t ROW_FORMAT=COMPRESSED; +--error ER_PARTITION_MGMT_ON_NONPARTITIONED +ALTER TABLE t ANALYZE PARTITION p2; + +SELECT table_schema, table_name, table_type, engine, temporary +FROM information_schema.tables WHERE table_name='t'; + +--error ER_TRUNCATED_WRONG_VALUE +INSERT INTO t VALUES (0); +--error ER_TRUNCATED_WRONG_VALUE +INSERT INTO t VALUES ('0000-00-00 00:00:00'); + +SET SESSION sql_mode=DEFAULT; +DROP TEMPORARY TABLE t; + +--echo # +--echo # End of 11.4 tests +--echo # diff --git a/sql/sql_class.h b/sql/sql_class.h index 0bd5b73ad28bf..572c7db945f7b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -8168,10 +8168,23 @@ class Sql_mode_save_for_frm_handling: public Sql_mode_save ? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs + MODE_NO_BACKSLASH_ESCAPES affect expression parsing + MODE_EMPTY_STRING_IS_NULL affect expression parsing + + MODE_STRICT_TRANS_TABLES affect stored default/expr validation + + MODE_STRICT_ALL_TABLES affect stored default/expr validation + + MODE_NO_ZERO_DATE affect stored default/expr validation + + MODE_NO_ZERO_IN_DATE affect stored default/expr validation + + The last four affect execution, not parsing, but must also be switched + off here: re-evaluating already-validated FRM defaults/CHECK expressions + when reopening a table (e.g. after a failed ALTER) must not turn a stored + zero DATE/TIMESTAMP into ER_WRONG_VALUE. Strictness applies only to newly + written values. */ thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES | - MODE_ORACLE | MODE_EMPTY_STRING_IS_NULL); + MODE_ORACLE | MODE_EMPTY_STRING_IS_NULL | + MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES | + MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE); + }; ~Sql_mode_save_for_frm_handling()