diff options
author | Alexander Barkov <bar@mariadb.com> | 2021-10-09 22:27:31 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2021-10-11 18:03:42 +0400 |
commit | 8f04ec288528fd53efd98e2139e5d22ba229d20b (patch) | |
tree | 9ea889eb32052021c167e6f574c6a1b835089f0f | |
parent | eadd87880887e6ca73e6f292c9d856df7e56c3c0 (diff) | |
download | mariadb-git-8f04ec288528fd53efd98e2139e5d22ba229d20b.tar.gz |
MDEV-25925 Warning: Memory not freed: 32 on INSERT DELAYEDbb-10.2-bar-MDEV-25925
Also fixes MDEV-24467 Memory not freed after failed INSERT DELAYED
Description:
In case of an error (e.g. data truncation) during mysql_insert()
handling an INSERT DELAYED, the data type specific data in
fields (e.g. Field_blob::value) is not taken over by the delayed
writer thread.
All fields in table_list->table are freed by free_root()
immediately after mysql_insert(). To avoid a memory leak,
we need to free the specific data before exiting mysql_insert()
on error.
-rw-r--r-- | mysql-test/r/delayed_blob.result | 17 | ||||
-rw-r--r-- | mysql-test/t/delayed_blob-master.opt | 1 | ||||
-rw-r--r-- | mysql-test/t/delayed_blob.test | 21 | ||||
-rw-r--r-- | sql/sql_insert.cc | 11 |
4 files changed, 50 insertions, 0 deletions
diff --git a/mysql-test/r/delayed_blob.result b/mysql-test/r/delayed_blob.result new file mode 100644 index 00000000000..caa2e3ae5fe --- /dev/null +++ b/mysql-test/r/delayed_blob.result @@ -0,0 +1,17 @@ +# +# MDEV-25925 Warning: Memory not freed: 32 on INSERT DELAYED +# +SET sql_mode='TRADITIONAL'; +CREATE TABLE t1 (c BLOB) ENGINE=MyISAM; +INSERT DELAYED INTO t1 VALUES (''||''); +ERROR 22007: Truncated incorrect DOUBLE value: '' +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# MDEV-24467 Memory not freed after failed INSERT DELAYED +# +CREATE TABLE t1 (a VARCHAR(1)) ENGINE=MyISAM; +ALTER TABLE t1 ADD b BLOB DEFAULT 'x'; +INSERT DELAYED INTO t1 (a) VALUES ('foo'); +ERROR 22001: Data too long for column 'a' at row 1 +DROP TABLE t1; diff --git a/mysql-test/t/delayed_blob-master.opt b/mysql-test/t/delayed_blob-master.opt new file mode 100644 index 00000000000..e442a822046 --- /dev/null +++ b/mysql-test/t/delayed_blob-master.opt @@ -0,0 +1 @@ +--init_connect="set @a='something unique to have MTR start a dedicated mariadbd for this test and shutdown it after the test'" diff --git a/mysql-test/t/delayed_blob.test b/mysql-test/t/delayed_blob.test new file mode 100644 index 00000000000..bf3e01a8825 --- /dev/null +++ b/mysql-test/t/delayed_blob.test @@ -0,0 +1,21 @@ +--echo # +--echo # MDEV-25925 Warning: Memory not freed: 32 on INSERT DELAYED +--echo # + +SET sql_mode='TRADITIONAL'; +CREATE TABLE t1 (c BLOB) ENGINE=MyISAM; +--error ER_TRUNCATED_WRONG_VALUE +INSERT DELAYED INTO t1 VALUES (''||''); +DROP TABLE t1; +SET sql_mode=DEFAULT; + + +--echo # +--echo # MDEV-24467 Memory not freed after failed INSERT DELAYED +--echo # + +CREATE TABLE t1 (a VARCHAR(1)) ENGINE=MyISAM; +ALTER TABLE t1 ADD b BLOB DEFAULT 'x'; +--error ER_DATA_TOO_LONG +INSERT DELAYED INTO t1 (a) VALUES ('foo'); +DROP TABLE t1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 51b2c84cfea..718682f767e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1257,7 +1257,18 @@ values_loop_end: abort: #ifndef EMBEDDED_LIBRARY if (lock_type == TL_WRITE_DELAYED) + { end_delayed_insert(thd); + /* + In case of an error (e.g. data truncation), the data type specific data + in fields (e.g. Field_blob::value) was not taken over + by the delayed writer thread. All fields in table_list->table + will be freed by free_root() soon. We need to free the specific + data before free_root() to avoid a memory leak. + */ + for (Field **ptr= table_list->table->field ; *ptr ; ptr++) + (*ptr)->free(); + } #endif if (table != NULL) table->file->ha_release_auto_increment(); |