Repository navigation
Commit c54051e
authored
fix(native): reject typed arrays other than Uint8Array in feed (#49)
## Why
The goal is to handle the items still open after the #12 follow-ups and land each on main as its own PR. This one fixes the raw addon's `feed`.
`native/README.md` says the addon's `feed` throws `TypeError("feed typed array must be Uint8Array")` for a typed array that is not a `Uint8Array`. It throws `TypeError("feed data must be a string, Buffer, or Uint8Array")` for any other value. The typed-array check in `TerminalWrap::Feed` never ran. The `IsBuffer()` branch before it is true for every ArrayBufferView in Node, because `napi_is_buffer` accepts any view. So a `Uint16Array` or `Float32Array` was written as raw bytes, and a `DataView` failed with `Error: Invalid argument`.
## What changed
- `native/terminal.cc`: I deleted the `IsBuffer()` branch in `TerminalWrap::Feed`. A Buffer is a `Uint8Array`, so the typed-array branch now handles it.
- `test/terminal.test.ts`: new raw-addon tests. `Uint16Array`, `Float32Array` and `Uint8ClampedArray` throw the typed-array `TypeError`. A `DataView` throws the generic `TypeError`. `Buffer`, `Uint8Array` and a Buffer slice with a byte offset still write "AB".
- `native/README.md`: the Verification section no longer lists the typed-array errors as untested.
## Scope
Only the raw addon's `feed` argument check changes. `src/index.ts` already rejects these values before native code runs, so the public API keeps its behavior.
## Blast Radius
Code that calls the raw addon directly with a non-`Uint8Array` typed array or a `DataView` now gets a `TypeError`. Before, it got raw bytes written or `Error: Invalid argument`. Package users who go through `createTerminal` from the package see no change.
## Verification
The test commit (1727d01) fails on the unfixed code:
```
× rejects a Uint16Array in the addon feed with a TypeError 5ms
× rejects a Float32Array in the addon feed with a TypeError 1ms
× rejects a Uint8ClampedArray in the addon feed with a TypeError 0ms
× rejects a DataView in the addon feed with a TypeError 1ms
✓ writes a Buffer in the addon feed 0ms
✓ writes a Uint8Array in the addon feed 0ms
✓ writes a Buffer slice with a byte offset in the addon feed 0ms
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 4 ⎯⎯⎯⎯⎯⎯⎯
FAIL test/terminal.test.ts > GhosttyVtTerminal > rejects a Uint16Array in the addon feed with a TypeError
FAIL test/terminal.test.ts > GhosttyVtTerminal > rejects a Float32Array in the addon feed with a TypeError
FAIL test/terminal.test.ts > GhosttyVtTerminal > rejects a Uint8ClampedArray in the addon feed with a TypeError
AssertionError: expected undefined to be an instance of TypeError
FAIL test/terminal.test.ts > GhosttyVtTerminal > rejects a DataView in the addon feed with a TypeError
AssertionError: expected Error: Invalid argument to be an instance of TypeError
Tests 4 failed | 3 passed | 33 skipped (40)
```
With the fix (fabeeaf):
```
✓ test/terminal.test.ts (40 tests | 33 skipped) 5ms
Tests 7 passed | 33 skipped (40)
```
Repro script (`node repro-feed.mjs` after `npm run build`), after the fix. On main the raw `Uint16Array`, `Float32Array` and `Uint8ClampedArray` cases returned "ok", and `DataView` threw `Error: Invalid argument`.
```
raw feed(Buffer 'AB'): ok, text "AB"
raw feed(Uint8Array [65,66]): ok, text "AB"
raw feed(Uint16Array [0x4241]): TypeError: feed typed array must be Uint8Array
raw feed(Float32Array [1]): TypeError: feed typed array must be Uint8Array
raw feed(Uint8ClampedArray [65,66]): TypeError: feed typed array must be Uint8Array
raw feed(DataView(2 bytes 'AB')): TypeError: feed data must be a string, Buffer, or Uint8Array
public feed(Buffer 'AB'): ok, text "AB"
public feed(Uint8Array [65,66]): ok, text "AB"
public feed(Uint16Array [0x4241]): TypeError: feed data must be a string, Buffer, or Uint8Array
public feed(Float32Array [1]): TypeError: feed data must be a string, Buffer, or Uint8Array
public feed(Uint8ClampedArray [65,66]): TypeError: feed data must be a string, Buffer, or Uint8Array
public feed(DataView(2 bytes 'AB')): TypeError: feed data must be a string, Buffer, or Uint8Array
```
Gates, each exit 0:
1. `npm ci && LIBGHOSTTY_VT_PREFIX=<ReleaseFast> npm run build:native && npm run build && npm run verify`: 84 tests passed.
2. The same with the ReleaseSafe prefix: 84 tests passed.
3. UBSan: `rm -rf dist && LIBGHOSTTY_VT_PREFIX=<ReleaseFast> CXXFLAGS="-fsanitize=undefined,float-cast-overflow -fno-sanitize-recover=all" LDFLAGS="-fsanitize=undefined,float-cast-overflow" npm run build:native && npm test && npm run smoke`: 84 tests passed, smoke passed.
4. `.agents/skills/verify-native-lifecycle/run.sh`: `OK: every result matches EXPECT.`
---
_Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `medium`_1 parent 9d5a707 commit c54051e
3 files changed
Lines changed: 34 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
79 | | - | |
| 79 | + | |
80 | 80 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
307 | 307 | | |
308 | 308 | | |
309 | 309 | | |
310 | | - | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | 310 | | |
315 | 311 | | |
316 | 312 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
562 | 562 | | |
563 | 563 | | |
564 | 564 | | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
565 | 598 | | |
566 | 599 | | |
567 | 600 | | |
| |||
0 commit comments