From effc6788ebe0958f64b3218fbd341b4091ed016b Mon Sep 17 00:00:00 2001 From: Rangi Date: Wed, 7 Oct 2020 13:20:30 -0400 Subject: [PATCH 1/2] Fix #586 segfault: Update the `charmaps` hashmap when an existing charmap is resized --- include/hashmap.h | 10 ++++++++++ src/asm/charmap.c | 1 + src/hashmap.c | 16 ++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/include/hashmap.h b/include/hashmap.h index fddb0eae..f81664f0 100644 --- a/include/hashmap.h +++ b/include/hashmap.h @@ -33,6 +33,16 @@ typedef struct HashMapEntry *HashMap[HASHMAP_NB_BUCKETS]; */ bool hash_AddElement(HashMap map, char const *key, void *element); +/** + * Replaces an element with an already-present key in a hashmap. + * @warning Inserting a NULL will make `hash_GetElement`'s return ambiguous! + * @param map The HashMap to replace the element in + * @param key The key with which the element will be stored and retrieved + * @param element The element to replace + * @return True if the element was found and replaced + */ +bool hash_ReplaceElement(HashMap const map, char const *key, void *element); + /** * Removes an element from a hashmap. * @param map The HashMap to remove the element from diff --git a/src/asm/charmap.c b/src/asm/charmap.c index c8cfca72..eaddc3e0 100644 --- a/src/asm/charmap.c +++ b/src/asm/charmap.c @@ -173,6 +173,7 @@ void charmap_Add(char *mapping, uint8_t value) if (currentCharmap->usedNodes == currentCharmap->capacity) { currentCharmap->capacity *= 2; currentCharmap = resizeCharmap(currentCharmap, currentCharmap->capacity); + hash_ReplaceElement(charmaps, currentCharmap->name, currentCharmap); } /* Switch to and init new node */ diff --git a/src/hashmap.c b/src/hashmap.c index 76299396..a45cd449 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -64,6 +64,22 @@ bool hash_AddElement(HashMap map, char const *key, void *element) return newEntry->next != NULL; } +bool hash_ReplaceElement(HashMap const map, char const *key, void *element) +{ + HashType hashedKey = hash(key); + struct HashMapEntry *ptr = map[(HalfHashType)hashedKey]; + + while (ptr) { + if (hashedKey >> HALF_HASH_NB_BITS == ptr->hash + && !strcmp(ptr->key, key)) { + ptr->content = element; + return true; + } + ptr = ptr->next; + } + return false; +} + bool hash_RemoveElement(HashMap map, char const *key) { HashType hashedKey = hash(key); From 7c8ec5a5edbdae184ce5c0f6bbcde6037340f209 Mon Sep 17 00:00:00 2001 From: Rangi Date: Thu, 8 Oct 2020 18:10:27 -0400 Subject: [PATCH 2/2] Add a test case for charmaps that segfaults prior to this fix --- test/asm/charmap-inheritance.asm | 23 +++++++++++++++++++++++ test/asm/charmap-inheritance.err | 0 test/asm/charmap-inheritance.out | 0 3 files changed, 23 insertions(+) create mode 100644 test/asm/charmap-inheritance.asm create mode 100644 test/asm/charmap-inheritance.err create mode 100644 test/asm/charmap-inheritance.out diff --git a/test/asm/charmap-inheritance.asm b/test/asm/charmap-inheritance.asm new file mode 100644 index 00000000..eab9c12f --- /dev/null +++ b/test/asm/charmap-inheritance.asm @@ -0,0 +1,23 @@ +SECTION "test", ROM0 + + newcharmap foo + + charmap "", $00 + charmap "", $01 + charmap "", $02 + charmap "", $03 + charmap "", $04 + charmap "", $05 + charmap "", $06 + charmap "", $07 + charmap "", $08 + + ; At this point, enough nodes were allocated for 'foo' to be reallocated. + ; Its value in the charmaps' hashmap should have been updated too, + ; so that usages of 'foo' will not segfault. + + ; This uses 'foo; by switching to it. + setcharmap foo + + ; This uses 'foo' by deriving another charmap from it. + newcharmap bar, foo diff --git a/test/asm/charmap-inheritance.err b/test/asm/charmap-inheritance.err new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/charmap-inheritance.out b/test/asm/charmap-inheritance.out new file mode 100644 index 00000000..e69de29b