diff options
author | Guilhem Bichot <guilhem.bichot@oracle.com> | 2011-04-07 15:09:19 +0200 |
---|---|---|
committer | Guilhem Bichot <guilhem.bichot@oracle.com> | 2011-04-07 15:09:19 +0200 |
commit | dc65d9217c36a0edc8fab0a4a09fbeda7a5c278d (patch) | |
tree | 1361390096fdbc9f653b47618e94a1872121fa4d | |
parent | c68a034e8382c03118f8c6708dd029a89aae30a7 (diff) | |
download | mariadb-git-dc65d9217c36a0edc8fab0a4a09fbeda7a5c278d.tar.gz |
Fix for Bug#11765141 - "58072: LOAD DATA INFILE: LEAKS IO CACHE MEMORY WHEN ERROR OCCURS"
mysql-test/t/loaddata.test:
test for bug; without fix, running the test with --valgrind would show the leak
and make the test fail.
sql/sql_load.cc:
* In READ_INFO class, 'need_end_io_cache' is true as long as init_io_cache() was called,
so if it's true, we need to call end_io_cache(), to free memory allocated
by init_io_cache(). No matter the value of 'error'. In the bug's scenario,
'error' was set to true in read_sep_field() because
'1' (read from file) isn't suitable to load into a geometric column. Because of
'error', end_io_cache() was not called.
Note: end_io_cache() calls my_b_flush_io_cache(), which will do nothing wrong given
that the file is opened for reads only; see the init_io_cache() call which uses
only those read-only types:
(get_it_from_net) ? READ_NET : (is_fifo ? READ_FIFO : READ_CACHE).
IF the cache were rather used to write to the file, my_b_flush_io_cache() may
write to it, and it may be questionable to write to the file
if 'error' is true. But here there's no problem.
* Now that 'need_end_io_cache' is checked even if 'error' is true, it needs
to be initialized in all cases.
* Bonus: move some variables to the initialization list.
-rw-r--r-- | mysql-test/r/loaddata.result | 9 | ||||
-rw-r--r-- | mysql-test/t/loaddata.test | 15 | ||||
-rw-r--r-- | sql/sql_load.cc | 9 |
3 files changed, 28 insertions, 5 deletions
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 3a421b3ea3f..59a1b904744 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -539,4 +539,13 @@ CREATE TABLE t1(f1 INT); SELECT 0xE1BB30 INTO OUTFILE 't1.dat'; LOAD DATA INFILE 't1.dat' IGNORE INTO TABLE t1 CHARACTER SET utf8; DROP TABLE t1; +# +# Bug#11765141 - 58072: LOAD DATA INFILE: LEAKS IO CACHE MEMORY +# WHEN ERROR OCCURS +# +SELECT '1\n' INTO DUMPFILE 'MYSQLTEST_VARDIR/tmp/bug11735141.txt'; +create table t1(a point); +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug11735141.txt' INTO TABLE t1; +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; End of 5.1 tests diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index e0764b67ec0..3d0fdea05ed 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -625,4 +625,19 @@ DROP TABLE t1; let $MYSQLD_DATADIR= `select @@datadir`; remove_file $MYSQLD_DATADIR/test/t1.dat; +--echo # +--echo # Bug#11765141 - 58072: LOAD DATA INFILE: LEAKS IO CACHE MEMORY +--echo # WHEN ERROR OCCURS +--echo # + +--let $file=$MYSQLTEST_VARDIR/tmp/bug11735141.txt +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT '1\n' INTO DUMPFILE '$file' + +create table t1(a point); +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--error ER_CANT_CREATE_GEOMETRY_OBJECT +--eval LOAD DATA INFILE '$file' INTO TABLE t1 +drop table t1; + --echo End of 5.1 tests diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 513cd62b510..b9b7bd74f6c 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1075,9 +1075,10 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, String &field_term, String &line_start, String &line_term, String &enclosed_par, int escape, bool get_it_from_net, bool is_fifo) - :file(file_par),escape_char(escape) + :file(file_par), buff_length(tot_length), escape_char(escape), + found_end_of_line(false), eof(false), need_end_io_cache(false), + error(false), line_cuted(false), found_null(false), read_charset(cs) { - read_charset= cs; field_term_ptr=(char*) field_term.ptr(); field_term_length= field_term.length(); line_term_ptr=(char*) line_term.ptr(); @@ -1104,8 +1105,6 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, (uchar) enclosed_par[0] : INT_MAX; field_term_char= field_term_length ? (uchar) field_term_ptr[0] : INT_MAX; line_term_char= line_term_length ? (uchar) line_term_ptr[0] : INT_MAX; - error=eof=found_end_of_line=found_null=line_cuted=0; - buff_length=tot_length; /* Set of a stack for unget if long terminators */ @@ -1151,7 +1150,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, READ_INFO::~READ_INFO() { - if (!error && need_end_io_cache) + if (need_end_io_cache) ::end_io_cache(&cache); my_free(buffer, MYF(MY_ALLOW_ZERO_PTR)); |