Skip to content

Use-after-free in ui_toast_close(): stale msgbox pointer crashes the next toast #445

Description

@ft972

Version: 2.0.3.2
Hardware: Waveshare ESP32-S3-Touch-LCD-1.9 (CONFIG_TONEX_CONTROLLER_WAVESHARE_169_LANDSCAPE)
ESP-IDF: v5.5.4, LVGL 8.3.11

Problem

ui_toast_close() in main/display.c deletes the message box but leaves the
pointer set:

static void ui_toast_close(void)
{
    ESP_LOGI(TAG, "Closing message box");
    lv_msgbox_close(msgbox_data.mbox);   // deletes the object
}                                        // msgbox_data.mbox still points at it

lv_msgbox_close() calls lv_obj_del() (LVGL 8.3.11,
src/extra/widgets/msgbox/lv_msgbox.c). The next call to ui_show_toast() then
finds the pointer non-NULL and deletes the same object a second time:

if (msgbox_data.mbox != NULL)
{
    lv_obj_del(msgbox_data.mbox);   // freed memory
    msgbox_data.mbox = NULL;
}

Whether this actually crashes depends on whether the heap has reused the block
in the meantime, which is why it looks intermittent rather than reproducible.

Reproduction

Show a toast via UI_ShowToast(), wait more than 3 s so the auto-close timer in
display_task() runs, then show another one. Roughly half the attempts end in a
panic and the device reboots.

Fix

static void ui_toast_close(void)
{
    ESP_LOGI(TAG, "Closing message box");
    lv_msgbox_close(msgbox_data.mbox);
    msgbox_data.mbox = NULL;
}

Evidence

Measured on real hardware over repeated runs that display two toasts more than
3 s apart:

crashes
before the fix 5 of 8
after the fix 0 of 10

esp_reset_reason() returned ESP_RST_PANIC in every failing run.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions