diff options
author | unknown <konstantin@mysql.com> | 2006-06-28 23:47:45 +0400 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2006-06-28 23:47:45 +0400 |
commit | 88843709d8d2bb07794f3c13084bf33e5dea8662 (patch) | |
tree | 0604cb0378ffd697c49e6d0a5753e39aeb18f147 /sql/sql_class.h | |
parent | d127fa3b511996d3f2753bb81c854a4f0a3ddbf7 (diff) | |
download | mariadb-git-88843709d8d2bb07794f3c13084bf33e5dea8662.tar.gz |
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.
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r-- | sql/sql_class.h | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h index 1ba104df2a4..eb075dd54bb 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -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) { |