Fix: PanelType unregister potential use-after-free

There are two issues here. First, the instanced panel freeing uses
the panel type after it's been freed a few lines up in this function.
Second, while panel types are registered for a single space type,
there are cases where they're used in multiple space/region types
anyway. Because of that, removing the dangling pointer of the freed
type from just the registered region & space type combination isn't
enough, we need to process all regions.

Pull Request: https://projects.blender.org/blender/blender/pulls/129676
This commit is contained in:
Hans Goudey
2024-11-01 12:14:44 +01:00
committed by Hans Goudey
parent 7fbc9e9428
commit 37e35147d8

View File

@@ -211,31 +211,25 @@ static bool rna_Panel_unregister(Main *bmain, StructRNA *type)
child_pt->parent = nullptr;
}
const char space_type = pt->space_type;
BLI_freelistN(&pt->children);
BLI_freelinkN(&art->paneltypes, pt);
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype == space_type) {
ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
&sl->regionbase;
LISTBASE_FOREACH (ARegion *, region, regionbase) {
if (region->type == art) {
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
panel_type_clear_recursive(panel, pt);
}
}
/* The unregistered panel might have had a template that added instanced panels,
* so remove them just in case. They can be re-added on redraw anyway. */
UI_panels_free_instanced(nullptr, region);
ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
LISTBASE_FOREACH (ARegion *, region, regionbase) {
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
panel_type_clear_recursive(panel, pt);
}
/* The unregistered panel might have had a template that added instanced panels,
* so remove them just in case. They can be re-added on redraw anyway. */
UI_panels_free_instanced(nullptr, region);
}
}
}
}
BLI_freelistN(&pt->children);
BLI_freelinkN(&art->paneltypes, pt);
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, nullptr);
return true;