summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2019-08-14 23:46:47 +0300
committerMonty <monty@mariadb.org>2020-07-02 14:25:41 +0300
commit29f9e679adc90adf5d3c6e08da947789c9c2ac8b (patch)
treef15a3530548b3b0c7c9efd34386302fd63ec6c73
parent3f2044ae99633ce6d9c756bb6b045efc0707b4b5 (diff)
downloadmariadb-git-29f9e679adc90adf5d3c6e08da947789c9c2ac8b.tar.gz
Don't copy uninitialized bytes when copying varstrings
When using field_conv(), which is called in case of field1=field2 copy in fill_records(), full varstring's was copied, including unitialized bytes. This caused valgrind to compilain about usage of unitialized bytes when using Aria static length records. Fixed by not using memcpy when copying varstrings but instead just copy the real bytes.
-rw-r--r--sql/field.cc11
-rw-r--r--sql/field.h7
-rw-r--r--sql/handler.h3
-rw-r--r--storage/maria/ha_maria.cc2
-rw-r--r--storage/myisam/ha_myisam.cc5
5 files changed, 18 insertions, 10 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 155d8a4eb0d..1e2a711c956 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -7613,6 +7613,17 @@ int Field_varstring::save_field_metadata(uchar *metadata_ptr)
return 2;
}
+
+bool Field_varstring::memcpy_field_possible(const Field *from) const
+{
+ return (Field_str::memcpy_field_possible(from) &&
+ !compression_method() == !from->compression_method() &&
+ length_bytes == ((Field_varstring*) from)->length_bytes &&
+ (table->file && !(table->file->ha_table_flags() &
+ HA_RECORD_MUST_BE_CLEAN_ON_WRITE)));
+}
+
+
int Field_varstring::store(const char *from,size_t length,CHARSET_INFO *cs)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
diff --git a/sql/field.h b/sql/field.h
index db78efe0754..34d6684571b 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -3463,12 +3463,7 @@ public:
length_bytes : 0);
}
Copy_func *get_copy_func(const Field *from) const;
- bool memcpy_field_possible(const Field *from) const
- {
- return Field_str::memcpy_field_possible(from) &&
- !compression_method() == !from->compression_method() &&
- length_bytes == ((Field_varstring*) from)->length_bytes;
- }
+ bool memcpy_field_possible(const Field *from) const;
int store(const char *to,size_t length,CHARSET_INFO *charset);
using Field_str::store;
#ifdef HAVE_valgrind_or_MSAN
diff --git a/sql/handler.h b/sql/handler.h
index af9fa068891..16fcab1e755 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -200,7 +200,8 @@ enum enum_alter_inplace_result {
#define HA_HAS_NEW_CHECKSUM (1ULL << 38)
#define HA_CAN_VIRTUAL_COLUMNS (1ULL << 39)
#define HA_MRR_CANT_SORT (1ULL << 40)
-#define HA_RECORD_MUST_BE_CLEAN_ON_WRITE (1ULL << 41) /* unused */
+/* All of VARCHAR is stored, including bytes after real varchar data */
+#define HA_RECORD_MUST_BE_CLEAN_ON_WRITE (1ULL << 41)
/*
This storage engine supports condition pushdown
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index ec2a88de4df..c0163473f3a 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -1162,7 +1162,7 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
that all bytes in the row is properly reset.
*/
if (file->s->data_file_type == STATIC_RECORD &&
- (file->s->has_varchar_fields | file->s->has_null_fields))
+ (file->s->has_varchar_fields || file->s->has_null_fields))
int_table_flags|= HA_RECORD_MUST_BE_CLEAN_ON_WRITE;
for (i= 0; i < table->s->keys; i++)
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index fd2e8fd9425..0d9a2c6c18e 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -863,8 +863,9 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
the full row to ensure we don't get any errors from valgrind and
that all bytes in the row is properly reset.
*/
- if ((file->s->options & HA_OPTION_PACK_RECORD) &&
- (file->s->has_varchar_fields | file->s->has_null_fields))
+ if (!(file->s->options &
+ (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) &&
+ (file->s->has_varchar_fields || file->s->has_null_fields))
int_table_flags|= HA_RECORD_MUST_BE_CLEAN_ON_WRITE;
for (i= 0; i < table->s->keys; i++)