Commit: f271d85b865cb5e82b50a29f91d2cabbbede6a9a
Author: Bastien Montagne
Date:   Thu Apr 30 14:04:41 2015 +0200
Branches: master
https://developer.blender.org/rBf271d85b865cb5e82b50a29f91d2cabbbede6a9a

Fix T44439: outliner's treestore could keep invalid ID pointers, could crash on 
undo due to invalid mem access.

We cannot nuke treestore in readfile's `blo_lib_link_screen_restore()`, because 
this will
destroy all UI-state data (like opened/closed items, etc.).

Since we cannot know for sure whether an ID pointer from tselem->id is valid 
here, we
have to ensure they are never invalid, i.e. to always set them to NULL when we 
delete them.

To do so, this commit uses a similar approach as what already exists for ID 
references
in WM notifiers - it extends `free_notifier_reference_cb()` to also nullify 
those IDs in
all outliners.

Note that some ID types are not used(shown) by outliner currently, so 
`TREESTORE_ID_TYPE` macro
was added, that checks whether an ID is possibly used by outliner. Avoids a few 
searches
in whole tree whene deleting some IDs.

Reviewers: campbellbarton, sergey

Maniphest Tasks: T44439

Differential Revision: https://developer.blender.org/D1272

===================================================================

A       source/blender/editors/include/ED_outliner.h
M       source/blender/editors/space_outliner/outliner_edit.c
M       source/blender/editors/space_outliner/outliner_intern.h
M       source/blender/editors/space_outliner/outliner_tree.c
M       source/blender/windowmanager/intern/wm_event_system.c

===================================================================

diff --git a/source/blender/editors/include/ED_outliner.h 
b/source/blender/editors/include/ED_outliner.h
new file mode 100644
index 0000000..af4af8e
--- /dev/null
+++ b/source/blender/editors/include/ED_outliner.h
@@ -0,0 +1,36 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ED_outliner.h
+ *  \ingroup editors
+ */
+
+#ifndef __ED_OUTLINER_H__
+#define __ED_OUTLINER_H__
+
+struct ID;
+struct SpaceOops;
+
+/* Used to check whether a given texture context is valid in current context. 
*/
+void ED_outliner_id_unref(struct SpaceOops *so, const struct ID *id);
+
+#endif /*  __ED_OUTLINER_H__ */
diff --git a/source/blender/editors/space_outliner/outliner_edit.c 
b/source/blender/editors/space_outliner/outliner_edit.c
index 798dae2..058b8c4 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -39,20 +39,24 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_utildefines.h"
+#include "BLI_mempool.h"
 
 #include "BLF_translation.h"
 
 #include "BKE_animsys.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
+#include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
+#include "BKE_outliner_treehash.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_material.h"
 #include "BKE_group.h"
 
 #include "ED_object.h"
+#include "ED_outliner.h"
 #include "ED_screen.h"
 #include "ED_keyframing.h"
 
@@ -1952,3 +1956,35 @@ void OUTLINER_OT_group_link(wmOperatorType *ot)
        /* properties */
        RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", 
"Target Object");
 }
+
+/******** Utils to clear any ref to freed ID... **********/
+
+void ED_outliner_id_unref(SpaceOops *so, const ID *id)
+{
+       /* Some early out checks. */
+       if (!TREESTORE_ID_TYPE(id)) {
+               return;  /* ID type is not used by outilner... */
+       }
+
+       if (so->search_tse.id == id) {
+               so->search_tse.id = NULL;
+       }
+
+       if (so->treestore) {
+               TreeStoreElem *tselem;
+               BLI_mempool_iter iter;
+               bool changed = false;
+
+               BLI_mempool_iternew(so->treestore, &iter);
+               while ((tselem = BLI_mempool_iterstep(&iter))) {
+                       if (tselem->id == id) {
+                               tselem->id = NULL;
+                               changed = true;
+                       }
+               }
+               if (so->treehash && changed) {
+                       /* rebuild hash table, because it depends on ids too */
+                       
BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore);
+               }
+       }
+}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h 
b/source/blender/editors/space_outliner/outliner_intern.h
index b4b73a1..38672ef 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -57,6 +57,10 @@ typedef struct TreeElement {
        PointerRNA rnaptr;         // RNA Pointer
 }  TreeElement;
 
+#define TREESTORE_ID_TYPE(_id) \
+       (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, 
ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
+        ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, 
ID_BR, ID_PA, ID_GD, ID_LS))
+
 /* TreeElement->flag */
 #define TE_ACTIVE       1
 #define TE_ICONROW      2
diff --git a/source/blender/editors/space_outliner/outliner_tree.c 
b/source/blender/editors/space_outliner/outliner_tree.c
index 17a6e952..4b07c40 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -855,6 +855,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, 
ListBase *lb, void *i
                return NULL;
        }
 
+       if (type == 0) {
+               /* Zero type means real ID, ensure we do not get non-outliner 
ID types here... */
+               BLI_assert(TREESTORE_ID_TYPE(id));
+       }
+
        te = MEM_callocN(sizeof(TreeElement), "tree elem");
        /* add to the visual tree */
        BLI_addtail(lb, te);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c 
b/source/blender/windowmanager/intern/wm_event_system.c
index e2b8598..c883b37 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -63,6 +63,7 @@
 
 #include "ED_fileselect.h"
 #include "ED_info.h"
+#include "ED_outliner.h"
 #include "ED_screen.h"
 #include "ED_view3d.h"
 #include "ED_util.h"
@@ -217,6 +218,8 @@ void WM_main_remove_notifier_reference(const void 
*reference)
 {
        Main *bmain = G.main;
        wmWindowManager *wm = bmain->wm.first;
+       bScreen *sc;
+
        if (wm) {
                wmNotifier *note, *note_next;
 
@@ -230,6 +233,22 @@ void WM_main_remove_notifier_reference(const void 
*reference)
                        }
                }
        }
+
+       for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+               ScrArea *sa;
+
+               for (sa = sc->areabase.first; sa; sa = sa->next) {
+                       SpaceLink *sl;
+
+                       for (sl = sa->spacedata.first; sl; sl = sl->next) {
+                               if (sl->spacetype == SPACE_OUTLINER) {
+                                       SpaceOops *so = (SpaceOops *)sl;
+
+                                       ED_outliner_id_unref(so, (ID 
*)reference);
+                               }
+                       }
+               }
+       }
 }
 
 static void wm_notifier_clear(wmNotifier *note)

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to