diff options
author | Magne Mahre <magne.mahre@oracle.com> | 2011-10-07 14:08:31 +0200 |
---|---|---|
committer | Magne Mahre <magne.mahre@oracle.com> | 2011-10-07 14:08:31 +0200 |
commit | f36e854ac6ce19e7018addbb8701796006a27134 (patch) | |
tree | 6b78785fe9d18efb7a0fff1422ca1168662e0834 /sql/sql_parse.cc | |
parent | 1922d65fd8881836b57ac925596dac4cb753e29b (diff) | |
download | mariadb-git-f36e854ac6ce19e7018addbb8701796006a27134.tar.gz |
BUG#12589870 CRASHES WITH MULTIQUERY PACKET + USE<DB> + 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 <db>" 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.
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b5864fef19d..55509a31f77 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1912,13 +1912,30 @@ bool alloc_query(THD *thd, const char *packet, uint packet_length) pos--; packet_length--; } - /* We must allocate some extra memory for query cache */ + /* We must allocate some extra memory for query cache + + The query buffer layout is: + buffer :== + <statement> The input statement(s) + '\0' Terminating null char (1 byte) + <length> Length of following current database name (size_t) + <db_name> Name of current database + <flags> Flags struct + */ if (! (query= (char*) thd->memdup_w_gap(packet, packet_length, - 1 + thd->db_length + + 1 + sizeof(size_t) + thd->db_length + QUERY_CACHE_FLAGS_SIZE))) return TRUE; query[packet_length]= '\0'; + /* + Space to hold the name of the current database is allocated. We + also store this length, in case current database is changed during + execution. We might need to reallocate the 'query' buffer + */ + size_t *len = (size_t *) (query + packet_length + 1); + *len= thd->db_length; + thd->set_query(query, packet_length); /* Reclaim some memory */ |