From af808361c5025e761d5dc635149e7e5f88c8ed25 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Thu, 2 Jan 2025 20:24:06 +0100 Subject: [PATCH] Fix double free of esp32 uart driver on close - Also fix usage of memory_ensure_free in esp32 uart driver - Also remove unnecessary condition in context_destroy Signed-off-by: Paul Guyot --- CHANGELOG.md | 1 + src/libAtomVM/context.c | 4 +--- .../esp32/components/avm_builtins/uart_driver.c | 9 +++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18b7d8d9c..091339644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ certain VM instructions are used. - Fixed an issue where a timeout would occur immediately in a race condition - Fixed SPI close command - Added missing lock on socket structure +- Fixed a double free when esp32 uart driver was closed, yielding an assert abort ## [0.6.5] - 2024-10-15 diff --git a/src/libAtomVM/context.c b/src/libAtomVM/context.c index 46cff747e..1fd22be10 100644 --- a/src/libAtomVM/context.c +++ b/src/libAtomVM/context.c @@ -178,9 +178,7 @@ void context_destroy(Context *ctx) // globalcontext_get_process_lock before accessing platform_data. // Here, the context can no longer be acquired with // globalcontext_get_process_lock, so it's safe to free the pointer. - if (ctx->platform_data) { - free(ctx->platform_data); - } + free(ctx->platform_data); free(ctx); } diff --git a/src/platforms/esp32/components/avm_builtins/uart_driver.c b/src/platforms/esp32/components/avm_builtins/uart_driver.c index 22f9ed398..8f141d77b 100644 --- a/src/platforms/esp32/components/avm_builtins/uart_driver.c +++ b/src/platforms/esp32/components/avm_builtins/uart_driver.c @@ -309,7 +309,7 @@ static void uart_driver_do_read(Context *ctx, GenMessage gen_message) int local_pid = term_to_local_process_id(pid); if (uart_data->reader_process_pid != term_invalid_term()) { - if (UNLIKELY(memory_ensure_free(ctx, TUPLE_SIZE(2) * 2 + REF_SIZE) != MEMORY_GC_OK)) { + if (UNLIKELY(memory_ensure_free_with_roots(ctx, TUPLE_SIZE(2) * 2 , 1, &ref, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { ESP_LOGE(TAG, "[uart_driver_do_read] Failed to allocate space for error tuple"); globalcontext_send_message(glb, local_pid, MEMORY_ATOM); return; @@ -326,7 +326,7 @@ static void uart_driver_do_read(Context *ctx, GenMessage gen_message) if (count > 0) { int bin_size = term_binary_heap_size(count); - if (UNLIKELY(memory_ensure_free(ctx, bin_size + TUPLE_SIZE(2) * 2 + REF_SIZE) != MEMORY_GC_OK)) { + if (UNLIKELY(memory_ensure_free_with_roots(ctx, bin_size + TUPLE_SIZE(2) * 2, 1, &ref, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { ESP_LOGE(TAG, "[uart_driver_do_read] Failed to allocate space for return value"); globalcontext_send_message(glb, local_pid, MEMORY_ATOM); } @@ -387,7 +387,7 @@ static void uart_driver_do_write(Context *ctx, GenMessage gen_message) free(buffer); int local_pid = term_to_local_process_id(pid); - if (UNLIKELY(memory_ensure_free(ctx, TUPLE_SIZE(2) + REF_SIZE) != MEMORY_GC_OK)) { + if (UNLIKELY(memory_ensure_free_with_roots(ctx, TUPLE_SIZE(2), 1, &ref, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { ESP_LOGE(TAG, "[uart_driver_do_write] Failed to allocate space for return value"); globalcontext_send_message(glb, local_pid, MEMORY_ATOM); } @@ -406,7 +406,7 @@ static void uart_driver_do_close(Context *ctx, GenMessage gen_message) sys_unregister_listener(glb, &uart_data->listener); - if (UNLIKELY(memory_ensure_free(ctx, TUPLE_SIZE(2) + REF_SIZE) != MEMORY_GC_OK)) { + if (UNLIKELY(memory_ensure_free_with_roots(ctx, TUPLE_SIZE(2), 1, &ref, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { ESP_LOGE(TAG, "[uart_driver_do_close] Failed to allocate space for return value"); globalcontext_send_message(glb, local_pid, MEMORY_ATOM); } @@ -419,6 +419,7 @@ static void uart_driver_do_close(Context *ctx, GenMessage gen_message) } free(uart_data); + ctx->platform_data = NULL; } static NativeHandlerResult uart_driver_consume_mailbox(Context *ctx)