From dc65d9217c36a0edc8fab0a4a09fbeda7a5c278d Mon Sep 17 00:00:00 2001 From: Guilhem Bichot Date: Thu, 7 Apr 2011 15:09:19 +0200 Subject: 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. --- sql/sql_load.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'sql/sql_load.cc') 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)); -- cgit v1.2.1 From bba7b9ca0c96a1c140e725776b5e0382a4f62152 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 15 Apr 2011 12:51:34 +0400 Subject: Bug#11765139 58069: LOAD DATA INFILE: VALGRIND REPORTS INVALID MEMORY READS AND WRITES WITH U Some multibyte sequences could be considered by my_mbcharlen() functions as multibyte character but more exact my_ismbchar() does not think so. In such a case this multibyte sequences is pushed into 'stack' buffer which is too small to accommodate the sequence. The fix is to allocate stack buffer in compliance with max character length. mysql-test/r/loaddata.result: test case mysql-test/t/loaddata.test: test case sql/sql_load.cc: allocate stack buffer in compliance with max character length. --- sql/sql_load.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/sql_load.cc') diff --git a/sql/sql_load.cc b/sql/sql_load.cc index c227fe69b62..513cd62b510 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1109,7 +1109,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, /* Set of a stack for unget if long terminators */ - uint length=max(field_term_length,line_term_length)+1; + uint length= max(cs->mbmaxlen, max(field_term_length, line_term_length)) + 1; set_if_bigger(length,line_start.length()); stack=stack_pos=(int*) sql_alloc(sizeof(int)*length); -- cgit v1.2.1