From 36228c4755782447f74296a7c8d9c430288b3bad Mon Sep 17 00:00:00 2001 From: weng haishi <74546450+wenghaishi@users.noreply.github.com> Date: Wed, 2 Sep 2026 03:39:12 +0800 Subject: [PATCH] fix: prevent heap corruption when repairing models with auto-backup (#15395) * fix: prevent heap corruption in model repair with auto-backup The CGAL model repair (fix_model_with_cgal_gui) runs on a worker thread that mutates the live ModelObject (split / delete_volume / set_mesh). Those mutators transitively call save_object_mesh(), which hands the object to the auto-backup manager. The manager clones and serializes the object on its own thread via an internal Model documented as "visit only in main thread". Running that path from the repair worker races the backup thread on the shared model, causing use-after-free / heap corruption -- EXC_BAD_ACCESS and libmalloc "corruption of free block" aborts, always with the "cgal_fix_model" worker on the stack inside add_object_mesh -> Model::add_object / delete_object. Wrap the repair in a SaveObjectGaurd so the backup manager ignores the object for the duration of the repair; a single backup is taken when the guard is released on the main thread after the worker joins. This mirrors existing batch-edit usage of SaveObjectGaurd (Model.hpp, GUI_ObjectList). Repro: repair a multi-part / splittable object with auto-backup enabled (Preferences > Backup); crashed within a few repairs on macOS arm64. * Update FixModelByCgal.cpp --------- Co-authored-by: Ian Bassi --- src/slic3r/Utils/FixModelByCgal.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/Utils/FixModelByCgal.cpp b/src/slic3r/Utils/FixModelByCgal.cpp index 8d196f7201..9d973844bb 100644 --- a/src/slic3r/Utils/FixModelByCgal.cpp +++ b/src/slic3r/Utils/FixModelByCgal.cpp @@ -12,6 +12,7 @@ #include "libslic3r/MeshBoolean.hpp" #include "libslic3r/Model.hpp" +#include "libslic3r/Format/bbs_3mf.hpp" #include "libslic3r/format.hpp" #include "libslic3r/Thread.hpp" #include "../GUI/I18N.hpp" @@ -69,6 +70,9 @@ public: // Returns false if fixing was canceled. fix_result contains error message if failed. bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::ProgressDialog &progress_dialog, const wxString &msg_header, std::string &fix_result, bool keep_painting) { + // Hold SaveObjectGaurd to prevent backup manager from racing concurrent mesh mutations (use-after-free). + SaveObjectGaurd backup_gaurd(model_object); + // Orca: Synchronization primitives for progress updates between worker thread and GUI. std::mutex mtx; std::condition_variable condition;