[PR #430] [CLOSED] fix(core): fix memory leaks in Zig unicode encoding and grapheme pool #1316

Closed
opened 2026-03-14 09:30:06 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/anomalyco/opentui/pull/430
Author: @edlsh
Created: 12/19/2025
Status: Closed

Base: mainHead: fix/zig-critical-bugs


📝 Commits (4)

  • c3b22bd fix(core): wrap kitty graphics query in tmux DCS passthrough
  • 933f322 fix(core): defer kitty graphics query until detection
  • 4a9aa5e move test script to core/dev
  • 8f11e06 fix(core): fix memory leaks in Zig unicode encoding and grapheme pool

📊 Changes

8 files changed (+176 additions, -12 deletions)

View changed files

packages/core/dev/test-tmux-graphics-334.sh (+68 -0)
📝 packages/core/docs/env-vars.md (+14 -0)
📝 packages/core/src/zig.ts (+6 -0)
📝 packages/core/src/zig/ansi.zig (+2 -0)
📝 packages/core/src/zig/grapheme.zig (+4 -0)
📝 packages/core/src/zig/lib.zig (+26 -1)
📝 packages/core/src/zig/renderer.zig (+9 -0)
📝 packages/core/src/zig/terminal.zig (+47 -11)

📄 Description

Summary

Fixes critical memory leaks in the Zig native code for unicode encoding and grapheme pool operations.

Changes

1. Fix errdefer that never runs in encodeUnicode (lib.zig)

Problem: The function returns bool, but errdefer only triggers on error union returns. All failure paths used catch return false, which is a normal return—not an error return—so cleanup never executed.

Fix: Replace errdefer with defer + success flag pattern:

  • Added var success = false; at start
  • Changed errdefer to defer { if (!success) { ... } }
  • Set success = true; before final return true;

2. Fix grapheme leak on realloc failure (lib.zig)

Problem: After pool.alloc() + pool.incref(), if realloc fails, the newly allocated grapheme wasn't tracked yet in the result array, so it would leak.

Fix: Track pending grapheme with var pending_gid: ?u32 = null;:

  • Set pending_gid = gid immediately after allocation
  • Clear pending_gid = null after successfully stored in result array
  • Cleanup decrefs pending_gid if set

3. Add bounds checks in GraphemePool (grapheme.zig)

Problem: incref, decref, get, and getRefcount didn't validate class_id before array access.

Fix: Added if (class_id >= MAX_CLASSES) return GraphemePoolError.InvalidId; to all four methods.

Testing

  • bun run build passes (all 6 platform binaries)
  • bun run test:native passes (1241/1242 tests, 1 skipped)

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/anomalyco/opentui/pull/430 **Author:** [@edlsh](https://github.com/edlsh) **Created:** 12/19/2025 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/zig-critical-bugs` --- ### 📝 Commits (4) - [`c3b22bd`](https://github.com/anomalyco/opentui/commit/c3b22bd1a3e1db288a31a142c5eadd726cb2d62e) fix(core): wrap kitty graphics query in tmux DCS passthrough - [`933f322`](https://github.com/anomalyco/opentui/commit/933f3227c8a33940a53f387250de1ae7e9ee7ff2) fix(core): defer kitty graphics query until detection - [`4a9aa5e`](https://github.com/anomalyco/opentui/commit/4a9aa5e910d2924986dd3ebbf6fa27adc2cd1108) move test script to core/dev - [`8f11e06`](https://github.com/anomalyco/opentui/commit/8f11e06d326bc57194ecb04d7c4210b353831450) fix(core): fix memory leaks in Zig unicode encoding and grapheme pool ### 📊 Changes **8 files changed** (+176 additions, -12 deletions) <details> <summary>View changed files</summary> ➕ `packages/core/dev/test-tmux-graphics-334.sh` (+68 -0) 📝 `packages/core/docs/env-vars.md` (+14 -0) 📝 `packages/core/src/zig.ts` (+6 -0) 📝 `packages/core/src/zig/ansi.zig` (+2 -0) 📝 `packages/core/src/zig/grapheme.zig` (+4 -0) 📝 `packages/core/src/zig/lib.zig` (+26 -1) 📝 `packages/core/src/zig/renderer.zig` (+9 -0) 📝 `packages/core/src/zig/terminal.zig` (+47 -11) </details> ### 📄 Description ## Summary Fixes critical memory leaks in the Zig native code for unicode encoding and grapheme pool operations. ## Changes ### 1. Fix `errdefer` that never runs in `encodeUnicode` (lib.zig) **Problem**: The function returns `bool`, but `errdefer` only triggers on error union returns. All failure paths used `catch return false`, which is a normal return—not an error return—so cleanup never executed. **Fix**: Replace `errdefer` with `defer` + success flag pattern: - Added `var success = false;` at start - Changed `errdefer` to `defer { if (!success) { ... } }` - Set `success = true;` before final `return true;` ### 2. Fix grapheme leak on realloc failure (lib.zig) **Problem**: After `pool.alloc()` + `pool.incref()`, if `realloc` fails, the newly allocated grapheme wasn't tracked yet in the result array, so it would leak. **Fix**: Track pending grapheme with `var pending_gid: ?u32 = null;`: - Set `pending_gid = gid` immediately after allocation - Clear `pending_gid = null` after successfully stored in result array - Cleanup decrefs `pending_gid` if set ### 3. Add bounds checks in GraphemePool (grapheme.zig) **Problem**: `incref`, `decref`, `get`, and `getRefcount` didn't validate `class_id` before array access. **Fix**: Added `if (class_id >= MAX_CLASSES) return GraphemePoolError.InvalidId;` to all four methods. ## Testing - [x] `bun run build` passes (all 6 platform binaries) - [x] `bun run test:native` passes (1241/1242 tests, 1 skipped) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-14 09:30:06 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/opentui#1316
No description provided.