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 <ian.bassi@outlook.com>
This commit is contained in:
weng haishi
2026-09-02 03:39:12 +08:00
committed by GitHub
parent e108ddfd56
commit 36228c4755

View File

@@ -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;