From 7119b7488b6452c4d9e62bdbe290bf4955fdf7b5 Mon Sep 17 00:00:00 2001 From: Neo Xu Date: Mon, 11 Dec 2023 21:55:32 +0800 Subject: [PATCH] fix(display): check NULL act_screen before using it (#4973) Signed-off-by: Xu Xingliang Co-authored-by: Gabor Kiss-Vamosi --- src/display/lv_display.c | 28 ++++++++++++++----------- tests/src/test_cases/test_screen_load.c | 15 +++++++++++++ 2 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 tests/src/test_cases/test_screen_load.c diff --git a/src/display/lv_display.c b/src/display/lv_display.c index 3b781297a..7772cf322 100644 --- a/src/display/lv_display.c +++ b/src/display/lv_display.c @@ -542,7 +542,7 @@ void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, ui if(d->del_prev) { lv_obj_delete(act_scr); } - act_scr = d->scr_to_load; + act_scr = lv_screen_active(); /*Active screen changed.*/ } d->scr_to_load = new_scr; @@ -557,18 +557,18 @@ void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, ui /*Be sure there is no other animation on the screens*/ lv_anim_delete(new_scr, NULL); - lv_anim_delete(lv_screen_active(), NULL); + if(act_scr) lv_anim_delete(act_scr, NULL); /*Be sure both screens are in a normal position*/ lv_obj_set_pos(new_scr, 0, 0); - lv_obj_set_pos(lv_screen_active(), 0, 0); + if(act_scr) lv_obj_set_pos(act_scr, 0, 0); lv_obj_remove_local_style_prop(new_scr, LV_STYLE_OPA, 0); - lv_obj_remove_local_style_prop(lv_screen_active(), LV_STYLE_OPA, 0); + if(act_scr) lv_obj_remove_local_style_prop(act_scr, LV_STYLE_OPA, 0); /*Shortcut for immediate load*/ if(time == 0 && delay == 0) { scr_load_internal(new_scr); - if(auto_del) lv_obj_delete(act_scr); + if(auto_del && act_scr) lv_obj_delete(act_scr); return; } @@ -582,7 +582,7 @@ void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, ui lv_anim_t a_old; lv_anim_init(&a_old); - lv_anim_set_var(&a_old, d->act_scr); + lv_anim_set_var(&a_old, act_scr); lv_anim_set_duration(&a_old, time); lv_anim_set_delay(&a_old, delay); @@ -662,10 +662,10 @@ void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, ui break; } - lv_obj_send_event(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); + if(act_scr) lv_obj_send_event(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); lv_anim_start(&a_new); - lv_anim_start(&a_old); + if(act_scr) lv_anim_start(&a_old); } /*--------------------- @@ -894,19 +894,23 @@ static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_d static void scr_load_internal(lv_obj_t * scr) { + /*scr must not be NULL, but d->act_scr might be*/ + LV_ASSERT_NULL(scr); + if(scr == NULL) return; + lv_display_t * d = lv_obj_get_disp(scr); if(!d) return; /*Shouldn't happen, just to be sure*/ lv_obj_t * old_scr = d->act_scr; - if(d->act_scr) lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); - if(d->act_scr) lv_obj_send_event(scr, LV_EVENT_SCREEN_LOAD_START, NULL); + if(old_scr) lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); + lv_obj_send_event(scr, LV_EVENT_SCREEN_LOAD_START, NULL); d->act_scr = scr; d->scr_to_load = NULL; - if(d->act_scr) lv_obj_send_event(scr, LV_EVENT_SCREEN_LOADED, NULL); - if(d->act_scr) lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL); + lv_obj_send_event(scr, LV_EVENT_SCREEN_LOADED, NULL); + if(old_scr) lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL); lv_obj_invalidate(scr); } diff --git a/tests/src/test_cases/test_screen_load.c b/tests/src/test_cases/test_screen_load.c new file mode 100644 index 000000000..712165071 --- /dev/null +++ b/tests/src/test_cases/test_screen_load.c @@ -0,0 +1,15 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" + +#include "unity/unity.h" + +void test_screen_load_no_crash(void) +{ + /*Delete active screen and load new screen should not crash*/ + lv_obj_t * screen = lv_screen_active(); + lv_obj_del(screen); + screen = lv_obj_create(NULL); + lv_screen_load(screen); +} + +#endif