From bb17094be484a4cbf94e21a96c2dbb2930ae7ac4 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 25 Apr 2019 09:50:01 +0400 Subject: [PATCH] MDEV-18452 ASAN unknown-crash in Field::set_default upon SET bit_column = DEFAULT Field_bit for BIT(20) uses 2 full bytes in the record, with additional 4 uneven bits in the "null bit area". Field::set_default() called from Field_bit::set_default() erroneously copied 3 bytes instead of 2 bytes from the record with default values. Changing Field::set_default() to copy pack_length_in_rec() bytes instead of pack_length() bytes. --- mysql-test/r/type_bit.result | 7 +++++++ mysql-test/t/type_bit.test | 10 ++++++++++ sql/field.h | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index 4136eb4dff7..f460d05e2a9 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -830,3 +830,10 @@ def COALESCE(val, 1) 246 2 1 Y 32896 0 63 COALESCE(val, 1) 0 DROP TABLE t1; +# +# MDEV-18452 ASAN unknown-crash in Field::set_default upon SET bit_column = DEFAULT +# +CREATE TABLE t1 (b BIT(20)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (0); +UPDATE t1 SET b = DEFAULT; +DROP TABLE t1; diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index 01a610999bd..4df6d72ce9a 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -458,3 +458,13 @@ DROP TABLE t2; SELECT COALESCE(val, 1) FROM t1; --disable_metadata DROP TABLE t1; + + +--echo # +--echo # MDEV-18452 ASAN unknown-crash in Field::set_default upon SET bit_column = DEFAULT +--echo # + +CREATE TABLE t1 (b BIT(20)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (0); +UPDATE t1 SET b = DEFAULT; +DROP TABLE t1; diff --git a/sql/field.h b/sql/field.h index 86853f7d9d9..2243f8499fe 100644 --- a/sql/field.h +++ b/sql/field.h @@ -854,7 +854,7 @@ public: { my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values - table->record[0]); - memcpy(ptr, ptr + l_offset, pack_length()); + memcpy(ptr, ptr + l_offset, pack_length_in_rec()); if (maybe_null_in_table()) *null_ptr= ((*null_ptr & (uchar) ~null_bit) | (null_ptr[l_offset] & null_bit));