Commit d07b5f1c authored by Joerg Bruehe's avatar Joerg Bruehe

Last-minute fix to 5.1.67,

taking a change done to main 5.1 by Dmitri Lenev.

This is the original comment:

> committer: Dmitry Lenev <Dmitry.Lenev@oracle.com>
> branch nick: mysql-5.1-15954896
> timestamp: Wed 2012-12-05 19:26:56 +0400
> message:
>   Bug #15954896 "SP, MULTI-TABLE DELETE AND LONG ALIAS".

  Using too long table aliases in stored routines might
  have caused server crashes.

  Code in sp_head::merge_table_list() which is responsible
  for collecting information about tables used in stored
  routine was not aware of the fact that table alias might
  have arbitrary length. I.e. it assumed that table alias
  can't be longer than NAME_LEN bytes and allocated buffer
  for a key identifying table accordingly.

  This patch fixes the issue by ensuring that we use
  dynamically allocated buffer for table key when table
  alias is too long. By default stack based buffer is used
  in which NAME_LEN bytes are reserved for table alias.
parent 2cbf2e64
...@@ -3839,8 +3839,6 @@ typedef struct st_sp_table ...@@ -3839,8 +3839,6 @@ typedef struct st_sp_table
Multi-set key: Multi-set key:
db_name\0table_name\0alias\0 - for normal tables db_name\0table_name\0alias\0 - for normal tables
db_name\0table_name\0 - for temporary tables db_name\0table_name\0 - for temporary tables
Note that in both cases we don't take last '\0' into account when
we count length of key.
*/ */
LEX_STRING qname; LEX_STRING qname;
uint db_length, table_name_length; uint db_length, table_name_length;
...@@ -3897,19 +3895,26 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) ...@@ -3897,19 +3895,26 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
for (; table ; table= table->next_global) for (; table ; table= table->next_global)
if (!table->derived && !table->schema_table) if (!table->derived && !table->schema_table)
{ {
char tname[(NAME_LEN + 1) * 3]; // db\0table\0alias\0 /*
uint tlen, alen; Structure of key for the multi-set is "db\0table\0alias\0".
Since "alias" part can have arbitrary length we use String
object to construct the key. By default String will use
buffer allocated on stack with NAME_LEN bytes reserved for
alias, since in most cases it is going to be smaller than
NAME_LEN bytes.
*/
char tname_buff[(NAME_LEN + 1) * 3];
String tname(tname_buff, sizeof(tname_buff), &my_charset_bin);
uint temp_table_key_length;
tlen= table->db_length; tname.length(0);
memcpy(tname, table->db, tlen); tname.append(table->db, table->db_length);
tname[tlen++]= '\0'; tname.append('\0');
memcpy(tname+tlen, table->table_name, table->table_name_length); tname.append(table->table_name, table->table_name_length);
tlen+= table->table_name_length; tname.append('\0');
tname[tlen++]= '\0'; temp_table_key_length= tname.length();
alen= strlen(table->alias); tname.append(table->alias);
memcpy(tname+tlen, table->alias, alen); tname.append('\0');
tlen+= alen;
tname[tlen]= '\0';
/* /*
Upgrade the lock type because this table list will be used Upgrade the lock type because this table list will be used
...@@ -3924,9 +3929,10 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) ...@@ -3924,9 +3929,10 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
(and therefore should not be prelocked). Otherwise we will erroneously (and therefore should not be prelocked). Otherwise we will erroneously
treat table with same name but with different alias as non-temporary. treat table with same name but with different alias as non-temporary.
*/ */
if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname, tlen)) || if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname.ptr(),
((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname, tname.length())) ||
tlen - alen - 1)) && ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname.ptr(),
temp_table_key_length)) &&
tab->temp)) tab->temp))
{ {
if (tab->lock_type < table->lock_type) if (tab->lock_type < table->lock_type)
...@@ -3945,11 +3951,11 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) ...@@ -3945,11 +3951,11 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
lex_for_tmp_check->create_info.options & HA_LEX_CREATE_TMP_TABLE) lex_for_tmp_check->create_info.options & HA_LEX_CREATE_TMP_TABLE)
{ {
tab->temp= TRUE; tab->temp= TRUE;
tab->qname.length= tlen - alen - 1; tab->qname.length= temp_table_key_length;
} }
else else
tab->qname.length= tlen; tab->qname.length= tname.length();
tab->qname.str= (char*) thd->memdup(tname, tab->qname.length + 1); tab->qname.str= (char*) thd->memdup(tname.ptr(), tab->qname.length);
if (!tab->qname.str) if (!tab->qname.str)
return FALSE; return FALSE;
tab->table_name_length= table->table_name_length; tab->table_name_length= table->table_name_length;
...@@ -4018,7 +4024,7 @@ sp_head::add_used_tables_to_table_list(THD *thd, ...@@ -4018,7 +4024,7 @@ sp_head::add_used_tables_to_table_list(THD *thd,
if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) * if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) *
stab->lock_count)) || stab->lock_count)) ||
!(key_buff= (char*)thd->memdup(stab->qname.str, !(key_buff= (char*)thd->memdup(stab->qname.str,
stab->qname.length + 1))) stab->qname.length)))
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
for (uint j= 0; j < stab->lock_count; j++) for (uint j= 0; j < stab->lock_count; j++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment