Commit 3771d623 authored by Kristofer Pettersson's avatar Kristofer Pettersson

Bug#45613 handle failures from my_hash_insert

Not all my_hash_insert() calls are checked for return value.

This patch adds appropriate checks and failure responses
where needed.
parent e131edc9
...@@ -334,6 +334,7 @@ my_bool my_hash_insert(HASH *info, const uchar *record) ...@@ -334,6 +334,7 @@ my_bool my_hash_insert(HASH *info, const uchar *record)
size_t idx,halfbuff,hash_nr,first_index; size_t idx,halfbuff,hash_nr,first_index;
uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2);
HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos;
DBUG_EXECUTE("fail_hash_insert",return(TRUE););
if (HASH_UNIQUE & info->flags) if (HASH_UNIQUE & info->flags)
{ {
......
...@@ -5649,9 +5649,8 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) ...@@ -5649,9 +5649,8 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)
Xid_log_event *xev=(Xid_log_event *)ev; Xid_log_event *xev=(Xid_log_event *)ev;
uchar *x= (uchar *) memdup_root(&mem_root, (uchar*) &xev->xid, uchar *x= (uchar *) memdup_root(&mem_root, (uchar*) &xev->xid,
sizeof(xev->xid)); sizeof(xev->xid));
if (! x) if (!x || my_hash_insert(&xids, x))
goto err2; goto err2;
my_hash_insert(&xids, x);
} }
delete ev; delete ev;
} }
......
...@@ -559,7 +559,12 @@ HOSTS"; ...@@ -559,7 +559,12 @@ HOSTS";
goto err; goto err;
} }
si->server_id = log_server_id; si->server_id = log_server_id;
my_hash_insert(&slave_list, (uchar*)si); if (my_hash_insert(&slave_list, (uchar*)si))
{
error= "the slave is out of memory";
pthread_mutex_unlock(&LOCK_slave_list);
goto err;
}
} }
strmake(si->host, row[1], sizeof(si->host)-1); strmake(si->host, row[1], sizeof(si->host)-1);
si->port = atoi(row[port_ind]); si->port = atoi(row[port_ind]);
......
...@@ -119,7 +119,13 @@ int table_mapping::set_table(ulong table_id, TABLE* table) ...@@ -119,7 +119,13 @@ int table_mapping::set_table(ulong table_id, TABLE* table)
} }
e->table_id= table_id; e->table_id= table_id;
e->table= table; e->table= table;
my_hash_insert(&m_table_ids,(uchar *)e); if (my_hash_insert(&m_table_ids,(uchar *)e))
{
/* we add this entry to the chain of free (free for use) entries */
e->next= m_free;
m_free= e;
DBUG_RETURN(ERR_MEMORY_ALLOCATION);
}
DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)", DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)",
table_id, (long) e->table, table_id, (long) e->table,
......
...@@ -1506,7 +1506,8 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, ...@@ -1506,7 +1506,8 @@ static bool add_used_routine(LEX *lex, Query_arena *arena,
rn->key.length= key->length; rn->key.length= key->length;
rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry); rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry);
memcpy(rn->key.str, key->str, key->length + 1); memcpy(rn->key.str, key->str, key->length + 1);
my_hash_insert(&lex->sroutines, (uchar *)rn); if (my_hash_insert(&lex->sroutines, (uchar *)rn))
return FALSE;
lex->sroutines_list.link_in_list((uchar *)rn, (uchar **)&rn->next); lex->sroutines_list.link_in_list((uchar *)rn, (uchar **)&rn->next);
rn->belong_to_view= belong_to_view; rn->belong_to_view= belong_to_view;
return TRUE; return TRUE;
...@@ -1584,16 +1585,24 @@ void sp_remove_not_own_routines(LEX *lex) ...@@ -1584,16 +1585,24 @@ void sp_remove_not_own_routines(LEX *lex)
dependant on time of life of elements from source hash. It also dependant on time of life of elements from source hash. It also
won't touch lists linking elements in source and destination won't touch lists linking elements in source and destination
hashes. hashes.
@returns
@return TRUE Failure
@return FALSE Success
*/ */
void sp_update_sp_used_routines(HASH *dst, HASH *src) bool sp_update_sp_used_routines(HASH *dst, HASH *src)
{ {
for (uint i=0 ; i < src->records ; i++) for (uint i=0 ; i < src->records ; i++)
{ {
Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i); Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
if (!hash_search(dst, (uchar *)rt->key.str, rt->key.length)) if (!hash_search(dst, (uchar *)rt->key.str, rt->key.length))
my_hash_insert(dst, (uchar *)rt); {
if (my_hash_insert(dst, (uchar *)rt))
return TRUE;
}
} }
return FALSE;
} }
......
...@@ -69,7 +69,7 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking, ...@@ -69,7 +69,7 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking,
void sp_add_used_routine(LEX *lex, Query_arena *arena, void sp_add_used_routine(LEX *lex, Query_arena *arena,
sp_name *rt, char rt_type); sp_name *rt, char rt_type);
void sp_remove_not_own_routines(LEX *lex); void sp_remove_not_own_routines(LEX *lex);
void sp_update_sp_used_routines(HASH *dst, HASH *src); bool sp_update_sp_used_routines(HASH *dst, HASH *src);
int sp_cache_routines_and_add_tables(THD *thd, LEX *lex, int sp_cache_routines_and_add_tables(THD *thd, LEX *lex,
bool first_no_prelock); bool first_no_prelock);
int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex,
......
...@@ -36,10 +36,16 @@ public: ...@@ -36,10 +36,16 @@ public:
sp_cache(); sp_cache();
~sp_cache(); ~sp_cache();
inline void insert(sp_head *sp) /**
Inserts a sp_head object into a hash table.
@returns Success status
@return TRUE Failure
@return FALSE Success
*/
inline bool insert(sp_head *sp)
{ {
/* TODO: why don't we check return value? */ return my_hash_insert(&m_hashtable, (const uchar *)sp);
my_hash_insert(&m_hashtable, (const uchar *)sp);
} }
inline sp_head *lookup(char *name, uint namelen) inline sp_head *lookup(char *name, uint namelen)
......
...@@ -2087,8 +2087,18 @@ sp_head::reset_lex(THD *thd) ...@@ -2087,8 +2087,18 @@ sp_head::reset_lex(THD *thd)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
/// Restore lex during parsing, after we have parsed a sub statement.
void /**
Restore lex during parsing, after we have parsed a sub statement.
@param thd Thread handle
@return
@retval TRUE failure
@retval FALSE success
*/
bool
sp_head::restore_lex(THD *thd) sp_head::restore_lex(THD *thd)
{ {
DBUG_ENTER("sp_head::restore_lex"); DBUG_ENTER("sp_head::restore_lex");
...@@ -2099,7 +2109,7 @@ sp_head::restore_lex(THD *thd) ...@@ -2099,7 +2109,7 @@ sp_head::restore_lex(THD *thd)
oldlex= (LEX *)m_lex.pop(); oldlex= (LEX *)m_lex.pop();
if (! oldlex) if (! oldlex)
return; // Nothing to restore DBUG_RETURN(FALSE); // Nothing to restore
oldlex->trg_table_fields.push_back(&sublex->trg_table_fields); oldlex->trg_table_fields.push_back(&sublex->trg_table_fields);
...@@ -2115,7 +2125,8 @@ sp_head::restore_lex(THD *thd) ...@@ -2115,7 +2125,8 @@ sp_head::restore_lex(THD *thd)
Add routines which are used by statement to respective set for Add routines which are used by statement to respective set for
this routine. this routine.
*/ */
sp_update_sp_used_routines(&m_sroutines, &sublex->sroutines); if (sp_update_sp_used_routines(&m_sroutines, &sublex->sroutines))
DBUG_RETURN(TRUE);
/* /*
Merge tables used by this statement (but not by its functions or Merge tables used by this statement (but not by its functions or
procedures) to multiset of tables used by this routine. procedures) to multiset of tables used by this routine.
...@@ -2127,7 +2138,7 @@ sp_head::restore_lex(THD *thd) ...@@ -2127,7 +2138,7 @@ sp_head::restore_lex(THD *thd)
delete sublex; delete sublex;
} }
thd->lex= oldlex; thd->lex= oldlex;
DBUG_VOID_RETURN; DBUG_RETURN(FALSE);
} }
/** /**
...@@ -3865,7 +3876,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) ...@@ -3865,7 +3876,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
tab->lock_type= table->lock_type; tab->lock_type= table->lock_type;
tab->lock_count= tab->query_lock_count= 1; tab->lock_count= tab->query_lock_count= 1;
tab->trg_event_map= table->trg_event_map; tab->trg_event_map= table->trg_event_map;
my_hash_insert(&m_sptabs, (uchar *)tab); if (my_hash_insert(&m_sptabs, (uchar *)tab))
return FALSE;
} }
} }
return TRUE; return TRUE;
......
...@@ -340,7 +340,7 @@ public: ...@@ -340,7 +340,7 @@ public:
@todo Conflicting comment in sp_head.cc @todo Conflicting comment in sp_head.cc
*/ */
void bool
restore_lex(THD *thd); restore_lex(THD *thd);
/// Put the instruction on the backpatch list, associated with the label. /// Put the instruction on the backpatch list, associated with the label.
......
...@@ -2400,7 +2400,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) ...@@ -2400,7 +2400,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
privs = cols = 0; /* purecov: deadcode */ privs = cols = 0; /* purecov: deadcode */
return; /* purecov: deadcode */ return; /* purecov: deadcode */
} }
my_hash_insert(&hash_columns, (uchar *) mem_check); if (my_hash_insert(&hash_columns, (uchar *) mem_check))
{
/* Invalidate this entry */
privs= cols= 0;
return;
}
} while (!col_privs->file->index_next(col_privs->record[0]) && } while (!col_privs->file->index_next(col_privs->record[0]) &&
!key_cmp_if_same(col_privs,key,0,key_prefix_len)); !key_cmp_if_same(col_privs,key,0,key_prefix_len));
col_privs->file->ha_index_end(); col_privs->file->ha_index_end();
...@@ -2605,7 +2610,11 @@ static int replace_column_table(GRANT_TABLE *g_t, ...@@ -2605,7 +2610,11 @@ static int replace_column_table(GRANT_TABLE *g_t,
goto end; /* purecov: inspected */ goto end; /* purecov: inspected */
} }
grant_column= new GRANT_COLUMN(column->column,privileges); grant_column= new GRANT_COLUMN(column->column,privileges);
my_hash_insert(&g_t->hash_columns,(uchar*) grant_column); if (my_hash_insert(&g_t->hash_columns,(uchar*) grant_column))
{
result= -1;
goto end;
}
} }
} }
...@@ -3130,12 +3139,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, ...@@ -3130,12 +3139,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
Str->user.str, table_name, Str->user.str, table_name,
rights, rights,
column_priv); column_priv);
if (!grant_table) // end of memory if (!grant_table ||
my_hash_insert(&column_priv_hash,(uchar*) grant_table))
{ {
result= TRUE; /* purecov: deadcode */ result= TRUE; /* purecov: deadcode */
continue; /* purecov: deadcode */ continue; /* purecov: deadcode */
} }
my_hash_insert(&column_priv_hash,(uchar*) grant_table);
} }
/* If revoke_grant, calculate the new column privilege for tables_priv */ /* If revoke_grant, calculate the new column privilege for tables_priv */
...@@ -3339,12 +3348,13 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, ...@@ -3339,12 +3348,13 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
grant_name= new GRANT_NAME(Str->host.str, db_name, grant_name= new GRANT_NAME(Str->host.str, db_name,
Str->user.str, table_name, Str->user.str, table_name,
rights); rights);
if (!grant_name) if (!grant_name ||
my_hash_insert(is_proc ?
&proc_priv_hash : &func_priv_hash,(uchar*) grant_name))
{ {
result= TRUE; result= TRUE;
continue; continue;
} }
my_hash_insert(is_proc ? &proc_priv_hash : &func_priv_hash,(uchar*) grant_name);
} }
if (replace_routine_table(thd, grant_name, tables[1].table, *Str, if (replace_routine_table(thd, grant_name, tables[1].table, *Str,
......
...@@ -2933,7 +2933,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, ...@@ -2933,7 +2933,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
DBUG_PRINT("info", ("inserting table '%s'.'%s' 0x%lx into the cache", DBUG_PRINT("info", ("inserting table '%s'.'%s' 0x%lx into the cache",
table->s->db.str, table->s->table_name.str, table->s->db.str, table->s->table_name.str,
(long) table)); (long) table));
VOID(my_hash_insert(&open_cache,(uchar*) table)); if (my_hash_insert(&open_cache,(uchar*) table))
{
my_free(table, MYF(0));
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL);
}
} }
check_unused(); // Debugging call check_unused(); // Debugging call
......
...@@ -13862,7 +13862,10 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, ...@@ -13862,7 +13862,10 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
goto err; goto err;
} }
else else
(void) my_hash_insert(&hash, org_key_pos); {
if (my_hash_insert(&hash, org_key_pos))
goto err;
}
key_pos+=extra_length; key_pos+=extra_length;
} }
my_free((char*) key_buffer,MYF(0)); my_free((char*) key_buffer,MYF(0));
......
...@@ -2330,8 +2330,8 @@ sp_decl: ...@@ -2330,8 +2330,8 @@ sp_decl:
} }
pctx->declare_var_boundary(0); pctx->declare_var_boundary(0);
lex->sphead->restore_lex(YYTHD); if (lex->sphead->restore_lex(YYTHD))
MYSQL_YYABORT;
$$.vars= $2; $$.vars= $2;
$$.conds= $$.hndlrs= $$.curs= 0; $$.conds= $$.hndlrs= $$.curs= 0;
} }
...@@ -2441,7 +2441,8 @@ sp_cursor_stmt: ...@@ -2441,7 +2441,8 @@ sp_cursor_stmt:
} }
lex->sp_lex_in_use= TRUE; lex->sp_lex_in_use= TRUE;
$$= lex; $$= lex;
lex->sphead->restore_lex(YYTHD); if (lex->sphead->restore_lex(YYTHD))
MYSQL_YYABORT;
} }
; ;
...@@ -2660,7 +2661,8 @@ sp_proc_stmt_statement: ...@@ -2660,7 +2661,8 @@ sp_proc_stmt_statement:
sp->add_instr(i)) sp->add_instr(i))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
sp->restore_lex(thd); if (sp->restore_lex(thd))
MYSQL_YYABORT;
} }
; ;
...@@ -2688,7 +2690,8 @@ sp_proc_stmt_return: ...@@ -2688,7 +2690,8 @@ sp_proc_stmt_return:
MYSQL_YYABORT; MYSQL_YYABORT;
sp->m_flags|= sp_head::HAS_RETURN; sp->m_flags|= sp_head::HAS_RETURN;
} }
sp->restore_lex(YYTHD); if (sp->restore_lex(YYTHD))
MYSQL_YYABORT;
} }
; ;
...@@ -2928,7 +2931,8 @@ sp_if: ...@@ -2928,7 +2931,8 @@ sp_if:
sp->add_cont_backpatch(i) || sp->add_cont_backpatch(i) ||
sp->add_instr(i)) sp->add_instr(i))
MYSQL_YYABORT; MYSQL_YYABORT;
sp->restore_lex(YYTHD); if (sp->restore_lex(YYTHD))
MYSQL_YYABORT;
} }
sp_proc_stmts1 sp_proc_stmts1
{ {
...@@ -2974,7 +2978,9 @@ simple_case_stmt: ...@@ -2974,7 +2978,9 @@ simple_case_stmt:
if (case_stmt_action_expr(lex, $3)) if (case_stmt_action_expr(lex, $3))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sphead->restore_lex(YYTHD); /* For expr $3 */ /* For expr $3 */
if (lex->sphead->restore_lex(YYTHD))
MYSQL_YYABORT;
} }
simple_when_clause_list simple_when_clause_list
else_clause_opt else_clause_opt
...@@ -3024,7 +3030,9 @@ simple_when_clause: ...@@ -3024,7 +3030,9 @@ simple_when_clause:
LEX *lex= Lex; LEX *lex= Lex;
if (case_stmt_action_when(lex, $3, true)) if (case_stmt_action_when(lex, $3, true))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sphead->restore_lex(YYTHD); /* For expr $3 */ /* For expr $3 */
if (lex->sphead->restore_lex(YYTHD))
MYSQL_YYABORT;
} }
THEN_SYM THEN_SYM
sp_proc_stmts1 sp_proc_stmts1
...@@ -3045,7 +3053,9 @@ searched_when_clause: ...@@ -3045,7 +3053,9 @@ searched_when_clause:
LEX *lex= Lex; LEX *lex= Lex;
if (case_stmt_action_when(lex, $3, false)) if (case_stmt_action_when(lex, $3, false))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sphead->restore_lex(YYTHD); /* For expr $3 */ /* For expr $3 */
if (lex->sphead->restore_lex(YYTHD))
MYSQL_YYABORT;
} }
THEN_SYM THEN_SYM
sp_proc_stmts1 sp_proc_stmts1
...@@ -3222,7 +3232,8 @@ sp_unlabeled_control: ...@@ -3222,7 +3232,8 @@ sp_unlabeled_control:
sp->new_cont_backpatch(i) || sp->new_cont_backpatch(i) ||
sp->add_instr(i)) sp->add_instr(i))
MYSQL_YYABORT; MYSQL_YYABORT;
sp->restore_lex(YYTHD); if (sp->restore_lex(YYTHD))
MYSQL_YYABORT;
} }
sp_proc_stmts1 END WHILE_SYM sp_proc_stmts1 END WHILE_SYM
{ {
...@@ -3248,7 +3259,8 @@ sp_unlabeled_control: ...@@ -3248,7 +3259,8 @@ sp_unlabeled_control:
if (i == NULL || if (i == NULL ||
lex->sphead->add_instr(i)) lex->sphead->add_instr(i))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sphead->restore_lex(YYTHD); if (lex->sphead->restore_lex(YYTHD))
MYSQL_YYABORT;
/* We can shortcut the cont_backpatch here */ /* We can shortcut the cont_backpatch here */
i->m_cont_dest= ip+1; i->m_cont_dest= ip+1;
} }
...@@ -11770,7 +11782,8 @@ option_type_value: ...@@ -11770,7 +11782,8 @@ option_type_value:
if (sp->add_instr(i)) if (sp->add_instr(i))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
lex->sphead->restore_lex(thd); if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
} }
} }
; ;
......
...@@ -1315,8 +1315,16 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ...@@ -1315,8 +1315,16 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
share->timestamp_field_offset= i; share->timestamp_field_offset= i;
if (use_hash) if (use_hash)
(void) my_hash_insert(&share->name_hash, if (my_hash_insert(&share->name_hash, (uchar*) field_ptr) )
(uchar*) field_ptr); // never fail {
/*
Set return code 8 here to indicate that an error has
occurred but that the error message already has been
sent (OOM).
*/
error= 8;
goto err;
}
} }
*field_ptr=0; // End marker *field_ptr=0; // End marker
......
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