2.5: fix for crashes due to access to free'd memory in joining areas,
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 18 Dec 2008 19:41:36 +0000 (19:41 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 18 Dec 2008 19:41:36 +0000 (19:41 +0000)
ripping areas and duplicating windows.

source/blender/editors/interface/interface_handlers.c
source/blender/editors/screen/screen_ops.c
source/blender/windowmanager/intern/wm_event_system.c

index f22431ba73d46894cfee608bc2e8e1aadfc08cac..a0227af6540f050ca0305e6d613438f912139aff 100644 (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 */
index 4514d54e317cf51dbe330a325b3b1b349da5ee30..2342d5c2e8ba9e44171f36dfcb42b0a8c2ec20b0 100644 (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;
index e5d5f7ebc9caa41286682dc26e1cd13d1d7771ca..c015da29ea1a39f2313279a05ac3b9dec0b1a8fc 100644 (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) {