Page MenuHome

Fix T100286: Crash accessing freed depsgraph object instances
ClosedPublic

Authored by Campbell Barton (campbellbarton) on Aug 23 2022, 8:18 AM.

Details

Summary

Invalidate depsgraph.object_instances when freed, this resolves a crash when accessing the object instances after iteration has finished.

Unlike most other collections, object_instances is only valid while the iterator is in-memory.

The Python/RNA API needs to inline int/string collection lookups so the Python instance can be created before the iterator ends.


Notes:

  • I'd prefer this over D15754 as this also resolves the crash accessing any references held to the object_instances after iteration has finished, where D15754 only disables direct string/int lookups.
  • This change is more intrusive than I'd like, arguably using py_instance here is awkward as allowing integer lookups, only to return freed RNA data isn't so great, nevertheless it avoids the crash in a way the RNA API supports (via RNA_POINTER_INVALIDATE).

Diff Detail

Repository
rB Blender
Branch
TEMP-T100286-ALT (branched from master)
Build Status
Buildable 23457
Build 23457: arc lint + arc unit

Event Timeline

Campbell Barton (campbellbarton) requested review of this revision.Aug 23 2022, 8:18 AM
Campbell Barton (campbellbarton) created this revision.

Add comment why 'py_instance' is used.

  • Diffirentiate between Python succeeding int/str lookups and the success of pyrna_struct_CreatePyObject (which could fail)
Campbell Barton (campbellbarton) retitled this revision from Fix T100286: Crash accessing freed depsgraph instances to Fix T100286: Crash accessing freed depsgraph object instances.Aug 23 2022, 9:18 AM
Bastien Montagne (mont29) requested changes to this revision.Aug 23 2022, 9:56 AM

Generally looks fine, also think that this is a better/nicer solution than D15754...

source/blender/makesrna/intern/rna_depsgraph.c
50

defined so that it can ?

412

eeeek! Guess this works currently because of where di->iter is defined in the struct, was even wrong already in existing code...
Pretty sure this should be explicitly &di->iter.current ?

source/blender/python/intern/bpy_rna.c
2246–2275

Would add a comment here about why this is needed, and the fact that this may return an 'invalidated' PyObject in case the actual data memory is freed by the call to RNA_property_collection_end (with link back to the deg instance objects iterator code) ?
Same with the string subscript function below.

This revision now requires changes to proceed.Aug 23 2022, 9:56 AM

I am not sure why this patch and D15754 are considered to be mutually exclusive. To me the proper API behavior would be the combination of both patches.

The good thing about D15754 is that it explicitly disallows operation which is not supported. Having an error message that an integer and string lookup is not supported on a property is much better than pretending it worked but gave some weird result.

The good thing about this patch is that it prevents accidental use of iterator outside of a loop.

So I'd say both of the changes should go in! ;)

  • Raise an exceptioin instead of returning an invalid (freed) BPy_StructRNA.
Campbell Barton (campbellbarton) marked 2 inline comments as done and an inline comment as not done.Aug 23 2022, 12:02 PM

@Sergey Sharybin (sergey) updated this patch to include the behavior of D15754 without having to add a flag to the collection.

While I'm not totally against having both patches, I wasn't so keen on expanding the API for such a special case.

source/blender/makesrna/intern/rna_depsgraph.c
412

For this iterator the BLI_Iterator was used, not BLI_Iterator.current unlike rna_Depsgraph_ids_get.

This is working as intended, and doesn't depend on the location of BLI_Iterator in RNA_DepsgraphIterator, double checked that putting py_instance first works.

  • Minor tweak to asignment/return.

@Campbell Barton (campbellbarton), I like the updated behavior!

source/blender/makesrna/intern/rna_access.c
4085

How about adding an BLI_assert(RNA_property_type(prop) == PROP_COLLECTION); which is seen in some other functions around?

Same applies to the RNA_property_collection_lookup_string_has_fn.

source/blender/makesrna/intern/rna_depsgraph.c
50

Nope, not done :P

412

Oooooh right, all members of the DepsgraphObjectInstance are only accessors, so the only thing that matters is that they all agree on the type of ptr.data!
Sorry about that.

source/blender/python/intern/bpy_rna.c
2385–2397

This could be de-duplicated with the same code above maybe? E.g. in a pyrna_prop_collection_subscript_end ?

  • Add assertions, move some None check into pyrna_prop_collection_subscript_is_valid_or_error
Campbell Barton (campbellbarton) added inline comments.
source/blender/makesrna/intern/rna_depsgraph.c
50

Thought the re-wording addressed your comment, re-worked again for better clarity.

source/blender/python/intern/bpy_rna.c
2385–2397

Agree with the goal of de-duplicating boiler plate.
An issue with this is it moves Py_DECREF into a function, which can make reference counting a bit more difficult to follow.

if (found) {
  if (result && (pyrna_prop_collection_subscript_is_valid_or_error(result) == -1)) {
    Py_DECREF(result);
    result = NULL; /* The exception has been set. */
  }
  return result;
}

Could be replaced with:

if (found) {
  pyrna_prop_collection_subscript_is_valid_or_error_and_clear(&result);
  return result;
}
Bastien Montagne (mont29) added inline comments.
source/blender/makesrna/intern/rna_depsgraph.c
50

Damn never saw there was a 'suggest edit', much easier to communicate!

source/blender/python/intern/bpy_rna.c
2385–2397

Fair enough, can keep it like for now.

This revision is now accepted and ready to land.Aug 23 2022, 2:50 PM
Campbell Barton (campbellbarton) marked an inline comment as done.

Committed, thanks for review, closing.