1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-24 11:21:21 +03:00

A fix for Bug#19022 "Memory bug when switching db during trigger execution".

No test case as the bug is in an existing test case (rpl_trigger.test
when it is run under valgrind).
The warning was caused by memory corruption in replication slave: thd->db
was pointing at a stack address that was previously used by 
sp_head::execute()::old_db. This happened because mysql_change_db
behaved differently in replication slave and did not make a copy of the 
argument to assign to thd->db. 
The solution is to always free the old value of thd->db and allocate a new
copy, regardless whether we're running in a replication slave or not.


sql/log_event.cc:
  Move rewrite_db to log_event.cc, the only place where it is used.
sql/slave.cc:
  Move rewrite_db to log_event.cc
sql/slave.h:
  Remove an unneeded declaration.
sql/sql_class.h:
  Fix set_db to always free the old db, even if the argument is NULL.
  Add a comment.
sql/sql_db.cc:
  Always make a deep copy of the argument in mysql_change_db, even 
  if running in a replication slave. This is necessary because 
  sp_use_new_db (stored procedures) assumes that mysql_change_db always makes
  a deep copy of the argument, and thus passes a pointer to stack into it.
  This assumption was true for all cases except the replication slave thread.
This commit is contained in:
unknown
2006-06-28 23:47:45 +04:00
parent d127fa3b51
commit 88843709d8
5 changed files with 111 additions and 121 deletions

View File

@@ -1574,21 +1574,23 @@ public:
/*
Initialize the current database from a NULL-terminated string with length
If we run out of memory, we free the current database and return TRUE.
This way the user will notice the error as there will be no current
database selected (in addition to the error message set by malloc).
*/
void set_db(const char *new_db, uint new_db_len)
bool set_db(const char *new_db, uint new_db_len)
{
if (new_db)
/* Do not reallocate memory if current chunk is big enough. */
if (db && new_db && db_length >= new_db_len)
memcpy(db, new_db, new_db_len+1);
else
{
/* Do not reallocate memory if current chunk is big enough. */
if (db && db_length >= new_db_len)
memcpy(db, new_db, new_db_len+1);
else
{
safeFree(db);
db= my_strdup_with_length(new_db, new_db_len, MYF(MY_WME));
}
db_length= db ? new_db_len: 0;
x_free(db);
db= new_db ? my_strdup_with_length(new_db, new_db_len, MYF(MY_WME)) :
NULL;
}
db_length= db ? new_db_len : 0;
return new_db && !db;
}
void reset_db(char *new_db, uint new_db_len)
{