Fix: Some undo crashes related to packed data.

The owner library could keep invalid references to removed archive
libraries after undo.

This should fix the immediate issues reported as #147236, #147095 and #147036.

There is still a known crash, although it is harder to reproduce reliably
from the UI, so it will be handled separately. It is tracked by #147317.
This commit is contained in:
Bastien Montagne
2025-10-07 19:33:24 +02:00
parent 5e6c3e720d
commit 37a676212c

View File

@@ -2749,7 +2749,14 @@ static Main *blo_add_main_for_library(FileData *fd,
if (is_packed_library) {
BLI_assert(lib->flag & LIBRARY_FLAG_IS_ARCHIVE);
BLI_assert(lib->archive_parent_library == reference_lib);
BLI_assert(reference_lib->runtime->archived_libraries.contains(lib));
/* If there is already an archive library in the new set of Mains, but not a 'libmain' for it
* yet, it is the first time that this archive library is effectively used to own a packed
* ID. Since regular libraries have their list of owned archive libs cleared when reused on
* undo, it means that this archive library should yet be listed in its regular owner one,
* and needs to be added there. See also #read_undo_move_libmain_data. */
BLI_assert(!reference_lib->runtime->archived_libraries.contains(lib));
reference_lib->runtime->archived_libraries.append(lib);
BLI_assert(lib->runtime->filedata == nullptr);
lib->runtime->filedata = fd;
@@ -2841,6 +2848,12 @@ static void read_undo_move_libmain_data(FileData *fd, Main *libmain, BHead *bhea
new_main->split_mains->add_new(libmain);
BLI_addtail(&new_main->libraries, curlib);
/* Remove all references to the archive libraries owned by this 'regular' library. The
* archive ones are only moved over into the new Main if some of their IDs are actually
* re-used. Otherwise they are deleted, so the 'regular' library cannot keep references to
* them at this point. See also #blo_add_main_for_library. */
curlib->runtime->archived_libraries = {};
curlib->id.tag |= ID_TAG_UNDO_OLD_ID_REUSED_NOUNDO;
BKE_main_idmap_insert_id(fd->new_idmap_uid, &curlib->id);
if (bhead != nullptr) {