Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2013-08-06 09:35:54 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2013-08-06 09:35:54 +0400
commitbff75bafbd7608d5c9c79f51d2941a3c1b9d51bf (patch)
tree01e44ad1303d9ec61ae825b4de19d8baf7321c4f /source/blender/blenloader
parent90b22486c7058b8991bc228a12e8ee599a95d24d (diff)
Fix crash loading .blend files that have multiple outliners in a screen, saved
with recent outliner optimizations (revision 58855, 3 days ago), in any Blender version before this commit. On current Blender it would give a double free warning in the console. The problem is that it creates a temporary TreeStore on file save. However if you have multiple outliners this memory block would always be at the same memory address making it no longer unique. That then meant old memory address lookups on file read were failing. Solution now is to postpone freeing these temporary memory blocks until the end so that they are at unique addresses.
Diffstat (limited to 'source/blender/blenloader')
-rw-r--r--source/blender/blenloader/intern/writefile.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index dc4b1d48ce5..4f0ccd3c626 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2394,7 +2394,7 @@ static void write_region(WriteData *wd, ARegion *ar, int spacetype)
}
}
-static void write_soops(WriteData *wd, SpaceOops *so)
+static void write_soops(WriteData *wd, SpaceOops *so, LinkNode **tmp_mem_list)
{
BLI_mempool *ts = so->treestore;
@@ -2402,18 +2402,35 @@ static void write_soops(WriteData *wd, SpaceOops *so)
int elems = BLI_mempool_count(ts);
/* linearize mempool to array */
TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL;
- TreeStore ts_flat = {elems, elems, data};
-
- /* temporarily replace mempool-treestore by flat-treestore */
- so->treestore = (BLI_mempool *)&ts_flat;
- writestruct(wd, DATA, "SpaceOops", 1, so);
- /* restore old treestore */
- so->treestore = ts;
- writestruct(wd, DATA, "TreeStore", 1, &ts_flat);
+
if (data) {
+ TreeStore *ts_flat = MEM_callocN(sizeof(TreeStore), "TreeStore");
+
+ ts_flat->usedelem = elems;
+ ts_flat->totelem = elems;
+ ts_flat->data = data;
+
+ /* temporarily replace mempool-treestore by flat-treestore */
+ so->treestore = (BLI_mempool *)ts_flat;
+ writestruct(wd, DATA, "SpaceOops", 1, so);
+
+ writestruct(wd, DATA, "TreeStore", 1, ts_flat);
writestruct(wd, DATA, "TreeStoreElem", elems, data);
- MEM_freeN(data);
+
+ /* we do not free the pointers immediately, because if we have multiple
+ * outliners in a screen we might get the same address on the next
+ * malloc, which makes the address no longer unique and so invalid for
+ * lookups on file read, causing crashes or double frees */
+ BLI_linklist_append(tmp_mem_list, ts_flat);
+ BLI_linklist_append(tmp_mem_list, data);
+ }
+ else {
+ so->treestore = NULL;
+ writestruct(wd, DATA, "SpaceOops", 1, so);
}
+
+ /* restore old treestore */
+ so->treestore = ts;
} else {
writestruct(wd, DATA, "SpaceOops", 1, so);
}
@@ -2425,6 +2442,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
ScrArea *sa;
ScrVert *sv;
ScrEdge *se;
+ LinkNode *tmp_mem_list = NULL;
sc= scrbase->first;
while (sc) {
@@ -2501,7 +2519,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
}
else if (sl->spacetype==SPACE_OUTLINER) {
SpaceOops *so= (SpaceOops *)sl;
- write_soops(wd, so);
+ write_soops(wd, so, &tmp_mem_list);
}
else if (sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage *)sl;
@@ -2566,6 +2584,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
sc= sc->id.next;
}
+
+ BLI_linklist_freeN(tmp_mem_list);
/* flush helps the compression for undo-save */
mywrite(wd, MYWRITE_FLUSH, 0);