From 8bc308b4e1193cc00cb910cc55b8ad7f74ef51d0 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Tue, 1 Mar 2022 22:43:33 +0100 Subject: [PATCH] main: fix double free of screen_off_bg lv_obj If the Alarm is set, then switch away from the Alarm Screen and turn off display to get the "Screen is OFF" overlay. When the alarm rings the Screen is switched to the Alarm Screen, which triggers the current screen (for example the Clock/WatchFace) to issue an `lv_obj_clean()` call. This call removes the `screen_off_bg` object, before the main `refresh_sceen()` of the simulator can do it. Later the simulator tries to remove the `screen_off_bg` object again, which is a double-free of memory resulting in a segfault. To prevent this segfault add a callback to the `screen_off_bg` callback which informs the simulator, that the object has already been removed. Fixes: https://github.com/InfiniTimeOrg/InfiniSim/issues/8 --- main.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/main.cpp b/main.cpp index 1f9a255..568f5db 100644 --- a/main.cpp +++ b/main.cpp @@ -617,6 +617,17 @@ public: std::cout << "unhandled screen_idx: " << int(screen_idx) << std::endl; } } + static void screen_off_delete_cb(lv_obj_t *obj, lv_event_t event) + { + if (event == LV_EVENT_DELETE) { + auto* fw = static_cast(obj->user_data); + if (obj == fw->screen_off_bg) + { + // on delete make sure to not double free the screen_off objects + fw->screen_off_created = false; + } + } + } // render the current status of the simulated controller void refresh_screen() { const Pinetime::Controllers::BrightnessController::Levels level = brightnessController.Level(); @@ -627,6 +638,8 @@ public: lv_obj_set_size(screen_off_bg, 240, 240); lv_obj_set_pos(screen_off_bg, 0, 0); lv_obj_set_style_local_bg_color(screen_off_bg, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + screen_off_bg->user_data = this; // add callback to prevent double free through Alarm Screen + lv_obj_set_event_cb(screen_off_bg, screen_off_delete_cb); screen_off_label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(screen_off_label, "Screen is OFF"); lv_obj_align(screen_off_label, nullptr, LV_ALIGN_CENTER, 0, -20);