Description:
I think the problem is still in trunk. This is an accident waiting to happen -- current code can't trigger a problem but if you use the fix for http://bugs.mysql.com/bug.php?id=64353, then you will hit the problem.
String doesn't own the memory referenced by Ptr when alloced=0, it should not free it. But shrink() can free it in the call to my_realloc. The call stack to the accident (double-free) is:
String::shrink - called because my_b_read call fails
String::append(IO_CACHE* file, uint32 arg_length)
Log_event::read_log_event
In the call stack above the my_b_read call fails because the end of the binlog
is corrupt on crash recovery. Newer versions of MySQL truncate the end of the
binlog when it is corrupt after a crash.
An earlier change by me to add rpl_event_buffer_size makes this possible because
with that change, the instance of String named "packet" in mysql_binlog_send
provides a buffer to "packet", thus "packet" doesn't own the buffer. But in the
call stack above it will attempt to free it.
How to repeat:
see above
Suggested fix:
diff --git a/sql/sql_string.h b/sql/sql_string.h
index fd644cb..0d95343 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -212,6 +212,15 @@ public:
bool realloc(uint32 arg_length);
inline void shrink(uint32 arg_length) // Shrink buffer
{
+ if (!alloced)
+ {
+ /*
+ Either the buffer is NULL or this class doesn't own the
+ buffer memory and cannot shrink it.
+ */
+ return;
+ }
+
It wouldn't hurt to add a few comments to sql_string.h. It is really unkind to write base classes that many people will try to use and then have no comments.