LibOverride: Fix use-after-free error when freeing whole Main DB.

We do not want to touch to other ID pointers in that case, those might
have already been freed...
This commit is contained in:
Bastien Montagne 2019-08-29 14:49:54 +02:00
parent 6b33bd1067
commit 7f23c91478
4 changed files with 13 additions and 11 deletions

View File

@ -35,8 +35,8 @@ bool BKE_override_library_is_enabled(void);
struct IDOverrideLibrary *BKE_override_library_init(struct ID *local_id, struct ID *reference_id);
void BKE_override_library_copy(struct ID *dst_id, const struct ID *src_id);
void BKE_override_library_clear(struct IDOverrideLibrary *override);
void BKE_override_library_free(struct IDOverrideLibrary **override);
void BKE_override_library_clear(struct IDOverrideLibrary *override, const bool do_id_user);
void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user);
struct ID *BKE_override_library_create_from_id(struct Main *bmain, struct ID *reference_id);
bool BKE_override_library_create_from_tag(struct Main *bmain);

View File

@ -111,11 +111,11 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id)
if (dst_id->override_library != NULL) {
if (src_id->override_library == NULL) {
BKE_override_library_free(&dst_id->override_library);
BKE_override_library_free(&dst_id->override_library, true);
return;
}
else {
BKE_override_library_clear(dst_id->override_library);
BKE_override_library_clear(dst_id->override_library, true);
}
}
else if (src_id->override_library == NULL) {
@ -144,7 +144,7 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id)
}
/** Clear any overriding data from given \a override. */
void BKE_override_library_clear(IDOverrideLibrary *override)
void BKE_override_library_clear(IDOverrideLibrary *override, const bool do_id_user)
{
BLI_assert(override != NULL);
@ -153,16 +153,18 @@ void BKE_override_library_clear(IDOverrideLibrary *override)
}
BLI_freelistN(&override->properties);
id_us_min(override->reference);
/* override->storage should never be refcounted... */
if (do_id_user) {
id_us_min(override->reference);
/* override->storage should never be refcounted... */
}
}
/** Free given \a override. */
void BKE_override_library_free(struct IDOverrideLibrary **override)
void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user)
{
BLI_assert(*override != NULL);
BKE_override_library_clear(*override);
BKE_override_library_clear(*override, do_id_user);
MEM_freeN(*override);
*override = NULL;
}

View File

@ -757,7 +757,7 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user)
}
if (id->override_library) {
BKE_override_library_free(&id->override_library);
BKE_override_library_free(&id->override_library, do_id_user);
}
/* XXX TODO remove animdata handling from each type's freeing func,

View File

@ -538,7 +538,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_OVERRIDE:
if (id && id->override_library) {
BKE_override_library_free(&id->override_library);
BKE_override_library_free(&id->override_library, true);
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);