summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorTor Didriksen <tor.didriksen@oracle.com>2012-04-12 15:04:22 +0200
committerTor Didriksen <tor.didriksen@oracle.com>2012-04-12 15:04:22 +0200
commit83d455be90a06e8fc1293a611061bd9529ed8536 (patch)
tree3a272d304a40e4f35352c9eff016ee04b0d5cc08 /sql
parenta84ca722247a2aa118c42d8c55d80196660d6795 (diff)
downloadmariadb-git-83d455be90a06e8fc1293a611061bd9529ed8536.tar.gz
Bug#13871079 RQG_MYISAM_DML_ALTER_VALGRIND FAILS ON VALGRIND PN PB2
The class Copy_field contains a String tmp, which may allocate memory on the heap. That means that all instances of Copy_field must be properly destroyed. Alas they are not. Solution: don't use Copy_field::tmp for copying from_field => tmp => to_field in do_field_string() sql/field.cc: In Field_set::val_str return empty string (of appropriate character set) for an empty set. sql/field.h: New private member in Field_enum: empty_set_string. sql/field_conv.cc: In do_field_string, use an auto variable for copying from_field => tmp => to_field rather than copy->tmp.
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc14
-rw-r--r--sql/field.h8
-rw-r--r--sql/field_conv.cc11
3 files changed, 26 insertions, 7 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 59eb83da5fa..c7f19976260 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -8257,7 +8257,19 @@ String *Field_set::val_str(String *val_buffer,
ulonglong tmp=(ulonglong) Field_enum::val_int();
uint bitnr=0;
- val_buffer->set("", 0, field_charset);
+ if (tmp == 0)
+ {
+ /*
+ Some callers expect *val_buffer to contain the result,
+ so we assign to it, rather than doing 'return &empty_set_string.
+ */
+ *val_buffer= empty_set_string;
+ return val_buffer;
+ }
+
+ val_buffer->set_charset(field_charset);
+ val_buffer->length(0);
+
while (tmp && bitnr < (uint) typelib->count)
{
if (tmp & 1)
diff --git a/sql/field.h b/sql/field.h
index b4adb764b22..674b58108d4 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1985,7 +1985,8 @@ public:
:Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
packlength_arg,
- typelib_arg,charset_arg)
+ typelib_arg,charset_arg),
+ empty_set_string("", 0, charset_arg)
{
flags=(flags & ~ENUM_FLAG) | SET_FLAG;
}
@@ -1996,8 +1997,11 @@ public:
virtual bool zero_pack() const { return 1; }
String *val_str(String*,String *);
void sql_type(String &str) const;
+ uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_SET; }
bool has_charset(void) const { return TRUE; }
+private:
+ const String empty_set_string;
};
@@ -2192,6 +2196,8 @@ public:
{
return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
}
+private:
+ const String empty_set_string;
};
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 594449174bc..605ac752e0d 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -317,10 +317,11 @@ static void do_save_blob(Copy_field *copy)
static void do_field_string(Copy_field *copy)
{
char buff[MAX_FIELD_WIDTH];
- copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
- copy->from_field->val_str(&copy->tmp);
- copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),
- copy->tmp.charset());
+ String res(buff, sizeof(buff), copy->from_field->charset());
+ res.length(0U);
+
+ copy->from_field->val_str(&res);
+ copy->to_field->store(res.c_ptr_quick(), res.length(), res.charset());
}
@@ -563,7 +564,7 @@ void Copy_field::set(uchar *to,Field *from)
/*
To do:
- If 'save\ is set to true and the 'from' is a blob field, do_copy is set to
+ If 'save' is set to true and the 'from' is a blob field, do_copy is set to
do_save_blob rather than do_conv_blob. The only differences between them
appears to be: