Skip to content

Commit 2928ac7

Browse files
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 (and SHOW 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.
1 parent 40f9361 commit 2928ac7

3 files changed

Lines changed: 76 additions & 1 deletion

File tree

‎mysql-test/main/reopen_temp_table.result‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,31 @@ f b
243243
NULL 1
244244
NULL 2
245245
drop table t1;
246+
#
247+
# Start of 11.4 tests
248+
#
249+
#
250+
# MDEV-39609 - SIGSEGV in process_i_s_table_temporary_tables after failed ALTER TABLE on temporary TIMESTAMP table with CHECK constraint
251+
#
252+
CREATE TEMPORARY TABLE t (c INT KEY) ENGINE=INNODB;
253+
ALTER TABLE t MODIFY c TIMESTAMP;
254+
ALTER TABLE t ADD CHECK(c=0);
255+
ALTER TABLE t ADD INDEX idx1 (c);
256+
SET SESSION sql_mode='TRADITIONAL';
257+
ALTER TABLE t ROW_FORMAT=COMPRESSED;
258+
ERROR HY000: InnoDB refuses to write tables with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE.
259+
ALTER TABLE t ANALYZE PARTITION p2;
260+
ERROR HY000: Partition management on a not partitioned table is not possible
261+
SELECT table_schema, table_name, table_type, engine, temporary
262+
FROM information_schema.tables WHERE table_name='t';
263+
table_schema table_name table_type engine temporary
264+
test t TEMPORARY InnoDB Y
265+
INSERT INTO t VALUES (0);
266+
ERROR 22007: Incorrect datetime value: '0' for column `test`.`t`.`c` at row 1
267+
INSERT INTO t VALUES ('0000-00-00 00:00:00');
268+
ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column `test`.`t`.`c` at row 1
269+
SET SESSION sql_mode=DEFAULT;
270+
DROP TEMPORARY TABLE t;
271+
#
272+
# End of 11.4 tests
273+
#

‎mysql-test/main/reopen_temp_table.test‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,37 @@ alter table t1 change if exists a b int, algorithm=inplace;
226226
check table t1;
227227
select * from t1;
228228
drop table t1;
229+
230+
--echo #
231+
--echo # Start of 11.4 tests
232+
--echo #
233+
234+
--echo #
235+
--echo # MDEV-39609 - SIGSEGV in process_i_s_table_temporary_tables after failed ALTER TABLE on temporary TIMESTAMP table with CHECK constraint
236+
--echo #
237+
238+
CREATE TEMPORARY TABLE t (c INT KEY) ENGINE=INNODB;
239+
ALTER TABLE t MODIFY c TIMESTAMP;
240+
ALTER TABLE t ADD CHECK(c=0);
241+
ALTER TABLE t ADD INDEX idx1 (c);
242+
SET SESSION sql_mode='TRADITIONAL';
243+
244+
--error ER_UNSUPPORTED_COMPRESSED_TABLE
245+
ALTER TABLE t ROW_FORMAT=COMPRESSED;
246+
--error ER_PARTITION_MGMT_ON_NONPARTITIONED
247+
ALTER TABLE t ANALYZE PARTITION p2;
248+
249+
SELECT table_schema, table_name, table_type, engine, temporary
250+
FROM information_schema.tables WHERE table_name='t';
251+
252+
--error ER_TRUNCATED_WRONG_VALUE
253+
INSERT INTO t VALUES (0);
254+
--error ER_TRUNCATED_WRONG_VALUE
255+
INSERT INTO t VALUES ('0000-00-00 00:00:00');
256+
257+
SET SESSION sql_mode=DEFAULT;
258+
DROP TEMPORARY TABLE t;
259+
260+
--echo #
261+
--echo # End of 11.4 tests
262+
--echo #

‎sql/sql_class.h‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8168,10 +8168,23 @@ class Sql_mode_save_for_frm_handling: public Sql_mode_save
81688168
? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs
81698169
+ MODE_NO_BACKSLASH_ESCAPES affect expression parsing
81708170
+ MODE_EMPTY_STRING_IS_NULL affect expression parsing
8171+
+ MODE_STRICT_TRANS_TABLES affect stored default/expr validation
8172+
+ MODE_STRICT_ALL_TABLES affect stored default/expr validation
8173+
+ MODE_NO_ZERO_DATE affect stored default/expr validation
8174+
+ MODE_NO_ZERO_IN_DATE affect stored default/expr validation
8175+
8176+
The last four affect execution, not parsing, but must also be switched
8177+
off here: re-evaluating already-validated FRM defaults/CHECK expressions
8178+
when reopening a table (e.g. after a failed ALTER) must not turn a stored
8179+
zero DATE/TIMESTAMP into ER_WRONG_VALUE. Strictness applies only to newly
8180+
written values.
81718181
*/
81728182
thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
81738183
MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES |
8174-
MODE_ORACLE | MODE_EMPTY_STRING_IS_NULL);
8184+
MODE_ORACLE | MODE_EMPTY_STRING_IS_NULL |
8185+
MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
8186+
MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE);
8187+
81758188
};
81768189

81778190
~Sql_mode_save_for_frm_handling()

0 commit comments

Comments
 (0)