[Bf-blender-cvs] [7eb9b7976ff] blender-v2.93-release: Fix T85889: recursive instances result in crash

Jacques Lucke noreply at git.blender.org
Tue Apr 27 12:34:59 CEST 2021


Commit: 7eb9b7976ff4e6ba820595dc59178f1ac189db3e
Author: Jacques Lucke
Date:   Tue Apr 27 12:33:40 2021 +0200
Branches: blender-v2.93-release
https://developer.blender.org/rB7eb9b7976ff4e6ba820595dc59178f1ac189db3e

Fix T85889: recursive instances result in crash

Generally, it would be good to not allow this from happening in the
first place but that is quite tricky because an object does not know
which other object instances it. Similar checks might be necessary
in other places, but this fixes the bug already.

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

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

M	source/blender/blenkernel/intern/object_dupli.cc

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

diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index ddf7826969b..835b62c06bf 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -36,6 +36,7 @@
 #include "BLI_math.h"
 #include "BLI_rand.h"
 #include "BLI_span.hh"
+#include "BLI_vector.hh"
 
 #include "DNA_anim_types.h"
 #include "DNA_collection_types.h"
@@ -73,6 +74,7 @@ using blender::Array;
 using blender::float3;
 using blender::float4x4;
 using blender::Span;
+using blender::Vector;
 
 /* -------------------------------------------------------------------- */
 /** \name Internal Duplicate Context
@@ -90,6 +92,13 @@ struct DupliContext {
   Object *object;
   float space_mat[4][4];
 
+  /**
+   * A stack that contains all the "parent" objects of a particular instance when recursive
+   * instancing is used. This is used to prevent objects from instancing themselves accidentally.
+   * Use a vector instead of a stack because we want to use the #contains method.
+   */
+  Vector<Object *> *instance_stack;
+
   int persistent_id[MAX_DUPLI_RECUR];
   int level;
 
@@ -113,7 +122,8 @@ static void init_context(DupliContext *r_ctx,
                          Depsgraph *depsgraph,
                          Scene *scene,
                          Object *ob,
-                         const float space_mat[4][4])
+                         const float space_mat[4][4],
+                         Vector<Object *> &instance_stack)
 {
   r_ctx->depsgraph = depsgraph;
   r_ctx->scene = scene;
@@ -122,6 +132,7 @@ static void init_context(DupliContext *r_ctx,
 
   r_ctx->object = ob;
   r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
+  r_ctx->instance_stack = &instance_stack;
   if (space_mat) {
     copy_m4_m4(r_ctx->space_mat, space_mat);
   }
@@ -150,6 +161,7 @@ static void copy_dupli_context(
   }
 
   r_ctx->object = ob;
+  r_ctx->instance_stack = ctx->instance_stack;
   if (mat) {
     mul_m4_m4m4(r_ctx->space_mat, (float(*)[4])ctx->space_mat, mat);
   }
@@ -235,12 +247,19 @@ static void make_recursive_duplis(const DupliContext *ctx,
                                   const float space_mat[4][4],
                                   int index)
 {
+  if (ctx->instance_stack->contains(ob)) {
+    /* Avoid recursive instances. */
+    printf("Warning: '%s' object is trying to instance itself.\n", ob->id.name + 2);
+    return;
+  }
   /* Simple preventing of too deep nested collections with #MAX_DUPLI_RECUR. */
   if (ctx->level < MAX_DUPLI_RECUR) {
     DupliContext rctx;
     copy_dupli_context(&rctx, ctx, ob, space_mat, index);
     if (rctx.gen) {
+      ctx->instance_stack->append(ob);
       rctx.gen->make_duplis(&rctx);
+      ctx->instance_stack->remove_last();
     }
   }
 }
@@ -1588,7 +1607,9 @@ ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob)
 {
   ListBase *duplilist = (ListBase *)MEM_callocN(sizeof(ListBase), "duplilist");
   DupliContext ctx;
-  init_context(&ctx, depsgraph, sce, ob, nullptr);
+  Vector<Object *> instance_stack;
+  instance_stack.append(ob);
+  init_context(&ctx, depsgraph, sce, ob, nullptr, instance_stack);
   if (ctx.gen) {
     ctx.duplilist = duplilist;
     ctx.gen->make_duplis(&ctx);



More information about the Bf-blender-cvs mailing list