added free function into RHashTable (#5249)

This commit is contained in:
Álvaro Felipe Melchor 2016-07-02 11:50:30 +02:00 committed by radare
parent 09435c7317
commit 34fae270dd
6 changed files with 63 additions and 39 deletions

View File

@ -23,6 +23,9 @@ static int cmpfun(void *a, void *b) {
R_API RListRange* r_listrange_new () {
RListRange *s = R_NEW (RListRange);
s->h = r_hashtable64_new ();
s->h->free = (RHashFree)r_list_free;
//s->l shouldn't free is a helper structure to get data in order
//s->h will free the list that contains RAnalFunction
s->l = r_list_new ();
return s;
}
@ -58,11 +61,10 @@ R_API void r_listrange_add(RListRange *s, RAnalFunction *f) {
list = r_hashtable64_lookup (s->h, key);
if (list) {
if (!r_list_contains (list, f))
//r_list_add_sorted (list, f, cmpfun);
r_list_append (list, f);
} else {
list = r_list_new ();
//r_list_add_sorted (list, f, cmpfun);
list->free = (RListFree)r_anal_fcn_free;
r_list_append (list, f);
r_hashtable64_insert (s->h, key, list);
}
@ -76,7 +78,7 @@ R_API void r_listrange_del(RListRange *s, RAnalFunction *f) {
if (!f) return;
from = f->addr;
to = f->addr + f->size;
for (addr = from; addr<to; addr = r_listrange_next (addr)) {
for (addr = from; addr < to; addr = r_listrange_next (addr)) {
list = r_hashtable64_lookup (s->h, r_listrange_key (addr));
if (list) r_list_delete_data (list, f);
}

View File

@ -14,7 +14,7 @@
#define IFDBG if(DO_THE_DBG)
#define IFINT if(0)
R_API RAnalState * r_anal_state_new (ut64 start, ut8* buffer, ut64 len) {
R_API RAnalState * r_anal_state_new(ut64 start, ut8* buffer, ut64 len) {
RAnalState *state = R_NEW0 (RAnalState);
if (!state) return NULL;
state->start = start;
@ -25,6 +25,7 @@ R_API RAnalState * r_anal_state_new (ut64 start, ut8* buffer, ut64 len) {
state->current_bb = NULL;
state->current_fcn = NULL;
state->ht = r_hashtable64_new();
state->ht->free = (RHashFree)r_anal_bb_free;
state->ht_sz = 512;
state->bbs = r_list_new();
state->max_depth = 50;
@ -37,7 +38,7 @@ R_API void r_anal_state_set_depth(RAnalState *state, ut32 depth) {
state->current_depth = depth;
}
R_API void r_anal_state_insert_bb (RAnalState* state, RAnalBlock *bb) {
R_API void r_anal_state_insert_bb(RAnalState* state, RAnalBlock *bb) {
if (!state || !bb)
return;
if (r_anal_state_search_bb (state, bb->addr) == NULL &&
@ -56,7 +57,7 @@ R_API void r_anal_state_insert_bb (RAnalState* state, RAnalBlock *bb) {
}
}
}
R_API RAnalBlock * r_anal_state_search_bb (RAnalState* state, ut64 addr) {
R_API RAnalBlock * r_anal_state_search_bb(RAnalState* state, ut64 addr) {
/*
* Return 0 if no rehash is needed, otherwise return 1
*/
@ -64,13 +65,13 @@ R_API RAnalBlock * r_anal_state_search_bb (RAnalState* state, ut64 addr) {
return tmp_bb;
}
R_API void r_anal_state_free (RAnalState * state) {
r_list_free(state->bbs);
r_hashtable64_free(state->ht);
free(state);
R_API void r_anal_state_free(RAnalState * state) {
r_list_free (state->bbs);
r_hashtable64_free (state->ht);
free (state);
}
R_API ut64 r_anal_state_get_len (RAnalState *state, ut64 addr) {
R_API ut64 r_anal_state_get_len(RAnalState *state, ut64 addr) {
ut64 result = 0;
if (r_anal_state_addr_is_valid (state, addr)) {
result = state->len - (addr - state->start);
@ -78,7 +79,7 @@ R_API ut64 r_anal_state_get_len (RAnalState *state, ut64 addr) {
return result;
}
R_API const ut8 * r_anal_state_get_buf_by_addr (RAnalState *state, ut64 addr) {
R_API const ut8 * r_anal_state_get_buf_by_addr(RAnalState *state, ut64 addr) {
if (r_anal_state_addr_is_valid (state, addr)) {
ut64 offset = addr - state->start;
return state->buffer+offset;
@ -86,7 +87,7 @@ R_API const ut8 * r_anal_state_get_buf_by_addr (RAnalState *state, ut64 addr) {
return NULL;
}
R_API bool r_anal_state_addr_is_valid (RAnalState *state, ut64 addr) {
R_API bool r_anal_state_addr_is_valid(RAnalState *state, ut64 addr) {
return (addr < state->end && addr >= state->start);
}
@ -94,7 +95,7 @@ R_API void r_anal_state_merge_bb_list (RAnalState *state, RList* bbs) {
RListIter *iter;
RAnalBlock *bb;
r_list_foreach (bbs, iter, bb) {
IFDBG eprintf ("Inserting bb fron 0x%04"PFMT64x"\n", bb->addr);
IFDBG eprintf ("Inserting bb from 0x%04"PFMT64x"\n", bb->addr);
r_anal_state_insert_bb (state, bb);
}
}

View File

@ -36,10 +36,7 @@ static void remove_offsetmap(RFlag *f, RFlagItem *item) {
if (fs_off) {
r_list_delete_data (fs_off, item);
if (r_list_empty (fs_off)) {
//make sure to free the list
RList *tmp_list = r_hashtable64_lookup (f->ht_off, XOROFF(item->offset));
r_hashtable64_remove (f->ht_off, XOROFF (item->offset));
r_list_free (tmp_list);
}
}
}
@ -83,7 +80,10 @@ R_API RFlag * r_flag_new() {
return NULL;
}
f->ht_name = r_hashtable64_new ();
f->ht_off = r_hashtable64_new ();
f->ht_off->free = (RHashFree)r_list_free;
for (i = 0; i < R_FLAG_SPACES_MAX; i++) {
f->spaces[i] = NULL;
}
@ -91,13 +91,17 @@ R_API RFlag * r_flag_new() {
}
R_API void r_flag_item_free(RFlagItem *item) {
free (item->color);
free (item->comment);
free (item->alias);
/* release only one of the two pointers if they are the same */
if (item->name != item->realname) free (item->name);
free (item->realname);
free (item);
if (item) {
free (item->color);
free (item->comment);
free (item->alias);
/* release only one of the two pointers if they are the same */
if (item->name != item->realname) {
free (item->name);
}
free (item->realname);
R_FREE (item);
}
}
R_API RFlag *r_flag_free(RFlag *f) {
@ -106,10 +110,6 @@ R_API RFlag *r_flag_free(RFlag *f) {
for (i = 0; i < R_FLAG_SPACES_MAX; i++) {
free (f->spaces[i]);
}
//in our case this is a list so just make sure to free it up
for (i = 0; i < f->ht_off->size_index; i++) {
r_list_free (f->ht_off->table[i].data);
}
r_hashtable64_free (f->ht_off);
r_hashtable64_free (f->ht_name);
r_list_free (f->flags);
@ -317,6 +317,8 @@ R_API RFlagItem *r_flag_set(RFlag *f, const char *name, ut64 off, ut32 size) {
free (item);
return NULL;
}
//item share ownership prone to uaf, that is why only
//f->flags has set up free pointer
r_hashtable64_insert (f->ht_name, item->namehash, item);
r_list_append (f->flags, item);
}
@ -395,7 +397,7 @@ R_API int r_flag_unset(RFlag *f, RFlagItem *item) {
R_API int r_flag_unset_off(RFlag *f, ut64 off) {
RFlagItem *item = r_flag_get_i (f, off);
if (item && r_flag_unset (f, item)) {
free (item);
R_FREE (item);
return true;
}
return false;
@ -427,7 +429,7 @@ R_API int r_flag_unset_name(RFlag *f, const char *name) {
ut64 hash = r_str_hash64 (name);
RFlagItem *item = r_hashtable64_lookup (f->ht_name, hash);
if (item && r_flag_unset (f, item)) {
free (item);
R_FREE (item);
return true;
}
return false;
@ -440,12 +442,15 @@ R_API void r_flag_unset_all(RFlag *f) {
r_list_free (f->flags);
f->flags = r_list_new ();
if (!f->flags) return;
f->flags->free = (RListFree) r_flag_item_free;
f->flags->free = (RListFree)r_flag_item_free;
r_hashtable64_free (f->ht_name);
//don't set free since f->flags will free up items when needed avoiding uaf
f->ht_name = r_hashtable64_new ();
r_hashtable64_free (f->ht_off);
f->ht_off = r_hashtable64_new ();
f->ht_off->free = (RHashFree)r_list_free;
r_flag_space_unset (f, NULL);
}

View File

@ -5,6 +5,9 @@
extern "C" {
#endif
typedef void (*RHashFree)(void *ptr);
/** hashtable **/
typedef struct r_hashtable_entry_t {
ut32 hash;
@ -19,6 +22,7 @@ typedef struct r_hashtable_t {
ut32 size_index;
ut32 entries;
ut32 deleted_entries;
RHashFree free; //function pointer to free data in table
} RHashTable;
typedef struct r_hashtable64_entry_t {
@ -34,6 +38,7 @@ typedef struct r_hashtable64_t {
ut64 size_index;
ut64 entries;
ut64 deleted_entries;
RHashFree free; //function pointer to free data in table
} RHashTable64;
R_API RHashTable* r_hashtable_new(void);

View File

@ -165,11 +165,19 @@ R_API RHT* ht_(new)(void) {
ht->deleted_entries = 0;
ht->rehash = hash_sizes[ht->size_index].rehash;
ht->max_entries = hash_sizes[ht->size_index].max_entries;
ht->free = NULL;
return ht;
}
R_API void ht_(free)(RHT *ht) {
if (ht) {
if (ht->free) {
int i;
for (i = 0; i < ht->size; i++) {
ht->free (ht->table[i].data);
ht->table[i].data = NULL;
}
}
free (ht->table);
free (ht);
}
@ -189,7 +197,7 @@ R_API void *ht_(lookup)(RHT *ht, utH hash) {
* Note that insertion may rearrange the table on a resize or rehash,
* so previously found hash_entries are no longer valid after this function.
*/
R_API bool ht_(insert) (RHT *ht, utH hash, void *data) {
R_API bool ht_(insert)(RHT *ht, utH hash, void *data) {
utH hash_address;
if (ht->entries >= ht->max_entries)
@ -208,7 +216,7 @@ R_API bool ht_(insert) (RHT *ht, utH hash, void *data) {
entry->hash = hash;
entry->data = data;
ht->entries++;
return R_TRUE;
return true;
}
double_hash = hash % ht->rehash;
if (double_hash == 0)
@ -219,13 +227,16 @@ R_API bool ht_(insert) (RHT *ht, utH hash, void *data) {
/* We could hit here if a required resize failed. An unchecked-malloc
* application could ignore this result.
*/
return R_FALSE;
return false;
}
R_API void ht_(remove) (RHT *ht, utH hash) {
R_API void ht_(remove)(RHT *ht, utH hash) {
RHTE *entry = ht_(search) (ht, hash);
if (entry) {
entry->hash = DELETED_HASH;
if (ht->free) {
ht->free (entry->data);
}
entry->data = NULL;
ht->entries--;
ht->deleted_entries++;

View File

@ -296,12 +296,12 @@ fail:
// Compute a 64 bit DJB hash of a string.
R_API ut64 r_str_hash64(const char *s) {
ut64 len, h = 5381;
ut64 len, h = 5381;
if (!s)
return 0;
for (len=strlen (s); len>0; len--)
h = (h^(h<<5)) ^ *s++;
return h;
for (len = strlen (s); len > 0; len--)
h = (h ^ (h << 5)) ^ *s++;
return h;
}
// Compute a 32bit DJB hash of a string.