summaryrefslogtreecommitdiff
path: root/sql/log_event.cc
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2006-06-28 23:47:45 +0400
committerunknown <konstantin@mysql.com>2006-06-28 23:47:45 +0400
commit88843709d8d2bb07794f3c13084bf33e5dea8662 (patch)
tree0604cb0378ffd697c49e6d0a5753e39aeb18f147 /sql/log_event.cc
parentd127fa3b511996d3f2753bb81c854a4f0a3ddbf7 (diff)
downloadmariadb-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/log_event.cc')
-rw-r--r--sql/log_event.cc32
1 files changed, 25 insertions, 7 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc
index b4707826205..cf5dbb1e77c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1635,14 +1635,33 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+
+static const char *rewrite_db(const char *db)
+{
+ if (replicate_rewrite_db.is_empty() || db == NULL)
+ return db;
+ I_List_iterator<i_string_pair> it(replicate_rewrite_db);
+ i_string_pair* tmp;
+
+ while ((tmp=it++))
+ {
+ if (strcmp(tmp->key, db) == 0)
+ return tmp->val;
+ }
+ return db;
+}
+
+
int Query_log_event::exec_event(struct st_relay_log_info* rli)
{
return exec_event(rli, query, q_len);
}
-int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query_arg, uint32 q_len_arg)
+int Query_log_event::exec_event(struct st_relay_log_info* rli,
+ const char *query_arg, uint32 q_len_arg)
{
+ const char *new_db= rewrite_db(db);
int expected_error,actual_error= 0;
/*
Colleagues: please never free(thd->catalog) in MySQL. This would lead to
@@ -1651,8 +1670,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query
Thank you.
*/
thd->catalog= catalog_len ? (char *) catalog : (char *)"";
- thd->db_length= db_len;
- thd->db= (char*) rewrite_db(db, &thd->db_length);
+ thd->set_db(new_db, strlen(new_db)); /* allocates a copy of 'db' */
thd->variables.auto_increment_increment= auto_increment_increment;
thd->variables.auto_increment_offset= auto_increment_offset;
@@ -1869,7 +1887,7 @@ end:
TABLE uses the db.table syntax.
*/
thd->catalog= 0;
- thd->reset_db(NULL, 0); // prevent db from being freed
+ thd->set_db(NULL, 0); /* will free the current database */
thd->query= 0; // just to be sure
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
@@ -2817,8 +2835,8 @@ void Load_log_event::set_fields(const char* affected_db,
int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors)
{
- thd->db_length= db_len;
- thd->db= (char*) rewrite_db(db, &thd->db_length);
+ const char *new_db= rewrite_db(db);
+ thd->set_db(new_db, strlen(new_db));
DBUG_ASSERT(thd->query == 0);
thd->query_length= 0; // Should not be needed
thd->query_error= 0;
@@ -3018,7 +3036,7 @@ error:
const char *remember_db= thd->db;
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->catalog= 0;
- thd->reset_db(NULL, 0);
+ thd->set_db(NULL, 0); /* will free the current database */
thd->query= 0;
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));