Fix: Leak of initialized but not pushed undo step

In some cases, sculpt code currently creates undo steps that are stored
in `step_init` in the undo stack, but then skips actually pushing them.
That can happen when an operator is cancelled (like the transform
operator in #123172) or because pushes in "nested operator calls"
are currently explicitly disabled. That happens when calling the brush
operator from a script.

It turns out the undo code never freed the `step_init`, probably because
it assumed it would be pushed to be part of the stack afterwards.

Personally I'm not convinced that separating undo step creation into
two stages with `step_encode_init` and `step_encode` is a great design
or a necessary one, but I'm trying not to get into that deeper right now.

Fixes #123172

Pull Request: https://projects.blender.org/blender/blender/pulls/123331
This commit is contained in:
Hans Goudey
2024-06-24 21:38:21 +02:00
committed by Hans Goudey
parent 68b85d1e68
commit 1b80125a67

View File

@@ -281,6 +281,10 @@ void BKE_undosys_stack_clear(UndoStack *ustack)
us_prev = us->prev;
undosys_step_free_and_unlink(ustack, us);
}
if (UndoStep *us = ustack->step_init) {
undosys_step_free_and_unlink(ustack, us);
ustack->step_init = nullptr;
}
BLI_listbase_clear(&ustack->steps);
ustack->step_active = nullptr;
}
@@ -472,6 +476,10 @@ UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack,
if (ut->step_encode_init) {
undosys_stack_validate(ustack, false);
if (UndoStep *us = ustack->step_init) {
undosys_step_free_and_unlink(ustack, us);
ustack->step_init = nullptr;
}
if (ustack->step_active) {
undosys_stack_clear_all_last(ustack, ustack->step_active->next);
}