From bcb5f9475e8b945fa67cf248ab7ffc34b9de9fe4 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Thu, 16 Jan 2014 10:29:51 +0000 Subject: [PATCH] [CDMAKE] - 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 --- reactos/tools/cdmake/dirhash.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/reactos/tools/cdmake/dirhash.c b/reactos/tools/cdmake/dirhash.c index c2f02f18070..b7d0b4445f6 100644 --- a/reactos/tools/cdmake/dirhash.c +++ b/reactos/tools/cdmake/dirhash.c @@ -10,7 +10,7 @@ djb_hash(const char *name) { unsigned int val = 5381; int i = 0; - + for (i = 0; name[i]; i++) { val = (33 * val) + name[i]; @@ -65,6 +65,19 @@ get_entry_by_normname(struct target_dir_hash *dh, const char *norm) 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) { int i, tgt; @@ -147,9 +160,9 @@ void dir_hash_add_file(struct target_dir_hash *dh, const char *source, const cha } struct target_dir_entry * -dir_hash_next_dir(struct target_dir_hash *dh, struct target_dir_traversal *t) +dir_hash_next_dir(struct target_dir_hash *dh, struct target_dir_traversal *t) { - if (t->i == -1) + if (t->i == -1) return NULL; if (!t->it) { @@ -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_dir_entry *te; + unsigned int hashcode; while ((te = de->child)) { de->child = te->next; - dir_hash_destroy_dir(te); + dir_hash_destroy_dir(dh, te); free(te); } while ((tf = de->head)) @@ -194,11 +209,12 @@ void dir_hash_destroy_dir(struct target_dir_entry *de) free(tf->target_name); free(tf); } + delete_entry_by_normname(dh, de->normalized_name); free(de->normalized_name); free(de->case_name); } void dir_hash_destroy(struct target_dir_hash *dh) { - dir_hash_destroy_dir(&dh->root); + dir_hash_destroy_dir(dh, &dh->root); }