From f283ce22408ad5d9817d398bc18e1cdd0dd3651c Mon Sep 17 00:00:00 2001 From: Peter M Date: Sat, 4 Jul 2026 14:06:46 +0200 Subject: [PATCH] Fix memory leaks in globalcontext_destroy Fix modules table cleanup on globalcontext_new errors Use valueshashtable_destroy when unwinding after modules_table has been allocated so its buckets and SMP lock are released consistently with normal GlobalContext teardown. Signed-off-by: Peter M --- src/libAtomVM/globalcontext.c | 20 ++++++++++++-------- src/libAtomVM/valueshashtable.c | 23 +++++++++++++++++++++++ src/libAtomVM/valueshashtable.h | 1 + 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/libAtomVM/globalcontext.c b/src/libAtomVM/globalcontext.c index 79b8bfd757..ee9031f976 100644 --- a/src/libAtomVM/globalcontext.c +++ b/src/libAtomVM/globalcontext.c @@ -108,7 +108,7 @@ GlobalContext *globalcontext_new(void) #ifndef AVM_NO_SMP glb->modules_lock = smp_rwlock_create(); if (IS_NULL_PTR(glb->modules_lock)) { - free(glb->modules_table); + valueshashtable_destroy(glb->modules_table); atom_table_destroy(glb->atom_table); free(glb); return NULL; @@ -140,7 +140,7 @@ GlobalContext *globalcontext_new(void) #ifndef AVM_NO_SMP smp_rwlock_destroy(glb->modules_lock); #endif - free(glb->modules_table); + valueshashtable_destroy(glb->modules_table); atom_table_destroy(glb->atom_table); free(glb); return NULL; @@ -155,7 +155,7 @@ GlobalContext *globalcontext_new(void) #ifndef AVM_NO_SMP smp_rwlock_destroy(glb->modules_lock); #endif - free(glb->modules_table); + valueshashtable_destroy(glb->modules_table); atom_table_destroy(glb->atom_table); free(glb); return NULL; @@ -171,7 +171,7 @@ GlobalContext *globalcontext_new(void) #ifndef AVM_NO_SMP smp_rwlock_destroy(glb->modules_lock); #endif - free(glb->modules_table); + valueshashtable_destroy(glb->modules_table); atom_table_destroy(glb->atom_table); free(glb); return NULL; @@ -185,7 +185,7 @@ GlobalContext *globalcontext_new(void) #ifndef AVM_NO_SMP smp_rwlock_destroy(glb->modules_lock); #endif - free(glb->modules_table); + valueshashtable_destroy(glb->modules_table); atom_table_destroy(glb->atom_table); free(glb); return NULL; @@ -199,7 +199,7 @@ GlobalContext *globalcontext_new(void) #ifndef AVM_NO_SMP smp_rwlock_destroy(glb->modules_lock); #endif - free(glb->modules_table); + valueshashtable_destroy(glb->modules_table); atom_table_destroy(glb->atom_table); free(glb); return NULL; @@ -215,7 +215,7 @@ GlobalContext *globalcontext_new(void) resource_type_destroy(glb->posix_fd_resource_type); #endif smp_rwlock_destroy(glb->modules_lock); - free(glb->modules_table); + valueshashtable_destroy(glb->modules_table); atom_table_destroy(glb->atom_table); free(glb); return NULL; @@ -227,7 +227,7 @@ GlobalContext *globalcontext_new(void) resource_type_destroy(glb->posix_fd_resource_type); #endif smp_rwlock_destroy(glb->modules_lock); - free(glb->modules_table); + valueshashtable_destroy(glb->modules_table); atom_table_destroy(glb->atom_table); free(glb); return NULL; @@ -311,6 +311,10 @@ COLD_FUNC void globalcontext_destroy(GlobalContext *glb) synclist_destroy(&glb->registered_processes); synclist_destroy(&glb->processes_table); + valueshashtable_destroy(glb->modules_table); + free(glb->modules_by_index); + atom_table_destroy(glb->atom_table); + free(glb); } diff --git a/src/libAtomVM/valueshashtable.c b/src/libAtomVM/valueshashtable.c index 5530421487..9f5b7594e8 100644 --- a/src/libAtomVM/valueshashtable.c +++ b/src/libAtomVM/valueshashtable.c @@ -145,3 +145,26 @@ int valueshashtable_has_key(const struct ValuesHashTable *hash_table, uintptr_t SMP_UNLOCK(hash_table); return 0; } + +void valueshashtable_destroy(struct ValuesHashTable *hash_table) +{ + if (IS_NULL_PTR(hash_table)) { + return; + } + + for (size_t i = 0; i < hash_table->capacity; i++) { + struct HNode *node = hash_table->buckets[i]; + while (node) { + struct HNode *tmp = node->next; + free(node); + node = tmp; + } + } + free(hash_table->buckets); + +#ifndef AVM_NO_SMP + smp_rwlock_destroy(hash_table->lock); +#endif + + free(hash_table); +} diff --git a/src/libAtomVM/valueshashtable.h b/src/libAtomVM/valueshashtable.h index 3aec410f11..800e577995 100644 --- a/src/libAtomVM/valueshashtable.h +++ b/src/libAtomVM/valueshashtable.h @@ -48,6 +48,7 @@ struct ValuesHashTable }; struct ValuesHashTable *valueshashtable_new(void); +void valueshashtable_destroy(struct ValuesHashTable *hash_table); int valueshashtable_insert(struct ValuesHashTable *hash_table, uintptr_t key, uintptr_t value); uintptr_t valueshashtable_get_value(const struct ValuesHashTable *hash_table, uintptr_t key, uintptr_t default_value); int valueshashtable_has_key(const struct ValuesHashTable *hash_table, uintptr_t key);