2.5: fix for crashes due to access to free'd memory in joining areas,

ripping areas and duplicating windows.
This commit is contained in:
2008-12-18 19:41:36 +00:00
parent af746acaad
commit 93cc4629e3
3 changed files with 29 additions and 12 deletions

View File

@@ -3649,16 +3649,25 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata)
static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
{
uiMenuBlockHandle *menu= userdata;
void (*popup_func)(struct bContext *C, void *arg, int event)= NULL;
void *popup_arg= NULL;
int retval= 0;
ui_handle_menus_recursive(C, event, menu);
/* free if done, does not free handle itself */
if(menu->menuretval) {
if(menu->menuretval == UI_RETURN_OK) {
popup_func= menu->popup_func;
popup_arg= menu->popup_arg;
retval= menu->retvalue;
}
ui_menu_block_free(C, menu);
WM_event_remove_ui_handler(&CTX_wm_window(C)->handlers, ui_handler_popup, ui_handler_remove_popup, menu);
if(menu->menuretval == UI_RETURN_OK && menu->popup_func)
menu->popup_func(C, menu->popup_arg, menu->retvalue);
if(popup_func)
popup_func(C, popup_arg, retval);
}
else {
/* re-enable tooltips */

View File

@@ -264,7 +264,7 @@ static int screen_area_rip_op(bContext *C, wmOperator *op)
/* allocs new screen and adds to newly created window, using window size */
newsc= screen_add(newwin, sc->id.name+2);
win->screen= newsc;
newwin->screen= newsc;
/* copy area to new screen */
area_copy_data((ScrArea *)newsc->areabase.first, sa, 0);
@@ -767,6 +767,7 @@ static int area_split_cancel(bContext *C, wmOperator *op)
if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) {
if (CTX_wm_area(C) == sd->narea) {
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
}
sd->narea = NULL;
}
@@ -1018,6 +1019,7 @@ static int area_join_apply(bContext *C, wmOperator *op)
}
if (CTX_wm_area(C) == jd->sa2) {
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
}
return 1;

View File

@@ -441,6 +441,12 @@ static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
return 1;
}
static int wm_event_always_pass(wmEvent *event)
{
/* some events we always pass on, to ensure proper communication */
return (event->type == TIMER);
}
/* Warning: this function removes a modal handler, when finished */
static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event, IDProperty *properties)
{
@@ -462,8 +468,15 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
retval= ot->modal(C, op, event);
/* putting back screen context */
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, region);
if((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) {
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, region);
}
else {
/* this special cases is for areas and regions that get removed */
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
}
if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
wm_operator_register(CTX_wm_manager(C), op);
@@ -474,7 +487,6 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
handler->op= NULL;
}
/* remove modal handler, operator itself should have been cancelled and freed */
if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
BLI_remlink(handlers, handler);
@@ -524,12 +536,6 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve
return WM_HANDLER_CONTINUE;
}
static int wm_event_always_pass(wmEvent *event)
{
/* some events we always pass on, to ensure proper communication */
return (event->type == TIMER);
}
static int handler_boundbox_test(wmEventHandler *handler, wmEvent *event)
{
if(handler->bbwin) {