Editor: share the SwapManager along with shared buffers

A secondary GUI window shared the primary's buffer vector but attached
buffers through its own SwapManager. Closing the window destroyed that
manager while buffers still held its recorders, so the next edit called
into freed memory; Rehome through the wrong manager also dropped
journaling for the primary's buffers.

Audit finding M3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
Claude
2026-09-24 09:16:04 -07:00
committed by Kyle Isom
parent fc9f83966c
commit 8cac2e9af8
4 changed files with 56 additions and 28 deletions
+7 -2
View File
@@ -607,9 +607,13 @@ public:
// Share another editor's buffer list. When set, this editor operates on
// the provided vector instead of its own. Pass nullptr to detach.
void SetSharedBuffers(std::vector<Buffer> *shared)
// Buffers hold recorders owned by the SwapManager that attached them, so
// editors sharing buffers must also share that manager (shared_swap);
// otherwise closing one window destroys recorders the other still uses.
void SetSharedBuffers(std::vector<Buffer> *shared, kte::SwapManager *shared_swap = nullptr)
{
shared_buffers_ = shared;
shared_swap_ = shared ? shared_swap : nullptr;
curbuf_ = 0;
}
@@ -617,7 +621,7 @@ public:
// Swap manager access (for advanced integrations/tests)
[[nodiscard]] kte::SwapManager *Swap()
{
return swap_.get();
return shared_swap_ ? shared_swap_ : swap_.get();
}
@@ -667,6 +671,7 @@ private:
// Swap journaling manager (lifetime = editor)
std::unique_ptr<kte::SwapManager> swap_;
kte::SwapManager *shared_swap_ = nullptr; // set with shared_buffers_; not owned
// Kill ring (Emacs-like)
std::vector<std::string> kill_ring_;