Skip to content

fix(tui,coding-agent): survive lone surrogates in table cells and terminate the WebP EXIF scan - #2033

Open
snimu wants to merge 4 commits into
mainfrom
fix/tui-media-defects
Open

fix(tui,coding-agent): survive lone surrogates in table cells and terminate the WebP EXIF scan#2033
snimu wants to merge 4 commits into
mainfrom
fix/tui-media-defects

Conversation

@snimu

@snimu snimu commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Two rendering-input crashes:

  • Lone UTF-16 surrogates no longer crash table rendering. Table cell selection markers encode cell content with encodeURIComponent, which throws URIError: URI malformed on a lone surrogate (e.g. text split mid-astral-character at a cell boundary) — taking down the whole TUI render. Content is now sanitized with toWellFormed() (available on every supported runtime, Node ≥ 20) so the surrogate becomes U+FFFD and the marker round-trips. Fixes the defect reported in discussion [Bug] TUI crashes with URIError in cellMarker when rendering markdown tables #2001.
  • A corrupt or crafted WebP can no longer hang the process. The RIFF chunk scan read the 32-bit chunk size with signed arithmetic; a size with the high bit set went negative and walked the scan offset backward, spinning the EXIF-orientation scan forever on the main thread. Chunk sizes — and the little-endian TIFF read32, which had the same signedness bug — are now read unsigned, guaranteeing forward progress. Fixes the defect reported in discussion A malformed WebP chunk size hangs the agent forever: RIFF size decoded with a signed shift #1554.

Validation

  • two pins, each verified fail-unfixed: a lone-surrogate cell round-trips (pre-fix: URIError), and a WebP whose chunk size re-visits its own offset terminates (pre-fix: infinite loop — the unfixed run had to be killed after 20s)
  • packages/tui vitest include list gains the new selection-metadata suite (the package runs an explicit whitelist)
  • root npm run check passes via the pre-commit hook

LOC

Total src: +6/−3 (net +3); tests: +35/−0 (net +35).
Src +7/−3 (both point fixes, no new mechanism). Tests +34, changelog 2 fragments, 1 vitest include line.

Linear: RES-1266 https://linear.app/primeintellect/issue/RES-1266


Note

Low Risk
Targeted defensive fixes in rendering metadata and binary parsing; behavior only changes for previously crashing or hanging malformed inputs.

Overview
Fixes two input-handling failures in the TUI and image EXIF path.

Table selection markers no longer throw when cell content includes a lone UTF-16 surrogate. cellMarker runs content through toWellFormed() before encodeURIComponent, so malformed sequences become U+FFFD and markers still round-trip through extraction.

WebP EXIF orientation no longer hangs on corrupt or crafted files. Chunk sizes and little-endian TIFF read32 values are coerced with >>> 0 so high-bit sizes are not treated as negative offsets that move the RIFF scan backward in a loop; the scan exits and orientation falls back to default instead.

Reviewed by Cursor Bugbot for commit a3d1139. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix WebP EXIF scan termination and lone-surrogate handling in TUI selection markers

  • Forces unsigned 32-bit interpretation of RIFF chunk sizes and TIFF offsets in exif-orientation.ts, so a high-bit size no longer moves the scan backward and loops forever.
  • Runs well-formed-string conversion before URI-encoding cell content in selection-metadata.ts, replacing lone UTF-16 surrogates with U+FFFD so encoding does not throw.
  • Adds regression tests for both fixes in exif-orientation.test.ts and selection-metadata.test.ts.
  • Risk: readOrientationFromTiff and findWebpTiffOffset now treat offsets/sizes with the high bit set as large unsigned values rather than negative; malformed inputs that previously errored early via negative-offset paths will instead be caught by existing bounds checks.

Macroscope summarized a3d1139.

…minate the WebP EXIF scan

encodeURIComponent throws URIError on a lone UTF-16 surrogate, so table cell markers sanitize content with toWellFormed before encoding. The WebP RIFF scan read chunk sizes with signed 32-bit arithmetic; a high-bit size walked the scan backward forever, hanging the process on a corrupt or crafted image. Chunk sizes (and the little-endian TIFF read32) are now unsigned.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4410455. Configure here.

Comment thread packages/tui/test/selection-metadata.test.ts Outdated
…test runner

packages/tui tests run via node --test, not vitest; the lone-surrogate pin now uses node:test and the vitest include-list change is reverted.
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.

1 participant