From f36e854ac6ce19e7018addbb8701796006a27134 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Fri, 7 Oct 2011 14:08:31 +0200 Subject: BUG#12589870 CRASHES WITH MULTIQUERY PACKET + USE + QUERY CACHE A buffer large enough to hold the query _plus_ some additional data is allocated before parsing is started. The additional data is used by the query cache, and consists of the name of the current database and a set of flags. When a packet containing multiple SQL statements is sent to the server and one of the statements changes the current database (a "USE " statement), and the name of the new current database is longer than of the previous, there is not enough space in the buffer for the new name, and we write out over the buffer boundary. The fix adds an extra field to store the number of bytes allocated to the database name in the buffer. If the current database name changes, and the new name is longer than the previous one, we refuse to cache the query. --- sql/sp_head.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'sql/sp_head.cc') diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 95a7eda0540..70ffb0a36ab 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1029,12 +1029,22 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) /* Allocate additional space at the end of the new query string for the query_cache_send_result_to_client function. + + The query buffer layout is: + buffer :== + The input statement(s) + '\0' Terminating null char + Length of following current database name (size_t) + Name of current database + Flags struct */ - buf_len= qbuf.length() + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE + 1; + buf_len= qbuf.length() + 1 + sizeof(size_t) + thd->db_length + + QUERY_CACHE_FLAGS_SIZE + 1; if ((pbuf= (char *) alloc_root(thd->mem_root, buf_len))) { memcpy(pbuf, qbuf.ptr(), qbuf.length()); pbuf[qbuf.length()]= 0; + *(size_t *)(pbuf+qbuf.length()+1)= thd->db_length; } else DBUG_RETURN(TRUE); -- cgit v1.2.1