- When deleting a directory entry, also remove it from the hash table. This prevents use after free in the case of a hash collision
CORE-7774 #resolve

svn path=/trunk/; revision=61643
This commit is contained in:
Thomas Faber 2014-01-16 10:29:51 +00:00
parent 4aa5c6f093
commit bcb5f9475e

View file

@ -65,6 +65,19 @@ get_entry_by_normname(struct target_dir_hash *dh, const char *norm)
return de; return de;
} }
static void
delete_entry_by_normname(struct target_dir_hash *dh, const char *norm)
{
unsigned int hashcode;
struct target_dir_entry **ent;
hashcode = djb_hash(norm);
ent = &dh->buckets[hashcode % NUM_DIR_HASH_BUCKETS];
while (*ent && strcmp((*ent)->normalized_name, norm))
ent = &(*ent)->next;
if (*ent)
*ent = (*ent)->next;
}
void normalize_dirname(char *filename) void normalize_dirname(char *filename)
{ {
int i, tgt; int i, tgt;
@ -177,14 +190,16 @@ dir_hash_next_dir(struct target_dir_hash *dh, struct target_dir_traversal *t)
} }
} }
void dir_hash_destroy_dir(struct target_dir_entry *de) static void
dir_hash_destroy_dir(struct target_dir_hash *dh, struct target_dir_entry *de)
{ {
struct target_file *tf; struct target_file *tf;
struct target_dir_entry *te; struct target_dir_entry *te;
unsigned int hashcode;
while ((te = de->child)) while ((te = de->child))
{ {
de->child = te->next; de->child = te->next;
dir_hash_destroy_dir(te); dir_hash_destroy_dir(dh, te);
free(te); free(te);
} }
while ((tf = de->head)) while ((tf = de->head))
@ -194,11 +209,12 @@ void dir_hash_destroy_dir(struct target_dir_entry *de)
free(tf->target_name); free(tf->target_name);
free(tf); free(tf);
} }
delete_entry_by_normname(dh, de->normalized_name);
free(de->normalized_name); free(de->normalized_name);
free(de->case_name); free(de->case_name);
} }
void dir_hash_destroy(struct target_dir_hash *dh) void dir_hash_destroy(struct target_dir_hash *dh)
{ {
dir_hash_destroy_dir(&dh->root); dir_hash_destroy_dir(dh, &dh->root);
} }