From ea413969f3444525d1c29773a57c7fa5335f1a9a Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 19 Nov 2017 15:40:20 +0100 Subject: [PATCH 1/2] screen:swap(): Avoid segfault on almost-deleted screens When a screen is in the process of being removed, it is still valid, but no longer in the global list of screens (globalconf.screens). In this time frame, trying to swap screens could cause a NULL pointer dereference. Fix this by throwing a Lua error in this case instead. Fixes: https://github.com/awesomeWM/awesome/issues/2110 Signed-off-by: Uli Schlachter --- objects/screen.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/objects/screen.c b/objects/screen.c index 5b701f29..f0943c78 100644 --- a/objects/screen.c +++ b/objects/screen.c @@ -1222,6 +1222,9 @@ luaA_screen_swap(lua_State *L) if(ref_s && ref_swap) break; } + if(!ref_s || !ref_swap) + return luaL_error(L, "Invalid call to screen:swap()"); + /* swap ! */ *ref_s = swap; *ref_swap = s; From c51a2c2f47bf956c12d650a3c86be123c3e14147 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 19 Nov 2017 15:53:07 +0100 Subject: [PATCH 2/2] screen_refresh: Protect against globalconf.screens changing Signed-off-by: Uli Schlachter --- objects/screen.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/objects/screen.c b/objects/screen.c index f0943c78..d0746c3f 100644 --- a/objects/screen.c +++ b/objects/screen.c @@ -640,6 +640,7 @@ screen_refresh(void) globalconf.screen_need_refresh = false; screen_array_t new_screens; + screen_array_t removed_screens; lua_State *L = globalconf_get_lua_State(); bool list_changed = false; @@ -669,6 +670,7 @@ screen_refresh(void) } /* Remove screens which are gone */ + screen_array_init(&removed_screens); for(int i = 0; i < globalconf.screens.len; i++) { screen_t *old_screen = globalconf.screens.tab[i]; bool found = false; @@ -678,15 +680,18 @@ screen_refresh(void) screen_array_take(&globalconf.screens, i); i--; - luaA_object_push(L, old_screen); - screen_removed(L, -1); - lua_pop(L, 1); - luaA_object_unref(L, old_screen); - old_screen->valid = false; - + screen_array_append(&removed_screens, old_screen); list_changed = true; } } + foreach(old_screen, removed_screens) { + luaA_object_push(L, *old_screen); + screen_removed(L, -1); + lua_pop(L, 1); + (*old_screen)->valid = false; + luaA_object_unref(L, *old_screen); + } + screen_array_wipe(&removed_screens); /* Update changed screens */ foreach(existing_screen, globalconf.screens)