Fix T44376: Buttons context, invalid data access
authorCampbell Barton <ideasman42@gmail.com>
Mon, 4 May 2015 05:07:24 +0000 (15:07 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 4 May 2015 06:01:20 +0000 (16:01 +1000)
Removing a scene from the buttons window would crash from a Python operator.

source/blender/blenkernel/BKE_screen.h
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/screen.c
source/blender/editors/include/ED_buttons.h
source/blender/editors/include/ED_screen.h
source/blender/editors/include/ED_util.h
source/blender/editors/space_buttons/buttons_context.c
source/blender/editors/util/ed_util.c
source/blender/windowmanager/intern/wm_init_exit.c

index bb764540da9ba2b9667df4f2929e3b02092fb594..c584051708baa7d5127da47a770491d1a6db16fc 100644 (file)
@@ -273,6 +273,9 @@ void BKE_spacedata_freelist(ListBase *lb);
 void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
 void BKE_spacedata_draw_locks(int set);
 
+void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *));
+void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
+
 /* area/regions */
 struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
 void            BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
index 5b34504184a73cd63ea50a299dc5d52132d67ccb..c24649556fc6cc3326a6775f86f7f868a1bb0a77 100644 (file)
@@ -82,6 +82,7 @@
 #include "BKE_paint.h"
 #include "BKE_rigidbody.h"
 #include "BKE_scene.h"
+#include "BKE_screen.h"
 #include "BKE_sequencer.h"
 #include "BKE_sound.h"
 #include "BKE_unit.h"
@@ -823,6 +824,8 @@ static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce)
        if (sbuts->pinid == &sce->id) {
                sbuts->pinid = NULL;
        }
+
+       BKE_spacedata_id_unref((SpaceLink *)sbuts, &sce->id);
 }
 
 void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
index 36fd598cc7067fd656bbc990e35f7dbf60162312..840e1f99f845087ca9ab85c2546927853b48a664 100644 (file)
@@ -272,6 +272,19 @@ void BKE_spacedata_draw_locks(int set)
        }
 }
 
+static void (*spacedata_id_unref_cb)(struct SpaceLink *sl, const struct ID *id) = NULL;
+
+void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *))
+{
+       spacedata_id_unref_cb = func;
+}
+
+void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id)
+{
+       if (spacedata_id_unref_cb) {
+               spacedata_id_unref_cb(sl, id);
+       }
+}
 
 /* not region itself */
 void BKE_area_region_free(SpaceType *st, ARegion *ar)
index 64c16605dec6f372cc0bff87e3aecd77e51ec264..9a987d7618c4f0c048a97fa05171278c92659bbd 100644 (file)
@@ -37,4 +37,6 @@ bool ED_texture_context_check_particles(const struct bContext *C);
 bool ED_texture_context_check_linestyle(const struct bContext *C);
 bool ED_texture_context_check_others(const struct bContext *C);
 
+void ED_buttons_id_unref(struct SpaceButs *sbuts, const struct ID *id);
+
 #endif /*  __ED_BUTTONS_H__ */
index 5b0b464264490959c5002f5a3fb5120b07055daf..8de9a7f5f88491323ad2e952ebf0be120b664374 100644 (file)
@@ -76,7 +76,6 @@ void  ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
 void    ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
 int     ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco);
 
-
 /* areas */
 void    ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa);
 void    ED_area_exit(struct bContext *C, struct ScrArea *sa);
index 9556c601d1f74fdc120c2e179acb746045dd2c32..496ce7f2c608e04c2094fd68e89b3bb72bd0c26a 100644 (file)
@@ -42,6 +42,8 @@ void    ED_editors_exit(struct bContext *C);
 
 bool    ED_editors_flush_edits(const struct bContext *C, bool for_render);
 
+void ED_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
+
 /* ************** Undo ************************ */
 
 /* undo.c */
index 73091e7f261a322ae6045e3bd0b402882dfaff30..b00a2c54ff950dce37cd1dbb84e08b8f36e7ca21 100644 (file)
@@ -59,6 +59,7 @@
 
 #include "RNA_access.h"
 
+#include "ED_buttons.h"
 #include "ED_armature.h"
 #include "ED_screen.h"
 #include "ED_physics.h"
@@ -1179,3 +1180,28 @@ ID *buttons_context_id_path(const bContext *C)
 
        return NULL;
 }
+
+void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id)
+{
+       if (sbuts->path) {
+               ButsContextPath *path = sbuts->path;
+               int i;
+
+               for (i = 0; i < path->len; i++) {
+                       if (path->ptr[i].id.data == id) {
+                               break;
+                       }
+               }
+
+               if (i == path->len) {
+                       /* pass */
+               }
+               else if (i == 0) {
+                       MEM_SAFE_FREE(sbuts->path);
+               }
+               else {
+                       memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
+                       path->len = i;
+               }
+       }
+}
index 438eb1f38647ff631ed83e23a84ca48592c88781..d162becfe983a75f0fcef7f9f25efb0b577ad244 100644 (file)
@@ -38,6 +38,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_object_types.h"
 #include "DNA_screen_types.h"
+#include "DNA_space_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_packedFile_types.h"
 
 #include "BKE_paint.h"
 
 #include "ED_armature.h"
+#include "ED_buttons.h"
 #include "ED_image.h"
 #include "ED_mesh.h"
 #include "ED_object.h"
+#include "ED_outliner.h"
 #include "ED_paint.h"
 #include "ED_space_api.h"
 #include "ED_util.h"
@@ -318,3 +321,21 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
        glEnd();
        setlinestyle(0);
 }
+
+/**
+ * Use to free ID references within runtime data (stored outside of DNA)
+ *
+ * \note Typically notifiers take care of this,
+ * but there are times we have to free references immediately, see: T44376
+ */
+void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id)
+{
+       switch (sl->spacetype) {
+               case SPACE_OUTLINER:
+                       ED_outliner_id_unref((SpaceOops *)sl, id);
+                       break;
+               case SPACE_BUTS:
+                       ED_buttons_id_unref((SpaceButs *)sl, id);
+                       break;
+       }
+}
index 7ca82c0c03ae958669bbe36d2d699063ec0e946d..b5c267e8a39c0bd3a7ac0a61ec1e2c9e59413fba 100644 (file)
@@ -153,6 +153,7 @@ void WM_init(bContext *C, int argc, const char **argv)
        BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference);   /* library.c */
        BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference);   /* library.c */
        BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */
+       BKE_spacedata_callback_id_unref_set(ED_spacedata_id_unref); /* screen.c */
        DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */
        
        ED_spacetypes_init();   /* editors/space_api/spacetype.c */