From c64b88d65a48d6c6651787f46f2094b310ceb5f1 Mon Sep 17 00:00:00 2001 From: Rohit Kalhans Date: Fri, 18 May 2012 14:44:40 +0530 Subject: [PATCH] BUG#14005409 - 64624 Problem: After the fix for Bug#12589870, a new field that stores the length of db name was added in the buffer that stores the query to be executed. Unlike for the plain user session, the replication execution did not allocate the necessary chunk in Query-event constructor. This caused an invalid read while accessing this field. Solution: We fix this problem by allocating a necessary chunk in the buffer created in the Query_log_event::Query_log_event() and store the length of database name. --- sql/log_event.cc | 50 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 8606964113c..afcc283a6d1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2835,24 +2835,34 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, pos= (const uchar*) end; // Break loop } } - + + /** + Layout for the data buffer is as follows + +--------+-----------+------+------+---------+----+-------+ + | catlog | time_zone | user | host | db name | \0 | Query | + +--------+-----------+------+------+---------+----+-------+ + + To support the query cache we append the following buffer to the above + +-------+----------------------------------------+-------+ + |db len | uninitiatlized space of size of db len | FLAGS | + +-------+----------------------------------------+-------+ + + The area of buffer starting from Query field all the way to the end belongs + to the Query buffer and its structure is described in alloc_query() in + sql_parse.cc + */ + + if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1 + + time_zone_len + 1 + + user.length + 1 + + host.length + 1 + + data_len + 1 #if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE) - if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1 + - time_zone_len + 1 + - data_len + 1 + - QUERY_CACHE_FLAGS_SIZE + - user.length + 1 + - host.length + 1 + - db_len + 1, - MYF(MY_WME)))) -#else - if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1 + - time_zone_len + 1 + - data_len + 1 + - user.length + 1 + - host.length + 1, - MYF(MY_WME)))) + + sizeof(size_t)//for db_len + + db_len + 1 + + QUERY_CACHE_FLAGS_SIZE #endif + , MYF(MY_WME)))) DBUG_VOID_RETURN; if (catalog_len) // If catalog is given { @@ -2891,6 +2901,14 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, db= (char *)start; query= (char *)(start + db_len + 1); q_len= data_len - db_len -1; + /** + Append the db length at the end of the buffer. This will be used by + Query_cache::send_result_to_client() in case the query cache is On. + */ +#if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE) + size_t db_length= (size_t)db_len; + memcpy(start + data_len + 1, &db_length, sizeof(size_t)); +#endif DBUG_VOID_RETURN; }