summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgi Kodinov <joro@sun.com>2010-03-23 17:07:00 +0200
committerGeorgi Kodinov <joro@sun.com>2010-03-23 17:07:00 +0200
commita9a2ceae1f360c275ed4db5b093ab65be4f5fb7b (patch)
tree71054058de67ea839694187d4caf855a62f8131e
parenta35418784bc35f5b6c461689c954bdcfbb4c9b33 (diff)
downloadmariadb-git-a9a2ceae1f360c275ed4db5b093ab65be4f5fb7b.tar.gz
Bug #51850: crash/memory overlap when using load data infile and set
col equal to itself! There's no need to copy the value of a field into itself. While generally harmless (except for some performance penalties) it may be dangerous when the copy code doesn't expect this. Fixed by checking if the source field is the same as the destination field before copying the data. Note that we must preserve the order of assignment of the null flags (hence the null_value assignment addition).
-rw-r--r--mysql-test/r/loaddata.result11
-rw-r--r--mysql-test/t/loaddata.test14
-rw-r--r--sql/item.cc16
3 files changed, 37 insertions, 4 deletions
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;
}