Skip to content

fix: zero-initialize WASM page buffers to prevent memory corruption#142

Open
sauyon wants to merge 2 commits into
coder:mainfrom
sauyon:sauyon/fix-mem-free
Open

fix: zero-initialize WASM page buffers to prevent memory corruption#142
sauyon wants to merge 2 commits into
coder:mainfrom
sauyon:sauyon/fix-mem-free

Conversation

@sauyon
Copy link
Copy Markdown

@sauyon sauyon commented Mar 22, 2026

PageList only zeroed page buffers in debug/safe builds, relying on the OS to guarantee zeroed memory in release builds. On WASM there is no OS guarantee — the allocator reuses freed memory as-is. This caused two bugs:

  1. Stale cell data from freed terminals appearing in newly created ones
  2. WASM memory corruption after freeing terminals that processed multi-codepoint grapheme clusters (flag emoji, skin tones, ZWJ sequences), crashing all subsequent terminal writes

The fix makes @Memset(page_buf, 0) unconditional on WASM in both initPages and createPageExt.

Includes two previously-failing regression tests. Should resolve #141.

sauyon and others added 2 commits March 22, 2026 06:33
…#141)

PageList only zeroed page buffers in debug/safe builds, relying on the
OS to guarantee zeroed memory in release builds. On WASM there is no OS
guarantee — the allocator reuses freed memory as-is. This caused two bugs:

1. Stale cell data from freed terminals appearing in newly created ones
2. WASM memory corruption after freeing terminals that processed
   multi-codepoint grapheme clusters (flag emoji, skin tones, ZWJ
   sequences), crashing all subsequent terminal writes

The fix makes @Memset(page_buf, 0) unconditional on WASM in both
initPages and createPageExt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
diegosouzapw added a commit to diegosouzapw/ghostty-web that referenced this pull request May 23, 2026
…tion

Ghostty allocates page buffers via the wasm allocator (which calls
wasm_alloc -> memory.grow). New memory pages on grow are zero on most
runtimes but the cell layout depends on this being EXPLICITLY true:
some cell fields are inspected before the first write, and a stray
non-zero byte can corrupt the screen state in ways that surface much
later (wrong colors, stuck cursor, dropped grapheme clusters).

Patches/ghostty-wasm-api.patch is updated so the underlying buffer
arrays are explicitly memset-to-zero at construction. Adds two TS-side
regression tests that exercise the corrupted-render shape.

Co-authored-by: Sauyon Lee <git@sjle.co>
Inspired-by: coder#142
diegosouzapw added a commit to diegosouzapw/ghostty-web that referenced this pull request May 23, 2026
…tion (#12)

Ghostty allocates page buffers via the wasm allocator (which calls
wasm_alloc -> memory.grow). New memory pages on grow are zero on most
runtimes but the cell layout depends on this being EXPLICITLY true:
some cell fields are inspected before the first write, and a stray
non-zero byte can corrupt the screen state in ways that surface much
later (wrong colors, stuck cursor, dropped grapheme clusters).

Patches/ghostty-wasm-api.patch is updated so the underlying buffer
arrays are explicitly memset-to-zero at construction. Adds two TS-side
regression tests that exercise the corrupted-render shape.


Inspired-by: coder#142

Co-authored-by: Sauyon Lee <git@sjle.co>
@diegosouzapw
Copy link
Copy Markdown

Hi @sauyon! 👋

Your work on this PR inspired a commit in my fork diegosouzapw/ghostty-web.
I ported the WASM page buffer zero-initialization fix and added you as co-author in the corresponding commit — thank you for the contribution!

I'm working on OmniRoute, a project that provides free access to LLM models, and I'm planning to use ghostty-web as the terminal component there. Your work is part of what makes that possible. 🙏

Feel free to check it out — contributions and feedback are very welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WASM memory corruption after freeing terminal that processed multi-codepoint grapheme clusters

2 participants