mirror of
https://github.com/MariaDB/server.git
synced 2025-03-26 17:08:41 +01:00
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. mysys/hash.c: * Debug hook for testing failures in my_hash_insert()
This commit is contained in:
parent
e942adb23d
commit
0a68603058
14 changed files with 117 additions and 40 deletions
|
@ -334,6 +334,7 @@ my_bool my_hash_insert(HASH *info, const uchar *record)
|
|||
size_t idx,halfbuff,hash_nr,first_index;
|
||||
uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2);
|
||||
HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos;
|
||||
DBUG_EXECUTE("fail_hash_insert",return(TRUE););
|
||||
|
||||
if (HASH_UNIQUE & info->flags)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
uchar *x= (uchar *) memdup_root(&mem_root, (uchar*) &xev->xid,
|
||||
sizeof(xev->xid));
|
||||
if (! x)
|
||||
if (!x || my_hash_insert(&xids, x))
|
||||
goto err2;
|
||||
my_hash_insert(&xids, x);
|
||||
}
|
||||
delete ev;
|
||||
}
|
||||
|
|
|
@ -559,7 +559,12 @@ HOSTS";
|
|||
goto err;
|
||||
}
|
||||
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);
|
||||
si->port = atoi(row[port_ind]);
|
||||
|
|
|
@ -119,7 +119,13 @@ int table_mapping::set_table(ulong table_id, TABLE* table)
|
|||
}
|
||||
e->table_id= table_id;
|
||||
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)",
|
||||
table_id, (long) e->table,
|
||||
|
|
15
sql/sp.cc
15
sql/sp.cc
|
@ -1506,7 +1506,8 @@ static bool add_used_routine(LEX *lex, Query_arena *arena,
|
|||
rn->key.length= key->length;
|
||||
rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry);
|
||||
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);
|
||||
rn->belong_to_view= belong_to_view;
|
||||
return TRUE;
|
||||
|
@ -1584,16 +1585,24 @@ void sp_remove_not_own_routines(LEX *lex)
|
|||
dependant on time of life of elements from source hash. It also
|
||||
won't touch lists linking elements in source and destination
|
||||
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++)
|
||||
{
|
||||
Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
2
sql/sp.h
2
sql/sp.h
|
@ -69,7 +69,7 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking,
|
|||
void sp_add_used_routine(LEX *lex, Query_arena *arena,
|
||||
sp_name *rt, char rt_type);
|
||||
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,
|
||||
bool first_no_prelock);
|
||||
int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex,
|
||||
|
|
|
@ -36,10 +36,16 @@ public:
|
|||
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? */
|
||||
my_hash_insert(&m_hashtable, (const uchar *)sp);
|
||||
return my_hash_insert(&m_hashtable, (const uchar *)sp);
|
||||
}
|
||||
|
||||
inline sp_head *lookup(char *name, uint namelen)
|
||||
|
|
|
@ -2087,8 +2087,18 @@ sp_head::reset_lex(THD *thd)
|
|||
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)
|
||||
{
|
||||
DBUG_ENTER("sp_head::restore_lex");
|
||||
|
@ -2099,7 +2109,7 @@ sp_head::restore_lex(THD *thd)
|
|||
|
||||
oldlex= (LEX *)m_lex.pop();
|
||||
if (! oldlex)
|
||||
return; // Nothing to restore
|
||||
DBUG_RETURN(FALSE); // Nothing to restore
|
||||
|
||||
oldlex->trg_table_fields.push_back(&sublex->trg_table_fields);
|
||||
|
||||
|
@ -2115,7 +2125,8 @@ sp_head::restore_lex(THD *thd)
|
|||
Add routines which are used by statement to respective set for
|
||||
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
|
||||
procedures) to multiset of tables used by this routine.
|
||||
|
@ -2127,7 +2138,7 @@ sp_head::restore_lex(THD *thd)
|
|||
delete sublex;
|
||||
}
|
||||
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)
|
|||
tab->lock_type= table->lock_type;
|
||||
tab->lock_count= tab->query_lock_count= 1;
|
||||
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;
|
||||
|
|
|
@ -340,7 +340,7 @@ public:
|
|||
|
||||
@todo Conflicting comment in sp_head.cc
|
||||
*/
|
||||
void
|
||||
bool
|
||||
restore_lex(THD *thd);
|
||||
|
||||
/// Put the instruction on the backpatch list, associated with the label.
|
||||
|
|
|
@ -2400,7 +2400,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
|
|||
privs = cols = 0; /* 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]) &&
|
||||
!key_cmp_if_same(col_privs,key,0,key_prefix_len));
|
||||
col_privs->file->ha_index_end();
|
||||
|
@ -2605,7 +2610,11 @@ static int replace_column_table(GRANT_TABLE *g_t,
|
|||
goto end; /* purecov: inspected */
|
||||
}
|
||||
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,
|
|||
Str->user.str, table_name,
|
||||
rights,
|
||||
column_priv);
|
||||
if (!grant_table) // end of memory
|
||||
if (!grant_table ||
|
||||
my_hash_insert(&column_priv_hash,(uchar*) grant_table))
|
||||
{
|
||||
result= TRUE; /* 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 */
|
||||
|
@ -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,
|
||||
Str->user.str, table_name,
|
||||
rights);
|
||||
if (!grant_name)
|
||||
if (!grant_name ||
|
||||
my_hash_insert(is_proc ?
|
||||
&proc_priv_hash : &func_priv_hash,(uchar*) grant_name))
|
||||
{
|
||||
result= TRUE;
|
||||
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,
|
||||
|
|
|
@ -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",
|
||||
table->s->db.str, table->s->table_name.str,
|
||||
(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
|
||||
|
|
|
@ -13862,7 +13862,10 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
|
|||
goto err;
|
||||
}
|
||||
else
|
||||
(void) my_hash_insert(&hash, org_key_pos);
|
||||
{
|
||||
if (my_hash_insert(&hash, org_key_pos))
|
||||
goto err;
|
||||
}
|
||||
key_pos+=extra_length;
|
||||
}
|
||||
my_free((char*) key_buffer,MYF(0));
|
||||
|
|
|
@ -2330,8 +2330,8 @@ sp_decl:
|
|||
}
|
||||
|
||||
pctx->declare_var_boundary(0);
|
||||
lex->sphead->restore_lex(YYTHD);
|
||||
|
||||
if (lex->sphead->restore_lex(YYTHD))
|
||||
MYSQL_YYABORT;
|
||||
$$.vars= $2;
|
||||
$$.conds= $$.hndlrs= $$.curs= 0;
|
||||
}
|
||||
|
@ -2441,7 +2441,8 @@ sp_cursor_stmt:
|
|||
}
|
||||
lex->sp_lex_in_use= TRUE;
|
||||
$$= lex;
|
||||
lex->sphead->restore_lex(YYTHD);
|
||||
if (lex->sphead->restore_lex(YYTHD))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -2660,7 +2661,8 @@ sp_proc_stmt_statement:
|
|||
sp->add_instr(i))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp->restore_lex(thd);
|
||||
if (sp->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -2688,7 +2690,8 @@ sp_proc_stmt_return:
|
|||
MYSQL_YYABORT;
|
||||
sp->m_flags|= sp_head::HAS_RETURN;
|
||||
}
|
||||
sp->restore_lex(YYTHD);
|
||||
if (sp->restore_lex(YYTHD))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -2928,7 +2931,8 @@ sp_if:
|
|||
sp->add_cont_backpatch(i) ||
|
||||
sp->add_instr(i))
|
||||
MYSQL_YYABORT;
|
||||
sp->restore_lex(YYTHD);
|
||||
if (sp->restore_lex(YYTHD))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp_proc_stmts1
|
||||
{
|
||||
|
@ -2974,7 +2978,9 @@ simple_case_stmt:
|
|||
if (case_stmt_action_expr(lex, $3))
|
||||
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
|
||||
else_clause_opt
|
||||
|
@ -3024,7 +3030,9 @@ simple_when_clause:
|
|||
LEX *lex= Lex;
|
||||
if (case_stmt_action_when(lex, $3, true))
|
||||
MYSQL_YYABORT;
|
||||
lex->sphead->restore_lex(YYTHD); /* For expr $3 */
|
||||
/* For expr $3 */
|
||||
if (lex->sphead->restore_lex(YYTHD))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
THEN_SYM
|
||||
sp_proc_stmts1
|
||||
|
@ -3045,7 +3053,9 @@ searched_when_clause:
|
|||
LEX *lex= Lex;
|
||||
if (case_stmt_action_when(lex, $3, false))
|
||||
MYSQL_YYABORT;
|
||||
lex->sphead->restore_lex(YYTHD); /* For expr $3 */
|
||||
/* For expr $3 */
|
||||
if (lex->sphead->restore_lex(YYTHD))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
THEN_SYM
|
||||
sp_proc_stmts1
|
||||
|
@ -3222,7 +3232,8 @@ sp_unlabeled_control:
|
|||
sp->new_cont_backpatch(i) ||
|
||||
sp->add_instr(i))
|
||||
MYSQL_YYABORT;
|
||||
sp->restore_lex(YYTHD);
|
||||
if (sp->restore_lex(YYTHD))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp_proc_stmts1 END WHILE_SYM
|
||||
{
|
||||
|
@ -3248,7 +3259,8 @@ sp_unlabeled_control:
|
|||
if (i == NULL ||
|
||||
lex->sphead->add_instr(i))
|
||||
MYSQL_YYABORT;
|
||||
lex->sphead->restore_lex(YYTHD);
|
||||
if (lex->sphead->restore_lex(YYTHD))
|
||||
MYSQL_YYABORT;
|
||||
/* We can shortcut the cont_backpatch here */
|
||||
i->m_cont_dest= ip+1;
|
||||
}
|
||||
|
@ -11770,7 +11782,8 @@ option_type_value:
|
|||
if (sp->add_instr(i))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
lex->sphead->restore_lex(thd);
|
||||
if (lex->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
|
12
sql/table.cc
12
sql/table.cc
|
@ -1315,8 +1315,16 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
|||
share->timestamp_field_offset= i;
|
||||
|
||||
if (use_hash)
|
||||
(void) my_hash_insert(&share->name_hash,
|
||||
(uchar*) field_ptr); // never fail
|
||||
if (my_hash_insert(&share->name_hash, (uchar*) field_ptr) )
|
||||
{
|
||||
/*
|
||||
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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue