Fix (unreported) potential issue in new `BKE_libblock_relink_to_newid_new`

Remapping code could call collection resync code while processing
remapping, which is a good way to crash by accessing no-more-valid
pointers.

Similar issue as with liboverrides resync, fixed the same way by
preventing any collection resync until whole remapping has been done.

This was probably not an issue in practice in current code, since this
is only used by append code currently, which should not affect
layers/collections in current scene yet.
This commit is contained in:
Bastien Montagne 2021-10-28 11:57:20 +02:00
parent 289843119d
commit aebb3d3062
1 changed files with 16 additions and 3 deletions

View File

@ -716,6 +716,7 @@ void BKE_libblock_relink_to_newid(ID *id)
* FIXME: Port all usages of #BKE_libblock_relink_to_newid to this
* #BKE_libblock_relink_to_newid_new new code and remove old one.
************************** */
static void libblock_relink_to_newid_new(Main *bmain, ID *id);
static int id_relink_to_newid_looper_new(LibraryIDLinkCallbackData *cb_data)
{
const int cb_flag = cb_data->cb_flag;
@ -739,12 +740,22 @@ static int id_relink_to_newid_looper_new(LibraryIDLinkCallbackData *cb_data)
}
if (id->tag & LIB_TAG_NEW) {
id->tag &= ~LIB_TAG_NEW;
BKE_libblock_relink_to_newid_new(bmain, id);
libblock_relink_to_newid_new(bmain, id);
}
}
return IDWALK_RET_NOP;
}
static void libblock_relink_to_newid_new(Main *bmain, ID *id)
{
if (ID_IS_LINKED(id)) {
return;
}
id->tag &= ~LIB_TAG_NEW;
BKE_library_foreach_ID_link(bmain, id, id_relink_to_newid_looper_new, NULL, 0);
}
/**
* Remaps ID usages of given ID to their `id->newid` pointer if not None, and proceeds recursively
* in the dependency tree of IDs for all data-blocks tagged with `LIB_TAG_NEW`.
@ -762,6 +773,8 @@ void BKE_libblock_relink_to_newid_new(Main *bmain, ID *id)
/* We do not want to have those cached relationship data here. */
BLI_assert(bmain->relations == NULL);
id->tag &= ~LIB_TAG_NEW;
BKE_library_foreach_ID_link(bmain, id, id_relink_to_newid_looper_new, NULL, 0);
BKE_layer_collection_resync_forbid();
libblock_relink_to_newid_new(bmain, id);
BKE_layer_collection_resync_allow();
BKE_main_collection_sync_remap(bmain);
}