diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2017-06-30 19:59:29 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2017-06-30 20:03:02 +0300 |
commit | 49a35033be60e58ed4910346bc29ffa1954b34ec (patch) | |
tree | c92fb52f035a1df2b71c19cb51f1679c6f027efe | |
parent | b43cdc91ce4188e2fc18ff6646781ff03fbfd693 (diff) |
Fix T51877: Deleting a scene uses freed memory
At the moment libblock_remap_data_preprocess is using
FOREACH_SCENE_OBJECT to iterate over all the objects of the scene and
unlink them.
However we were storing a reference to the Base of the removed object.
Anyways, the loop is now sanitized so that this crash no longer happens.
Also now we have an unittest for this.
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 10 | ||||
-rw-r--r-- | tests/python/render_layer/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/python/render_layer/test_scene_delete.py | 39 |
3 files changed, 45 insertions, 5 deletions
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index caaf482736b..38534f03123 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -565,7 +565,7 @@ void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter) typedef struct SceneObjectsIteratorData { GSet *visited; - LinkData *link; + LinkData *link_next; BLI_Iterator scene_collection_iter; } SceneObjectsIteratorData; @@ -609,10 +609,10 @@ static LinkData *object_base_unique(GSet *gs, LinkData *link) void BKE_scene_objects_iterator_next(BLI_Iterator *iter) { SceneObjectsIteratorData *data = iter->data; - LinkData *link = data->link ? object_base_unique(data->visited, data->link->next) : NULL; + LinkData *link = data->link_next ? object_base_unique(data->visited, data->link_next) : NULL; if (link) { - data->link = link; + data->link_next = link->next; iter->current = link->data; } else { @@ -624,8 +624,8 @@ void BKE_scene_objects_iterator_next(BLI_Iterator *iter) /* get the first unique object of this collection */ LinkData *new_link = object_base_unique(data->visited, sc->objects.first); if (new_link) { - data->link = new_link; - iter->current = data->link->data; + data->link_next = new_link->next; + iter->current = new_link->data; return; } BKE_scene_collections_iterator_next(&data->scene_collection_iter); diff --git a/tests/python/render_layer/CMakeLists.txt b/tests/python/render_layer/CMakeLists.txt index 526b169bc3d..b3c064289a0 100644 --- a/tests/python/render_layer/CMakeLists.txt +++ b/tests/python/render_layer/CMakeLists.txt @@ -170,4 +170,5 @@ RENDER_LAYER_TEST(scene_copy_b) RENDER_LAYER_TEST(scene_copy_c) RENDER_LAYER_TEST(scene_copy_d) RENDER_LAYER_TEST(scene_copy_e) +RENDER_LAYER_TEST(scene_delete) RENDER_LAYER_TEST(scene_write_read) diff --git a/tests/python/render_layer/test_scene_delete.py b/tests/python/render_layer/test_scene_delete.py new file mode 100644 index 00000000000..cd59a446c9a --- /dev/null +++ b/tests/python/render_layer/test_scene_delete.py @@ -0,0 +1,39 @@ +# ############################################################ +# Importing - Same For All Render Layer Tests +# ############################################################ + +import unittest +import os +import sys + +from render_layer_common import * + + +# ############################################################ +# Testing +# ############################################################ + +class UnitTesting(RenderLayerTesting): + def test_scene_delete(self): + """ + See if a scene can be properly deleted + """ + import bpy + + scene = bpy.context.scene + bpy.data.scenes.new('New') + bpy.data.scenes.remove(scene) + + +# ############################################################ +# Main - Same For All Render Layer Tests +# ############################################################ + +if __name__ == '__main__': + import sys + + extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [] + sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else []) + + UnitTesting._extra_arguments = extra_arguments + unittest.main() |