Fix crashes due to non-uniqueness in ID names in some cases.

Liboverrides are doing some very low-level manipulation of IDs in apply
code, to reduce over-head of name and sorting handling.

This requires specific care to ensure thatr the new namemap runtime data
remains up-to-date and valid. Otherwise, names of existing IDs would be
missing from the map, which would later lead to having several different
IDs with the same name. Critical corruption in Blender ID management.

Reported by animators at the Blender studio.

Regression from rB7f8d05131a77.
This commit is contained in:
Bastien Montagne 2022-07-27 10:49:29 +02:00
parent 4dd409a185
commit 13e17507c0
3 changed files with 13 additions and 3 deletions

View File

@ -254,6 +254,8 @@ enum {
LIB_ID_FREE_NO_DEG_TAG = 1 << 8,
/** Do not attempt to remove freed ID from UI data/notifiers/... */
LIB_ID_FREE_NO_UI_USER = 1 << 9,
/** Do not remove freed ID's name from a potential runtime namemap. */
LIB_ID_FREE_NO_NAMEMAP_REMOVE = 1 << 10,
};
void BKE_libblock_free_datablock(struct ID *id, int flag) ATTR_NONNULL();

View File

@ -152,7 +152,9 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
ListBase *lb = which_libbase(bmain, type);
BLI_remlink(lb, id);
BKE_main_namemap_remove_name(bmain, id, id->name + 2);
if ((flag & LIB_ID_FREE_NO_NAMEMAP_REMOVE) == 0) {
BKE_main_namemap_remove_name(bmain, id, id->name + 2);
}
}
BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);

View File

@ -34,6 +34,7 @@
#include "BKE_lib_query.h"
#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_main_namemap.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@ -3637,6 +3638,9 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
return;
}
/* Remove the pair (idname, lib) of this temp id from the name map. */
BKE_main_namemap_remove_name(bmain, tmp_id, tmp_id->name + 2);
tmp_id->lib = local->lib;
/* This ID name is problematic, since it is an 'rna name property' it should not be editable or
@ -3688,8 +3692,10 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
}
/* Again, horribly inefficient in our case, we need something off-Main
* (aka more generic nolib copy/free stuff)! */
BKE_id_free_ex(bmain, tmp_id, LIB_ID_FREE_NO_UI_USER, true);
* (aka more generic nolib copy/free stuff).
* NOTE: Do not remove this tmp_id's name from the namemap here, since this name actually still
* exists in `bmain`. */
BKE_id_free_ex(bmain, tmp_id, LIB_ID_FREE_NO_UI_USER | LIB_ID_FREE_NO_NAMEMAP_REMOVE, true);
if (GS(local->name) == ID_AR) {
/* Fun times again, thanks to bone pointers in pose data of objects. We keep same ID addresses,