Recursion depth equalled history length, so destroying or clearing a buffer with a few hundred thousand undo steps overflowed the stack. UndoSystem::clear() also freed only the first root branch, leaking the root's siblings; it now frees the whole forest. Audit finding M4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
32 lines
637 B
C++
32 lines
637 B
C++
// Undo logic is implemented in UndoSystem; this file only owns node lifetime.
|
|
#include "UndoTree.h"
|
|
|
|
#include <vector>
|
|
|
|
|
|
void
|
|
FreeUndoForest(UndoNode *first)
|
|
{
|
|
// Nodes form a first-child/next-sibling tree whose depth equals the
|
|
// length of the edit history, so walk it with an explicit stack.
|
|
std::vector<UndoNode *> stack;
|
|
if (first)
|
|
stack.push_back(first);
|
|
while (!stack.empty()) {
|
|
UndoNode *node = stack.back();
|
|
stack.pop_back();
|
|
if (node->child)
|
|
stack.push_back(node->child);
|
|
if (node->next)
|
|
stack.push_back(node->next);
|
|
delete node;
|
|
}
|
|
}
|
|
|
|
|
|
UndoTree::~UndoTree()
|
|
{
|
|
FreeUndoForest(root);
|
|
delete pending;
|
|
}
|