diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 1e488b320d7..0c3f8d04463 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -484,4 +484,15 @@ SET character_set_filesystem=default; select @@character_set_filesystem; @@character_set_filesystem binary +# +# Bug #51850: crash/memory overlap when using load data infile and set +# col equal to itself! +# +CREATE TABLE t1(col0 LONGBLOB); +SELECT 'test' INTO OUTFILE 't1.txt'; +LOAD DATA INFILE 't1.txt' IGNORE INTO TABLE t1 SET col0=col0; +SELECT * FROM t1; +col0 +test +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index 7bfe2491c7c..a32fee6b46e 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -532,5 +532,19 @@ SET character_set_filesystem=default; select @@character_set_filesystem; +--echo # +--echo # Bug #51850: crash/memory overlap when using load data infile and set +--echo # col equal to itself! +--echo # + +CREATE TABLE t1(col0 LONGBLOB); +SELECT 'test' INTO OUTFILE 't1.txt'; +LOAD DATA INFILE 't1.txt' IGNORE INTO TABLE t1 SET col0=col0; +SELECT * FROM t1; + +DROP TABLE t1; +let $MYSQLD_DATADIR= `select @@datadir`; +remove_file $MYSQLD_DATADIR/test/t1.txt; + --echo End of 5.1 tests diff --git a/sql/item.cc b/sql/item.cc index d253e19e068..809377e80b3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5063,14 +5063,22 @@ int Item_field::save_in_field(Field *to, bool no_conversions) if (result_field->is_null()) { null_value=1; - res= set_field_to_null_with_conversions(to, no_conversions); + return set_field_to_null_with_conversions(to, no_conversions); } - else + to->set_notnull(); + + /* + If we're setting the same field as the one we're reading from there's + nothing to do. This can happen in 'SET x = x' type of scenarios. + */ + if (to == result_field) { - to->set_notnull(); - res= field_conv(to,result_field); null_value=0; + return 0; } + + res= field_conv(to,result_field); + null_value=0; return res; }