From 214b24e025d950dbc54520daef0073f9e03db887 Mon Sep 17 00:00:00 2001 From: Damien Picard Date: Mon, 6 Mar 2023 14:09:44 +0100 Subject: [PATCH 1/7] Cleanup: Fix incorrectly formatted multi-line docstring This has the effect that the message is cut off at the end of the first line. I copied the solution from other similar docstrings elsewhere in the code. As far as my regex-fu can tell, there are no other occurrences of this in the codebase. Issue reported by Joan Pujolar in #43295. Pull Request #105474 --- scripts/startup/bl_operators/freestyle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/startup/bl_operators/freestyle.py b/scripts/startup/bl_operators/freestyle.py index 80520450786..12d19b19a84 100644 --- a/scripts/startup/bl_operators/freestyle.py +++ b/scripts/startup/bl_operators/freestyle.py @@ -13,8 +13,8 @@ from bpy.props import ( class SCENE_OT_freestyle_fill_range_by_selection(Operator): - """Fill the Range Min/Max entries by the min/max distance between selected mesh objects and the source object """ - """(either a user-specified object or the active camera)""" + """Fill the Range Min/Max entries by the min/max distance between selected mesh objects and the source object """ \ + """(either a user-specified object or the active camera)""" bl_idname = "scene.freestyle_fill_range_by_selection" bl_label = "Fill Range by Selection" bl_options = {'INTERNAL'} From f1df811899ab07bb5264a05038d2dbc3d2ebd271 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 Feb 2023 16:37:15 +0100 Subject: [PATCH 2/7] Fix (unreported) potential leak in Main freeing function. Could happen in case a 'split-by-libraries' Main is passed to `BKE_main_free`. --- source/blender/blenkernel/intern/main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c index 46094ae2854..0fb52a531ac 100644 --- a/source/blender/blenkernel/intern/main.c +++ b/source/blender/blenkernel/intern/main.c @@ -40,6 +40,13 @@ Main *BKE_main_new() void BKE_main_free(Main *mainvar) { + /* In case this is called on a 'split-by-libraries' list of mains. + * + * Should not happen in typical usages, but can occur e.g. if a file reading is aborted. */ + if (mainvar->next) { + BKE_main_free(mainvar->next); + } + /* also call when reading a file, erase all, etc */ ListBase *lbarray[INDEX_ID_MAX]; int a; From f49a995b2c80c7e583985a41133ad03873ec09d6 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 Feb 2023 16:37:15 +0100 Subject: [PATCH 3/7] Add a mechanism to abort a blend file reading on critical error. This commit introduces a new Main boolean flag that marks is as invalid. Higher-level file reading code does checks on this flag to abort reading process if needed. This is an implementation of the #105083 design task. Given the extense of the change, I do not think this should be considered for 3.5 and previous LTS releases. --- source/blender/blenkernel/BKE_main.h | 7 + source/blender/blenkernel/intern/blendfile.cc | 19 +++ source/blender/blenloader/BLO_readfile.h | 20 +++ .../blenloader/intern/readblenentry.cc | 7 + source/blender/blenloader/intern/readfile.cc | 139 +++++++++++++++--- source/blender/blenloader/intern/readfile.h | 10 +- .../blenloader/intern/versioning_280.c | 2 +- .../blenloader/intern/versioning_290.cc | 2 +- .../blenloader/intern/versioning_300.cc | 2 +- 9 files changed, 179 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index daf394b811a..f4ac0cfd0e7 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -138,6 +138,13 @@ typedef struct Main { */ bool is_locked_for_linking; + /** + * When set, indicates that an unrecoverable error/data corruption was detected. + * Should only be set by readfile code, and used by upper-level code (typically #setup_app_data) + * to cancel a file reading operation. + */ + bool is_read_invalid; + /** * True if this main is the 'GMAIN' of current Blender. * diff --git a/source/blender/blenkernel/intern/blendfile.cc b/source/blender/blenkernel/intern/blendfile.cc index 8f0e462cd27..a0ecb0c95b5 100644 --- a/source/blender/blenkernel/intern/blendfile.cc +++ b/source/blender/blenkernel/intern/blendfile.cc @@ -476,6 +476,13 @@ void BKE_blendfile_read_setup_ex(bContext *C, const bool startup_update_defaults, const char *startup_app_template) { + if (bfd->main->is_read_invalid) { + BKE_reports_prepend(reports->reports, + "File could not be read, critical data corruption detected"); + BLO_blendfiledata_free(bfd); + return; + } + if (startup_update_defaults) { if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) { BLO_update_defaults_startup_blend(bfd->main, startup_app_template); @@ -503,6 +510,10 @@ struct BlendFileData *BKE_blendfile_read(const char *filepath, } BlendFileData *bfd = BLO_read_from_file(filepath, eBLOReadSkip(params->skip_flags), reports); + if (bfd && bfd->main->is_read_invalid) { + BLO_blendfiledata_free(bfd); + bfd = nullptr; + } if (bfd) { handle_subversion_warning(bfd->main, reports); } @@ -519,6 +530,10 @@ struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf, { BlendFileData *bfd = BLO_read_from_memory( filebuf, filelength, eBLOReadSkip(params->skip_flags), reports); + if (bfd && bfd->main->is_read_invalid) { + BLO_blendfiledata_free(bfd); + bfd = nullptr; + } if (bfd) { /* Pass. */ } @@ -535,6 +550,10 @@ struct BlendFileData *BKE_blendfile_read_from_memfile(Main *bmain, { BlendFileData *bfd = BLO_read_from_memfile( bmain, BKE_main_blendfile_path(bmain), memfile, params, reports); + if (bfd && bfd->main->is_read_invalid) { + BLO_blendfiledata_free(bfd); + bfd = nullptr; + } if (bfd) { /* Removing the unused workspaces, screens and wm is useless here, setup_app_data will switch * those lists with the ones from old bmain, which freeing is much more efficient than diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 8b5f9d10044..e28688b6bab 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -288,6 +288,26 @@ struct LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh); */ void BLO_blendhandle_close(BlendHandle *bh); +/** Mark the given Main (and the 'root' local one in case of lib-split Mains) as invalid, and + * generate an error report containing given `message`. */ +void BLO_read_invalidate_message(BlendHandle *bh, struct Main *bmain, const char *message); + +/** + * BLI_assert-like macro to check a condition, and if `false`, fail the whole .blend reading + * process by marking the Main data-base as invalid, and returning provided `_ret_value`. + * + * NOTE: About usages: + * - #BLI_assert should be used when the error is considered as a bug, but there is some code to + * recover from it and produce a valid Main data-base. + * - #BLO_read_assert_message should be used when the error is not considered as recoverable. + */ +#define BLO_read_assert_message(_check_expr, _ret_value, _bh, _bmain, _message) \ + if (_check_expr) { \ + BLO_read_invalidate_message((_bh), (_bmain), (_message)); \ + return _ret_value; \ + } \ + (void)0 + /** \} */ #define BLO_GROUP_MAX 32 diff --git a/source/blender/blenloader/intern/readblenentry.cc b/source/blender/blenloader/intern/readblenentry.cc index 6b59ef87cec..c7884b3ae75 100644 --- a/source/blender/blenloader/intern/readblenentry.cc +++ b/source/blender/blenloader/intern/readblenentry.cc @@ -385,6 +385,13 @@ void BLO_blendhandle_close(BlendHandle *bh) blo_filedata_free(fd); } +void BLO_read_invalidate_message(BlendHandle *bh, Main *bmain, const char *message) +{ + FileData *fd = reinterpret_cast(bh); + + blo_readfile_invalidate(fd, bmain, message); +} + /**********/ BlendFileData *BLO_read_from_file(const char *filepath, diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index 29730f7f10a..bbcc0d54c14 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -320,6 +320,10 @@ static void add_main_to_main(Main *mainvar, Main *from) ListBase *lbarray[INDEX_ID_MAX], *fromarray[INDEX_ID_MAX]; int a; + if (from->is_read_invalid) { + mainvar->is_read_invalid = true; + } + set_listbasepointers(mainvar, lbarray); a = set_listbasepointers(from, fromarray); while (a--) { @@ -340,6 +344,9 @@ void blo_join_main(ListBase *mainlist) } while ((tojoin = mainl->next)) { + if (tojoin->is_read_invalid) { + mainl->is_read_invalid = true; + } add_main_to_main(mainl, tojoin); BLI_remlink(mainlist, tojoin); BKE_main_free(tojoin); @@ -548,6 +555,21 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab return m; } +void blo_readfile_invalidate(FileData *fd, Main *bmain, const char *message) +{ + /* Tag given bmain, and 'root 'local' main one (in case given one is a library one) as invalid. + */ + bmain->is_read_invalid = true; + for (; bmain->prev != nullptr; bmain = bmain->prev) + ; + bmain->is_read_invalid = true; + + BLO_reportf_wrap(fd->reports, + RPT_ERROR, + "A critical error happened (the blend file is likely corrupted): %s", + message); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -3564,15 +3586,33 @@ static void do_versions(FileData *fd, Library *lib, Main *main) main->build_hash); } - blo_do_versions_pre250(fd, lib, main); - blo_do_versions_250(fd, lib, main); - blo_do_versions_260(fd, lib, main); - blo_do_versions_270(fd, lib, main); - blo_do_versions_280(fd, lib, main); - blo_do_versions_290(fd, lib, main); - blo_do_versions_300(fd, lib, main); - blo_do_versions_400(fd, lib, main); - blo_do_versions_cycles(fd, lib, main); + if (!main->is_read_invalid) { + blo_do_versions_pre250(fd, lib, main); + } + if (!main->is_read_invalid) { + blo_do_versions_250(fd, lib, main); + } + if (!main->is_read_invalid) { + blo_do_versions_260(fd, lib, main); + } + if (!main->is_read_invalid) { + blo_do_versions_270(fd, lib, main); + } + if (!main->is_read_invalid) { + blo_do_versions_280(fd, lib, main); + } + if (!main->is_read_invalid) { + blo_do_versions_290(fd, lib, main); + } + if (!main->is_read_invalid) { + blo_do_versions_300(fd, lib, main); + } + if (!main->is_read_invalid) { + blo_do_versions_400(fd, lib, main); + } + if (!main->is_read_invalid) { + blo_do_versions_cycles(fd, lib, main); + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */ @@ -3582,7 +3622,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) main->is_locked_for_linking = false; } -static void do_versions_after_linking(Main *main, ReportList *reports) +static void do_versions_after_linking(FileData *fd, Main *main) { CLOG_INFO(&LOG, 2, @@ -3595,13 +3635,27 @@ static void do_versions_after_linking(Main *main, ReportList *reports) /* Don't allow versioning to create new data-blocks. */ main->is_locked_for_linking = true; - do_versions_after_linking_250(main); - do_versions_after_linking_260(main); - do_versions_after_linking_270(main); - do_versions_after_linking_280(main, reports); - do_versions_after_linking_290(main, reports); - do_versions_after_linking_300(main, reports); - do_versions_after_linking_cycles(main); + if (!main->is_read_invalid) { + do_versions_after_linking_250(main); + } + if (!main->is_read_invalid) { + do_versions_after_linking_260(main); + } + if (!main->is_read_invalid) { + do_versions_after_linking_270(main); + } + if (!main->is_read_invalid) { + do_versions_after_linking_280(fd, main); + } + if (!main->is_read_invalid) { + do_versions_after_linking_290(fd, main); + } + if (!main->is_read_invalid) { + do_versions_after_linking_300(fd, main); + } + if (!main->is_read_invalid) { + do_versions_after_linking_cycles(main); + } main->is_locked_for_linking = false; } @@ -3810,6 +3864,9 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) static void blo_read_file_checks(Main *bmain) { #ifndef NDEBUG + BLI_assert(bmain->next == nullptr); + BLI_assert(!bmain->is_read_invalid); + LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) { LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { /* This pointer is deprecated and should always be nullptr. */ @@ -3914,6 +3971,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, false, nullptr); } } + + if (bfd->main->is_read_invalid) { + return bfd; + } } /* do before read_libraries, but skip undo case */ @@ -3927,6 +3988,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) } } + if (bfd->main->is_read_invalid) { + return bfd; + } + if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) { fd->reports->duration.libraries = PIL_check_seconds_timer(); read_libraries(fd, &mainlist); @@ -3953,7 +4018,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) blo_split_main(&mainlist, bfd->main); LISTBASE_FOREACH (Main *, mainvar, &mainlist) { BLI_assert(mainvar->versionfile != 0); - do_versions_after_linking(mainvar, fd->reports->reports); + do_versions_after_linking(fd, mainvar); } blo_join_main(&mainlist); @@ -3963,6 +4028,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) BKE_main_id_refcount_recompute(bfd->main, false); } + if (bfd->main->is_read_invalid) { + return bfd; + } + /* After all data has been read and versioned, uses LIB_TAG_NEW. Theoretically this should * not be calculated in the undo case, but it is currently needed even on undo to recalculate * a cache. */ @@ -4174,6 +4243,10 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old) { FileData *fd = static_cast(fdhandle); + if (mainvar->is_read_invalid) { + return; + } + BHead *bhead = find_bhead(fd, old); if (bhead == nullptr) { return; @@ -4432,7 +4505,16 @@ ID *BLO_library_link_named_part(Main *mainl, const LibraryLink_Params *params) { FileData *fd = (FileData *)(*bh); - return link_named_part(mainl, fd, idcode, name, params->flag); + + ID *ret_id = nullptr; + if (!mainl->is_read_invalid) { + ret_id = link_named_part(mainl, fd, idcode, name, params->flag); + } + + if (mainl->is_read_invalid) { + return nullptr; + } + return ret_id; } /* common routine to append/link something from a library */ @@ -4562,6 +4644,10 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag) mainvar = static_cast
((*fd)->mainlist->first); mainl = nullptr; /* blo_join_main free's mainl, can't use anymore */ + if (mainvar->is_read_invalid) { + return; + } + lib_link_all(*fd, mainvar); after_liblink_merged_bmain_process(mainvar); @@ -4582,9 +4668,13 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag) * or they will go again through do_versions - bad, very bad! */ split_main_newid(mainvar, main_newid); - do_versions_after_linking(main_newid, (*fd)->reports->reports); + do_versions_after_linking(*fd, main_newid); add_main_to_main(mainvar, main_newid); + + if (mainvar->is_read_invalid) { + return; + } } blo_join_main((*fd)->mainlist); @@ -4631,9 +4721,12 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag) void BLO_library_link_end(Main *mainl, BlendHandle **bh, const LibraryLink_Params *params) { - FileData *fd = (FileData *)(*bh); - library_link_end(mainl, &fd, params->flag); - *bh = (BlendHandle *)fd; + FileData *fd = reinterpret_cast(*bh); + + if (!mainl->is_read_invalid) { + library_link_end(mainl, &fd, params->flag); + *bh = reinterpret_cast(fd); + } } void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname) diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 027f1453581..c79dc0670d6 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -219,9 +219,9 @@ void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Mai void do_versions_after_linking_250(struct Main *bmain); void do_versions_after_linking_260(struct Main *bmain); void do_versions_after_linking_270(struct Main *bmain); -void do_versions_after_linking_280(struct Main *bmain, struct ReportList *reports); -void do_versions_after_linking_290(struct Main *bmain, struct ReportList *reports); -void do_versions_after_linking_300(struct Main *bmain, struct ReportList *reports); +void do_versions_after_linking_280(struct FileData *fd, struct Main *bmain); +void do_versions_after_linking_290(struct FileData *fd, struct Main *bmain); +void do_versions_after_linking_300(struct FileData *fd, struct Main *bmain); void do_versions_after_linking_cycles(struct Main *bmain); /** @@ -232,6 +232,10 @@ void do_versions_after_linking_cycles(struct Main *bmain); */ void *blo_read_get_new_globaldata_address(struct FileData *fd, const void *adr); +/* Mark the Main data as invalid (.blend file reading should be aborted ASAP, and the already read + * data should be discarded). Also add an error report to `fd` including given `message`. */ +void blo_readfile_invalidate(struct FileData *fd, struct Main *bmain, const char *message); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index ff860677663..df2d6cd7d2b 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1171,7 +1171,7 @@ static void do_version_fcurve_hide_viewport_fix(struct ID *UNUSED(id), fcu->rna_path = BLI_strdupn("hide_viewport", 13); } -void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) +void do_versions_after_linking_280(FileData *UNUSED(fd), Main *bmain) { bool use_collection_compat_28 = true; diff --git a/source/blender/blenloader/intern/versioning_290.cc b/source/blender/blenloader/intern/versioning_290.cc index b90e7529bbc..75e055d6e42 100644 --- a/source/blender/blenloader/intern/versioning_290.cc +++ b/source/blender/blenloader/intern/versioning_290.cc @@ -410,7 +410,7 @@ static void version_node_socket_duplicate(bNodeTree *ntree, } } -void do_versions_after_linking_290(Main *bmain, ReportList * /*reports*/) +void do_versions_after_linking_290(FileData * /*fd*/, Main *bmain) { if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) { /* Patch old grease pencil modifiers material filter. */ diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index 4a1c14bd430..e1b3053dbd8 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -919,7 +919,7 @@ static void version_geometry_nodes_primitive_uv_maps(bNodeTree &ntree) } } -void do_versions_after_linking_300(Main *bmain, ReportList * /*reports*/) +void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain) { if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) { /* Set zero user text objects to have a fake user. */ From 08bd6deb57a7e1298ee88752938570413a069586 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 1 Mar 2023 11:48:53 +0100 Subject: [PATCH 4/7] Fix #99836: Blender SEGV when open .blend file in blender. Use recent 'abort file reading' mechanism to simply not try to load such purposedly broken .blend files at all. --- source/blender/blenloader/intern/versioning_280.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index df2d6cd7d2b..4672491425e 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1171,7 +1171,7 @@ static void do_version_fcurve_hide_viewport_fix(struct ID *UNUSED(id), fcu->rna_path = BLI_strdupn("hide_viewport", 13); } -void do_versions_after_linking_280(FileData *UNUSED(fd), Main *bmain) +void do_versions_after_linking_280(FileData *fd, Main *bmain) { bool use_collection_compat_28 = true; @@ -1241,6 +1241,12 @@ void do_versions_after_linking_280(FileData *UNUSED(fd), Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) { for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + BLO_read_assert_message(screen->scene == NULL, + , + (BlendHandle *)fd, + bmain, + "No Screen data-block should ever have a NULL `scene` pointer"); + /* same render-layer as do_version_workspaces_after_lib_link will activate, * so same layer as BKE_view_layer_default_view would return */ ViewLayer *layer = screen->scene->view_layers.first; From 1f2823291a7aa52667f967408ba713e23bf22c20 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 1 Mar 2023 15:11:11 +0100 Subject: [PATCH 5/7] Cleanup: Add warning to ListBase's `BLI_remlink` regarding not cleared prev/next pointers. While this behavior can be useful in some cases, it can also create issues (as in one of own recent commits, 3e5ce23c99), since it implicetly keeps the removed linknode 'linked' to the listbase. At least warn about it in the documentation of `BLI_remlink`. --- source/blender/blenlib/BLI_listbase.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index f819413c7ce..60c46f2e520 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -136,6 +136,8 @@ void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1); void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1); /** * Removes \a vlink from \a listbase. Assumes it is linked into there! + * + * \warning Does _not_ clear the `prev`/`next` pointers of the removed `vlink`. */ void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1); /** From a23102528c7e8e46191f6713f09fd28b67ce8c12 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 1 Mar 2023 15:14:11 +0100 Subject: [PATCH 6/7] Fix failing test after own recent commit regarding Main freeing function. 3e5ce23c99 introduced a regression in case the freed Main was part of a list, and was supposed to be removed from it, since calling `BLI_remlink` does _not_ clear the `prev`/`next` pointers of the removed link. This commit also contains a few more tweaks to recent related b3f42d8e98 commit. Pull Request #105485 --- source/blender/blenloader/intern/readfile.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index bbcc0d54c14..891a9f81358 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -344,11 +344,9 @@ void blo_join_main(ListBase *mainlist) } while ((tojoin = mainl->next)) { - if (tojoin->is_read_invalid) { - mainl->is_read_invalid = true; - } add_main_to_main(mainl, tojoin); BLI_remlink(mainlist, tojoin); + tojoin->next = tojoin->prev = nullptr; BKE_main_free(tojoin); } } @@ -4673,7 +4671,7 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag) add_main_to_main(mainvar, main_newid); if (mainvar->is_read_invalid) { - return; + break; } } @@ -4681,6 +4679,11 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag) mainvar = static_cast
((*fd)->mainlist->first); MEM_freeN((*fd)->mainlist); + if (mainvar->is_read_invalid) { + BKE_main_free(main_newid); + return; + } + /* This does not take into account old, deprecated data, so we also have to do it after * `do_versions_after_linking()`. */ BKE_main_id_refcount_recompute(mainvar, false); From 83f28793c0b39e11192936f82a2bcaf0adeee3bd Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 6 Mar 2023 22:58:36 +0100 Subject: [PATCH 7/7] Fix missing data role in color management fallback This would show as warning in gtests. Does not affect normal operation as OpenColorIO should have a valid configuration file for Blender itself. --- intern/opencolorio/fallback_impl.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 8fc0ccd7918..9e5c107ab92 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -20,11 +20,13 @@ enum TransformType { TRANSFORM_SRGB_TO_LINEAR, TRANSFORM_SCALE, TRANSFORM_EXPONENT, + TRANSFORM_NONE, TRANSFORM_UNKNOWN, }; #define COLORSPACE_LINEAR ((OCIO_ConstColorSpaceRcPtr *)1) #define COLORSPACE_SRGB ((OCIO_ConstColorSpaceRcPtr *)2) +#define COLORSPACE_DATA ((OCIO_ConstColorSpaceRcPtr *)3) typedef struct OCIO_PackedImageDescription { float *data; @@ -165,6 +167,8 @@ OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcP return COLORSPACE_LINEAR; else if (strcmp(name, "sRGB") == 0) return COLORSPACE_SRGB; + else if (strcmp(name, "data") == 0) + return COLORSPACE_DATA; return NULL; } @@ -179,6 +183,9 @@ int FallbackImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, con else if (cs == COLORSPACE_SRGB) { return 1; } + else if (cs == COLORSPACE_DATA) { + return 2; + } return -1; } @@ -314,7 +321,10 @@ OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(OCIO_ConstCo OCIO_ConstColorSpaceRcPtr *cs_src = configGetColorSpace(config, srcName); OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName); FallbackTransform transform; - if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) { + if (cs_src == COLORSPACE_DATA || cs_dst == COLORSPACE_DATA) { + transform.type = TRANSFORM_NONE; + } + else if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) { transform.type = TRANSFORM_LINEAR_TO_SRGB; } else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) { @@ -433,6 +443,9 @@ const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) else if (cs == COLORSPACE_SRGB) { return "sRGB"; } + else if (cs == COLORSPACE_DATA) { + return "data"; + } return NULL; }