Skip to content

Commit

Permalink
Bug#20683959 LOAD DATA INFILE IGNORES A SPECIFIC ROW SILENTLY UNDER D…
Browse files Browse the repository at this point in the history
…B CHARSET IS UTF8

READ_INFO::read_field has logic for reallocating the internal buffer
if it is too small. This did not work correctly for multibyte charsets.

Fix: If we are out of space, then push the current character on the
input stack, and break out of while loop, to reach realloc code.

Also: Ensure that we report an error before returning an error status.
  • Loading branch information
Tor Didriksen committed Apr 1, 2015
1 parent 3add658 commit 774e6ff
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 9 deletions.
27 changes: 27 additions & 0 deletions mysql-test/r/loaddata.result
Expand Up @@ -564,3 +564,30 @@ SET @@sql_mode= @old_mode;
Warnings:
Warning 3090 Changing sql mode 'NO_AUTO_CREATE_USER' is deprecated. It will be removed in a future release.
DROP TABLE t1;
#
# Bug#20683959 LOAD DATA INFILE IGNORES A SPECIFIC ROW SILENTLY
# UNDER DB CHARSET IS UTF8
#
CREATE DATABASE d1 CHARSET latin1;
USE d1;
CREATE TABLE t1 (val TEXT);
LOAD DATA INFILE '../../std_data/bug20683959loaddata.txt' INTO TABLE t1;
SELECT COUNT(*) FROM t1;
COUNT(*)
1
SELECT HEX(val) FROM t1;
HEX(val)
22525420406E696F757A656368756E3A20E7A781E381AFE3838FE38383E38394E383BCE382A8E383B3E38389E58EA8E381AAE38293E381A0E38191E3828CE381A9E38081E382A2E383B3E3838FE38383E38394E383BCE382A8E383B3E38389E38284E683A8E58A87E79A84E381AAE3818AE8A9B1E38292E38182E381BEE3828AE7A98DE6A5B5E79A84E381ABE69182E58F96E38197E381AAE38184E79086E794B1E381AFE38081E78FBEE5AE9FE381AEE4BABAE7949FE381AFE59FBAE69CACE79A84E381ABE38186E381BEE3818FE38184E3818BE381AAE38184E38197E4B88DE5B9B3E7AD89E381A0E38197E79086E4B88DE5B0BDE381A0E38197E8BE9BE38184
CREATE DATABASE d2 CHARSET utf8;
USE d2;
CREATE TABLE t1 (val TEXT);
LOAD DATA INFILE '../../std_data/bug20683959loaddata.txt' INTO TABLE t1;
SELECT COUNT(*) FROM t1;
COUNT(*)
1
SELECT HEX(val) FROM t1;
HEX(val)
22525420406E696F757A656368756E3A20E7A781E381AFE3838FE38383E38394E383BCE382A8E383B3E38389E58EA8E381AAE38293E381A0E38191E3828CE381A9E38081E382A2E383B3E3838FE38383E38394E383BCE382A8E383B3E38389E38284E683A8E58A87E79A84E381AAE3818AE8A9B1E38292E38182E381BEE3828AE7A98DE6A5B5E79A84E381ABE69182E58F96E38197E381AAE38184E79086E794B1E381AFE38081E78FBEE5AE9FE381AEE4BABAE7949FE381AFE59FBAE69CACE79A84E381ABE38186E381BEE3818FE38184E3818BE381AAE38184E38197E4B88DE5B9B3E7AD89E381A0E38197E79086E4B88DE5B0BDE381A0E38197E8BE9BE38184
DROP TABLE d1.t1, d2.t1;
DROP DATABASE d1;
DROP DATABASE d2;
1 change: 1 addition & 0 deletions mysql-test/std_data/bug20683959loaddata.txt
@@ -0,0 +1 @@
"RT @niouzechun: 私はハッピーエンド厨なんだけれど、アンハッピーエンドや惨劇的なお話をあまり積極的に摂取しない理由は、現実の人生は基本的にうまくいかないし不平等だし理不尽だし辛い
24 changes: 24 additions & 0 deletions mysql-test/t/loaddata.test
Expand Up @@ -670,3 +670,27 @@ eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/mysql' REPLACE INTO TABLE t1

