WM: prevent potential freed memory access for the UV unwrapping timer

This commit is contained in:
Campbell Barton
2024-09-21 17:14:24 +10:00
parent a5453ce992
commit 890f06ec42
3 changed files with 34 additions and 7 deletions
+4 -1
View File
@@ -260,7 +260,10 @@ char ED_uvedit_select_mode_get(const Scene *scene);
void ED_uvedit_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, bool select);
/* `uvedit_unwrap_ops.cc` */
const wmTimer *ED_uvedit_live_unwrap_timer();
/** Return true if the timer is managed by live-unwrap. */
bool ED_uvedit_live_unwrap_timer_check(const wmTimer *timer);
/**
* \param win_modal: Support interactive (modal) unwrapping that updates with a timer.
*/
@@ -1005,7 +1005,7 @@ int transformEvent(TransInfo *t, wmOperator *op, const wmEvent *event)
handled = true;
}
else if (event->type == TIMER) {
if (ED_uvedit_live_unwrap_timer() == event->customdata) {
if (ED_uvedit_live_unwrap_timer_check(static_cast<const wmTimer *>(event->customdata))) {
t->redraw |= TREDRAW_HARD;
}
}
@@ -2045,9 +2045,28 @@ static struct {
wmTimer *timer;
} g_live_unwrap = {nullptr};
const wmTimer *ED_uvedit_live_unwrap_timer()
bool ED_uvedit_live_unwrap_timer_check(const wmTimer *timer)
{
return g_live_unwrap.timer;
/* NOTE: don't validate the timer, assume the timer passed in is valid. */
return g_live_unwrap.timer == timer;
}
/**
* In practice the timer should practically always be valid.
* Use this to prevent the unlikely case of a stale timer being set.
*
* Loading a new file while unwrapping is running could cause this for example.
*/
static bool uvedit_live_unwrap_timer_validate(const wmWindowManager *wm)
{
if (g_live_unwrap.timer == nullptr) {
return false;
}
if (BLI_findindex(&wm->timers, g_live_unwrap.timer) != -1) {
return false;
}
g_live_unwrap.timer = nullptr;
return true;
}
void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit, wmWindow *win_modal)
@@ -2078,6 +2097,8 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit, wmWindow *win_mod
if (win_modal) {
wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
/* Clear in the unlikely event this is still set. */
uvedit_live_unwrap_timer_validate(wm);
BLI_assert(!g_live_unwrap.timer);
g_live_unwrap.timer = WM_event_timer_add(wm, win_modal, TIMER, 0.01f);
}
@@ -2121,10 +2142,13 @@ void ED_uvedit_live_unwrap_re_solve()
void ED_uvedit_live_unwrap_end(const bool cancel)
{
if (g_live_unwrap.timer) {
wmWindow *win = g_live_unwrap.timer->win;
wmWindowManager *wm = static_cast<wmWindowManager *>(G_MAIN->wm.first);
WM_event_timer_remove(wm, win, g_live_unwrap.timer);
g_live_unwrap.timer = nullptr;
uvedit_live_unwrap_timer_validate(wm);
if (g_live_unwrap.timer) {
wmWindow *win = g_live_unwrap.timer->win;
WM_event_timer_remove(wm, win, g_live_unwrap.timer);
g_live_unwrap.timer = nullptr;
}
}
if (g_live_unwrap.handles) {