From 37a676212c2d72f07b4e686e2e173a3f28dfeaf7 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 7 Oct 2025 19:33:24 +0200 Subject: [PATCH] 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. --- source/blender/blenloader/intern/readfile.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index b3833410a85..3eddb76988c 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -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) {