SET @@sql_mode= @old_mode;
DROP TABLE t1;

--echo #
--echo # Bug#20683959 LOAD DATA INFILE IGNORES A SPECIFIC ROW SILENTLY
--echo # UNDER DB CHARSET IS UTF8
--echo #

CREATE DATABASE d1 CHARSET latin1;
USE d1;
CREATE TABLE t1 (val TEXT);
LOAD DATA INFILE '../../std_data/bug20683959loaddata.txt' INTO TABLE t1;
SELECT COUNT(*) FROM t1;
SELECT HEX(val) FROM t1;

CREATE DATABASE d2 CHARSET utf8;
USE d2;
CREATE TABLE t1 (val TEXT);
LOAD DATA INFILE '../../std_data/bug20683959loaddata.txt' INTO TABLE t1;
SELECT COUNT(*) FROM t1;
SELECT HEX(val) FROM t1;


DROP TABLE d1.t1, d2.t1;
DROP DATABASE d1;
DROP DATABASE d2;
27 changes: 18 additions & 9 deletions sql/sql_load.cc
Expand Up @@ -864,7 +864,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
*/
if (validate_default_values_of_unset_fields(thd, table))
{
read_info.error= 1;
read_info.error= true;
break;
}

Expand Down Expand Up @@ -1021,7 +1021,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
*/
if (validate_default_values_of_unset_fields(thd, table))
{
read_info.error= 1;
read_info.error= true;
break;
}

Expand Down Expand Up @@ -1113,7 +1113,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}

if (thd->is_error())
read_info.error= 1;
read_info.error= true;

if (read_info.error)
break;
Expand Down Expand Up @@ -1284,7 +1284,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
*/
if (validate_default_values_of_unset_fields(thd, table))
{
read_info.error= 1;
read_info.error= true;
break;
}

Expand Down Expand Up @@ -1494,8 +1494,8 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, const CHARSET_INFO *cs,
stack=stack_pos=(int*) sql_alloc(sizeof(int)*length);

if (!(buffer=(uchar*) my_malloc(key_memory_READ_INFO,
buff_length+1,MYF(0))))
error=1; /* purecov: inspected */
buff_length+1, MYF(MY_WME))))
error= true; /* purecov: inspected */
else
{
end_of_buff=buffer+buff_length;
Expand All @@ -1506,7 +1506,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, const CHARSET_INFO *cs,
{
my_free(buffer); /* purecov: inspected */
buffer= NULL;
error=1;
error= true;
}
else
{
Expand Down Expand Up @@ -1712,7 +1712,10 @@ int READ_INFO::read_field()
GET_MBCHARLEN(read_charset, chr, ml);
if (ml == 0)
{
error= 1;
*to= '\0';
my_error(ER_INVALID_CHARACTER_STRING, MYF(0),
read_charset->csname, buffer);
error= true;
return 1;
}

Expand Down Expand Up @@ -1745,6 +1748,12 @@ int READ_INFO::read_field()
PUSH(*--to);
chr= GET;
}
else if (ml > 1)
{
// Buffer is too small, exit while loop, and reallocate.
PUSH(chr);
break;
}
*to++ = (uchar) chr;
}
/*
Expand All @@ -1753,7 +1762,7 @@ int READ_INFO::read_field()
if (!(new_buffer=(uchar*) my_realloc(key_memory_READ_INFO,
(char*) buffer,buff_length+1+IO_SIZE,
MYF(MY_WME))))
return (error=1);
return (error= true);
to=new_buffer + (to-buffer);
buffer=new_buffer;
buff_length+=IO_SIZE;
Expand Down

0 comments on commit 774e6ff

Please sign in to comment.