From 8db5274dce7f8710b25ca954559843c9cd812ac5 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 21 Feb 2021 20:38:32 +0200 Subject: [PATCH] MDEV-22703 DEFAULT() on a BLOB column can overwrite the default record This can cause crashes when accessing already released memory The issue was the Item_default created a internal field, pointing to share->default_values, to be used with the DEFAULT() function. This does not work for BLOB fields as these are freed at end of query. Fixed by storing BLOB field data inside and area allocated by Item_default_value, like we do for nondeterministic default values. --- mysql-test/main/default.result | 15 +++++++++++++++ mysql-test/main/default.test | 19 ++++++++++++++++++- sql/item.cc | 5 +++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/default.result b/mysql-test/main/default.result index cf0788b2fb2..f5ee1474b94 100644 --- a/mysql-test/main/default.result +++ b/mysql-test/main/default.result @@ -3390,3 +3390,18 @@ ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ERROR 42S22: Unknown column 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in 'DEFAULT' DROP TABLE t1; # end of 10.2 test +# +# MDEV-22703 DEFAULT() on a BLOB column can overwrite the default +# record, which can cause crashes when accessing already released +# memory. +# +CREATE TEMPORARY TABLE t1 (h POINT DEFAULT ST_GEOMFROMTEXT('Point(1 1)')) ENGINE=InnoDB; +INSERT INTO t1 () VALUES (),(); +ALTER TABLE t1 FORCE; +SELECT DEFAULT(h) FROM t1; +SELECT length(DEFAULT(h)) FROM t1; +length(DEFAULT(h)) +25 +25 +INSERT INTO t1 () VALUES (); +drop table t1; diff --git a/mysql-test/main/default.test b/mysql-test/main/default.test index 27e38eeeb49..c0561deac67 100644 --- a/mysql-test/main/default.test +++ b/mysql-test/main/default.test @@ -1,3 +1,5 @@ +--source include/have_innodb.inc + # # test of already fixed bugs # @@ -2107,5 +2109,20 @@ CREATE OR REPLACE TABLE t1(i int); ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`; DROP TABLE t1; - --echo # end of 10.2 test + +--echo # +--echo # MDEV-22703 DEFAULT() on a BLOB column can overwrite the default +--echo # record, which can cause crashes when accessing already released +--echo # memory. +--echo # + +CREATE TEMPORARY TABLE t1 (h POINT DEFAULT ST_GEOMFROMTEXT('Point(1 1)')) ENGINE=InnoDB; +INSERT INTO t1 () VALUES (),(); +ALTER TABLE t1 FORCE; +--disable_result_log +SELECT DEFAULT(h) FROM t1; +--enable_result_log +SELECT length(DEFAULT(h)) FROM t1; +INSERT INTO t1 () VALUES (); +drop table t1; diff --git a/sql/item.cc b/sql/item.cc index cd81aca7e37..f2324645d22 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9346,8 +9346,9 @@ bool Item_default_value::fix_fields(THD *thd, Item **items) memcpy((void *)def_field, (void *)field_arg->field, field_arg->field->size_of()); def_field->reset_fields(); - // If non-constant default value expression - if (def_field->default_value && def_field->default_value->flags) + // If non-constant default value expression or a blob + if (def_field->default_value && + (def_field->default_value->flags || def_field->flags & BLOB_FLAG)) { uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length()); if (!newptr)