Commit Graph

9837 Commits

Author SHA1 Message Date
Mitchell Hashimoto
f948d42076 termio: replace SegmentedPool with std.MemoryPool (#13659)
The purpose of SegmentedPool was pointer-stable values for the pty write
path, and the std.MemoryPool provides that.

SegmentedPool is actually so old it predates a stdlib memory pool! Just
noting why I did it in the first place. I also wrote it when I was
pretty fucking bad at Zig, so I'm shocked its lasted this long.

The write path is hot , so the replacement was benchmarked against the
old SegmentedPool plus a rewrite simple Pool I did before realizing...
wait... why not just a MemoryPool. Benchmarked using the real 240-byte
xev write request.

```
  workload                    old                     std.MemoryPool
  depth-1 (keystroke echo)    3.93 ns/op              0.96 ns/op
  burst (1MiB paste, d=256)   4.27 ns/op              1.00 ns/op
  cold growth (32 -> 16k)     4.54 ns/op              6.48 ns/op
  malloc create/destroy       15.9 ns/op              (baseline)
```

Cold growth is slower but this is only a cost when the pool grows.

Note this also gets rid of the preallocation, which didn't show any
measurable performance benefit at all. This has the benefit of shrinking
our ThreadData by ~10KB.

This was motivated by #13655
2026-08-05 21:06:16 -07:00
Mitchell Hashimoto
e0ef934f73 termio: replace SegmentedPool with std.MemoryPool
The purpose of SegmentedPool was pointer-stable values for the pty write
path, and the std.MemoryPool provides that. 

SegmentedPool is actually so old it predates a stdlib memory pool!
Just noting why I did it in the first place. I also wrote it when I was
pretty fucking bad at Zig, so I'm shocked its lasted this long.

The write path is hot , so the replacement was benchmarked against the old 
SegmentedPool plus a rewrite simple Pool I did before realizing...
wait... why not just a MemoryPool. Benchmarked using the real 240-byte xev
write request.

  workload                    old                     std.MemoryPool
  depth-1 (keystroke echo)    3.93 ns/op              0.96 ns/op
  burst (1MiB paste, d=256)   4.27 ns/op              1.00 ns/op
  cold growth (32 -> 16k)     4.54 ns/op              6.48 ns/op
  malloc create/destroy       15.9 ns/op              (baseline)

Cold growth is slower but this is only a cost when the pool grows.

Note this also gets rid of the preallocation, which didn't show any
measurable performance benefit at all. This has the benefit of shrinking
our ThreadData by ~10KB.
2026-08-05 20:58:33 -07:00
Mitchell Hashimoto
63da4e84d4 lib: remove backported cutPrefix implementation (#13658)
We can use std.mem.cutPrefix directly now that we're on Zig 0.16.
2026-08-05 20:47:26 -07:00
Jon Parise
1d6bc68298 lib: remove cutPrefix implementation
We can use std.mem.cutPrefix directly now that we're on Zig 0.16.
2026-08-05 23:07:43 -04:00
Jeffrey C. Ollie
f0f3f4d8d8 GTK: move audio bell processing to the application
This fixes #13647 by using at most one GStreamer thread per application.
This was previously addressed in #12815 which used at most one GStreamer
thread per surface. Originally discussed in #12808.
2026-08-05 20:10:53 -05:00
Mitchell Hashimoto
8eecb8fdbf terminal: release Kitty placement pins on eviction (#13656)
Image eviction removed associated placements from storage without
deinitializing them. Pin-backed placements therefore remained registered
with the screen after eviction, allowing graphics-heavy output to
accumulate stale tracked pins.

Pass the owning screen through image insertion and eviction, and
deinitialize each placement before removing it. Cover both the released
pin and a retained image's live pin in the eviction regression test.
2026-08-05 16:31:23 -07:00
Mitchell Hashimoto
ea21a2f141 core: avoid allocating for pwd change actions (#13654)
Surface.handleMessage allocated a null-terminated copy for every working
directory update. OSC 7 values fit within the parser's 2 KiB fixed
buffer, so use stack-fallback storage sized for that bound and its
terminator.

The message type does not enforce the OSC bound, so an oversized future
producer still falls back to the heap. performAction already borrows the
value only for the duration of the call, preserving its existing
lifetime.
2026-08-05 16:28:50 -07:00
Amp
b5e86a4284 terminal/kitty: release evicted placement pins
Image eviction removed associated placements from storage without
deinitializing them. Pin-backed placements therefore remained registered
with the screen after eviction, allowing graphics-heavy output to
accumulate stale tracked pins.

Pass the owning screen through image insertion and eviction, and
deinitialize each placement before removing it. Cover both the released
pin and a retained image's live pin in the eviction regression test.

Co-authored-by: Tim Culverhouse <tfc@ampcode.com>
2026-08-05 23:10:17 +00:00
Jon Parise
f1d225020a core: avoid allocating for small pwd change actions
Surface.handleMessage allocated a null-terminated copy for every working
directory update.

Use a small 256-byte stack-fallback buffer for common working directory
lengths without adding significant pressure to this deep call stack. Longer
paths retain the existing heap behavior, and performAction continues to borrow
the value only for the duration of the call.
2026-08-05 18:31:27 -04:00
Mitchell Hashimoto
9cb2147641 terminal/kitty: evict without scratch allocation (#13627)
Track each image's placement count in its existing metadata. This lets
us use constant-time usage checks (rather than scans) during eviction.

Select the best candidate directly from storage on each eviction,
preserving the existing priority order: unused status, transient hint,
generation, then ID.

Since eviction no longer allocates, it can't fail, so callers no longer
need to handle out-of-memory conditions.
2026-08-05 15:28:41 -07:00
Mitchell Hashimoto
090d161b28 terminal: report overline in DECRQSS SGR response (#13653)
#11638

Report SGR 53 when the active cursor style has overline enabled.
2026-08-05 15:20:19 -07:00
Mitchell Hashimoto
f973bd53ba terminal: report overline in DECRQSS SGR response
#11638

Report SGR 53 when the active cursor style has overline enabled.
2026-08-05 15:09:01 -07:00
Mitchell Hashimoto
8524cb593c terminal/kitty: fix point deletion calculations (d=p, d=c)
Fix d=p and d=c point deletion so only placements intersecting the
target cell are removed. 

Previously, placements spanning multiple rows could be deleted from
columns outside the target because the page-order comparison flattened
row and column coordinates.

Check the rectangle's column independently and use page order only for
its row span, matching Kitty's implementation:
https://github.com/kovidgoyal/kitty/blob/master/kitty/graphics.c

NOTE: I did not look at Kitty's source prior to fixing this. I only
referenced it after the fix to verify that the behavior matches.

Spec:
https://sw.kovidgoyal.net/kitty/graphics-protocol/#deleting-images
2026-08-05 15:00:53 -07:00
Mitchell Hashimoto
9ed61428da libghostty-vt: spacer-tail handling needs to respect slow runtime safety (#13651)
Debug libghostty-vt dependencies embedded in ReleaseFast or ReleaseSmall
binaries no longer panic when narrow text overwrites the tail of a wide
glyph.

Replace the root module's std.debug.runtime_safety gate with
build_options.slow_runtime_safety so mixed optimization modes use the
dependency's safety configuration consistently.
2026-08-05 14:49:10 -07:00
Mitchell Hashimoto
1aeca6705e terminal: color reset should set override to null, not default (#13650)
#12755

Reset previously copied the active default into the override. This is
wrong, a reset should unset the override and defer back to the default.

Reset foreground, background, and cursor colors now resolve through the
current default while explicit OSC overrides remain unchanged across
configuration updates.

Set a configured background in the OSC 11 regression, assert OSC 111
clears its override, then change the default to verify the reset color
follows it.
2026-08-05 14:48:40 -07:00
Mitchell Hashimoto
78dec345b2 terminfo: advertise overline support (#13649)
#12885

Ghostty already implements SGR 53 and 55, but its terminfo description
does not expose the corresponding Smol and Rmol capabilities. Add both
entries so the advertised capabilities match the renderer. Tmux uses
this to gate overline.
2026-08-05 14:48:27 -07:00
Mitchell Hashimoto
0dcb411681 fix screen action fd leak from tempdir (#13644)
Fixes #13219

Screen file actions intentionally retain their temporary directory so
the generated path remains valid after dispatch. The directory and
parent handles were retained with it, while TempDir.deinit also left the
parent handle open.

Each successful action leaked two descriptors. Repeated screen,
scrollback, or selection writes could exhaust the process descriptor
limit and prevent new PTYs, tabs, and windows from opening.

Give TempDir an exhaustive close mode that either deletes or retains its
contents while always releasing both handles. Defer screen-file cleanup,
retaining only after successful dispatch, and cover both lifecycle paths
with descriptor tests.
2026-08-05 14:47:34 -07:00
Mitchell Hashimoto
5033ea83d8 terminal: preserve cursor when formatting tabstops (#13643)
Fixes #13269

Move VT tabstop serialization ahead of screen formatting so
cursor-moving CHA and HTS sequences run before screen state is restored.

Tabstop-enabled snapshots previously finished at the final configured
tabstop instead of the serialized cursor position. Replaying a snapshot
could resume input in the wrong column.

Keep tabstop bytes in their original pin-map accounting and extend the
round-trip test to verify tabstops, cursor position, and map length.
2026-08-05 14:47:25 -07:00
Mitchell Hashimoto
b60970ce25 macos: handle missing CoreText display names (#13642)
Fixes https://github.com/ghostty-org/ghostty/discussions/13262

CTFontCopyDisplayName can return null.
2026-08-05 14:38:31 -07:00
Mitchell Hashimoto
71c2d68eb4 macos: tolerate display link creation failures (#13639)
Fixes #13293

Treat Core Video display link creation as optional when macOS has no
active displays. The previous error path reported every creation failure
as out of memory and aborted renderer initialization.

Tabs created while the session is locked now initialize normally and
fall back to event-driven rendering without vsync.
2026-08-05 14:38:15 -07:00
Mitchell Hashimoto
b30387a80f renderer/metal: clear callback before layer release (#13641)
Fixes https://github.com/ghostty-org/ghostty/discussions/13242

Clear the IOSurfaceLayer display callback when releasing the wrapper.
The host view can retain the backing layer beyond renderer teardown.
This prevents a later Core Animation display pass from invoking the
callback with a freed renderer context.

This doesn't happen the way Ghostty GUI uses our renderer, but it is
possible for folks using ghostty-internal and its straightforward and
easy for us to fix it.
2026-08-05 14:35:31 -07:00
Mitchell Hashimoto
e20564791e libghostty-vt: spacer-tail handling needs to respect slow runtime safety
Debug libghostty-vt dependencies embedded in ReleaseFast or ReleaseSmall
binaries no longer panic when narrow text overwrites the tail of a wide
glyph.

Replace the root module's std.debug.runtime_safety gate with
build_options.slow_runtime_safety so mixed optimization modes use the
dependency's safety configuration consistently.
2026-08-05 14:34:55 -07:00
Mitchell Hashimoto
7cd2f65f5c terminal: color reset should set override to null, not default
#12755

Reset previously copied the active default into the override. This is
wrong, a reset should unset the override and defer back to the default.

Reset foreground, background, and cursor colors now resolve through the
current default while explicit OSC overrides remain unchanged across
configuration updates.

Set a configured background in the OSC 11 regression, assert OSC 111
clears its override, then change the default to verify the reset color
follows it.
2026-08-05 14:30:21 -07:00
Mitchell Hashimoto
bb1f5908f8 terminfo: advertise overline support
#12885

Ghostty already implements SGR 53 and 55, but its terminfo description
does not expose the corresponding Smol and Rmol capabilities. Add both
entries so the advertised capabilities match the renderer.
2026-08-05 14:28:39 -07:00
Mitchell Hashimoto
2b32b5b75c core: close retained temp directory handles
Fixes #13219

Screen file actions intentionally retain their temporary directory so
the generated path remains valid after dispatch. The directory and
parent handles were retained with it, while TempDir.deinit also left the
parent handle open.

Each successful action leaked two descriptors. Repeated screen,
scrollback, or selection writes could exhaust the process descriptor
limit and prevent new PTYs, tabs, and windows from opening.

Give TempDir an exhaustive close mode that either deletes or retains its
contents while always releasing both handles. Defer screen-file cleanup,
retaining only after successful dispatch, and cover both lifecycle paths
with descriptor tests.
2026-08-05 14:06:51 -07:00
Mitchell Hashimoto
7a9c369cf5 terminal: preserve cursor when formatting tabstops
Fixes #13269

Move VT tabstop serialization ahead of screen formatting so cursor-moving
CHA and HTS sequences run before screen state is restored.

Tabstop-enabled snapshots previously finished at the final configured
tabstop instead of the serialized cursor position. Replaying a snapshot
could resume input in the wrong column.

Keep tabstop bytes in their original pin-map accounting and extend the
round-trip test to verify tabstops, cursor position, and map length.
2026-08-05 14:06:11 -07:00
Mitchell Hashimoto
d166c05edd font: handle missing CoreText display names
CTFontCopyDisplayName can return null.
2026-08-05 13:56:32 -07:00
Jeffrey C. Ollie
15ac61db16 gtk: implement drag-to-move for splits (#10423)
One major todo is moving splits across different split trees (i.e.
moving across tabs and windows), but that would involve a lot more
logic. This MVP version works for now.

Video demo (somehow the encode quality is terrible - I'll fix this
later):


https://github.com/user-attachments/assets/a5029451-9641-4680-bff6-38f52ebded4b


GTK version of #10090

Closes #10224
2026-08-05 15:54:52 -05:00
Mitchell Hashimoto
a177ba90af macos: tolerate display link creation failures
Fixes #13293

Treat Core Video display link creation as optional when macOS has no
active displays. The previous error path reported every creation
failure as out of memory and aborted renderer initialization.

This also resyncs the display link on any display change so when
a display becomes available it re-adds itself.

Tabs created while the session is locked now initialize normally and
fall back to event-driven rendering without vsync.
2026-08-05 13:54:47 -07:00
Mitchell Hashimoto
4b4a5b2411 renderer/metal: clear callback before layer release
Clear the IOSurfaceLayer display callback when releasing the wrapper.
The host view can retain the backing layer beyond renderer teardown.
This prevents a later Core Animation display pass from invoking the
callback with a freed renderer context.
2026-08-05 13:52:36 -07:00
Mitchell Hashimoto
168c7b9467 core: fix encoded key request cleanup (#13635)
Encoded key requests are owned by the caller until they are added to a
key sequence or queued for IO. The child_exited path and failed queue
append returned without freeing the allocated request.

The existing errdefer was also too broad: after queueIo took ownership,
a later setSelection or queueRender error could free the queued request.

We now free requests in the return paths that still own them, and the
errdefer has been removed.

Also, activate a sequence only after encoding and queue append succeed
so failure preserves the previous sequence state.
2026-08-05 12:32:48 -07:00
Mitchell Hashimoto
b1887bd716 terminal: reset wrap state for CSI 2 K (#13637)
#13616

Reset the soft-wrap state when CSI 2 K erases the complete cursor row.
Previously, erase-to-end reset the flag while complete-line erase left
it set.

WezTerm, kitty, Alacritty, VTE, and xterm.js clear the wrap state for
complete-line erase. xterm preserves it, but xterm copies physical rows
during resize instead of reflowing them. Diverge from xterm so reflow in
Ghostty does not treat erased rows as one logical line, and cover the
behavior with a resize regression test.
2026-08-05 11:41:56 -07:00
Mitchell Hashimoto
c247e455c2 config: refill after ignored line boundaries
Refill the line iterator when an ignored comment or blank line
consumes the remaining buffered data.

Configuration parsing previously stopped silently at these boundaries
and left every subsequent setting unapplied.

Request more data before continuing the loop and cover both comment
and blank line boundaries with buffered-reader regression tests.
2026-08-05 11:30:45 -07:00
Mitchell Hashimoto
bfd40c84bd terminal: reset wrap state for CSI 2 K
#13616

Reset the soft-wrap state when CSI 2 K erases the complete cursor
row. Previously, erase-to-end reset the flag while complete-line erase
left it set.

WezTerm, kitty, Alacritty, VTE, and xterm.js clear the wrap state for
complete-line erase. xterm preserves it, but xterm copies physical rows
during resize instead of reflowing them. Diverge from xterm so reflow in
Ghostty does not treat erased rows as one logical line, and cover the
behavior with a resize regression test.
2026-08-05 11:26:48 -07:00
Jon Parise
0060d89b5b core: fix encoded key request cleanup
Encoded key requests are owned by the caller until they are added to a
key sequence or queued for IO. The child_exited path and failed queue
append returned without freeing the allocated request.

The existing errdefer was also too broad: after queueIo took ownership, a
later setSelection or queueRender error could free the queued request.

We now free requests in the return paths that still own them, and the
errdefer has been removed.

Also, activate a sequence only after encoding and queue append succeed
so failure preserves the previous sequence state.
2026-08-05 14:12:52 -04:00
Mitchell Hashimoto
54fe8e1885 macos: handled untrusted OSC8 hyperlinks more carefully (#13634)
OSC8 hyperlinks previously executed directly via the NSWorkspace opener
so a malicious application can just do whatever it wanted and trick the
user into opening something through Launch Services.

This PR notifies apprt of OSC8 hyperlinks so they can be handled
specially. In this PR, I added macOS-specific handling of OSC8 through a
variety of improvements:

  - Preview text is sanitized, so invisible Unicode characters now show.
- Questionable-looking URLs require confirmation to open, but a user can
confirm to open.
- Very questionable or definitely unsafe URLs are blocked with an alert
that only allows the user to copy the link. The alert also notifies the
user why.

This PR also adds an explicit `link-osc8` config (default true) that
users can use to disable osc8 completely.

## Demos

### Custom URL Schemes (Confirm)

<img width="1432" height="1110" alt="CleanShot 2026-08-05 at 10 25
57@2x"
src="https://github.com/user-attachments/assets/f7773ca2-3389-4749-a5c9-393ae097c044"
/>

### Invisible Characters (Block)

<img width="1432" height="1110" alt="CleanShot 2026-08-05 at 10 26
44@2x"
src="https://github.com/user-attachments/assets/bd2d0f33-f128-46e8-9bdb-227afecbb942"
/>

### Executable Target (Block)

<img width="1432" height="1110" alt="CleanShot 2026-08-05 at 10 27
31@2x"
src="https://github.com/user-attachments/assets/080c0524-2c8e-4931-892f-d2643a5d0d4e"
/>
2026-08-05 10:44:56 -07:00
Mitchell Hashimoto
77537c8065 macos: handled untrusted OSC8 hyperlinks more carefully
OSC8 hyperlinks previously executed directly via the NSWorkspace opener
so a malicious application can just do whatever it wanted and trick the
user into opening something through Launch Services.

This PR notifies apprt of OSC8 hyperlinks so they can be handled
specially. In this PR, I added macOS-specific handling of OSC8 through a
variety of improvements:

  - Preview text is sanitized, so invisible Unicode characters now show.
  - Questionable-looking URLs require confirmation to open, but a user
    can confirm to open.
  - Very questionable or definitely unsafe URLs are blocked with an 
    alert that only allows the user to copy the link. The alert also
    notifies the user why.
2026-08-05 10:22:28 -07:00
Jon Parise
4371871bc2 terminal/kitty: evict without scratch allocation
Track each image's placement count in its existing metadata. This lets
us use constant-time usage checks (rather than scans) during eviction.

Select the best candidate directly from storage on each eviction, preserving
the existing priority order: unused status, transient hint, generation, then
ID.

Since eviction no longer allocates, it can't fail, so callers no longer
need to handle out-of-memory conditions.
2026-08-05 13:16:27 -04:00
Mitchell Hashimoto
46767b5213 terminal: bound OSC and grapheme allocations (#13633)
Cap allocating OSC payloads at 8 MiB and retain at most 64 grapheme
suffix codepoints per cell. Our limits are generous compared to other
terminals and this prevents an easy DoS.

When the grapheme codepoint max is hit we just ignore any remainders.
This can result in real broken graphemes because Unicode spec is really
unbounded on them but for all practical use cases its reasonable.

Compared to other terminals:

| Terminal | OSC capture limit | Cell codepoints | 
| --- | ---: | ---: |
| Ghostty | 8 MiB | 65 |
| kitty | ~256 KiB ordinary | 24 |
| VTE | 4,096 scalars | 11 |
| xterm | 20 or 600 KB | 3 default, 6 max |
| Alacritty | unbounded | unbounded |
| WezTerm | unbounded | no explicit limit |
2026-08-05 09:52:11 -07:00
Mitchell Hashimoto
ad27c989a4 libghostty-vt: require opt-in for title reports (#13632)
Add an explicit libghostty-vt title-report option and keep CSI 21 t
disabled unless an embedder enables it.

Previously, registering the general PTY write callback also caused the
terminal to echo attacker-controlled window titles. This exposed
embedders to command injection after user interaction. Ghostty fixed
this a long time ago by making CSI 21 t an opt-in in the config. Do the
same but with our C/Zig API.
2026-08-05 09:32:45 -07:00
Mitchell Hashimoto
727b8a02f8 terminal: bound OSC and grapheme allocations
Cap allocating OSC payloads at 8 MiB and retain at most 64 grapheme
suffix codepoints per cell. Our limits are generous compared to other
terminals and this prevents an easy DoS.

When the grapheme codepoint max is hit we just ignore any remainders.
This can result in real broken graphemes because Unicode spec is really
unbounded on them but for all practical use cases its reasonable.

Compared to other terminals:

| Terminal | OSC capture limit | Cell codepoints |
| --- | ---: | ---: |
| Ghostty | 8 MiB | 65 |
| kitty | ~256 KiB ordinary | 24 |
| VTE | 4,096 scalars | 11 |
| xterm | 20 or 600 KB | 3 default, 6 max |
| Alacritty | unbounded | unbounded |
| WezTerm | unbounded | no explicit limit |
2026-08-05 09:30:24 -07:00
Mitchell Hashimoto
38e891e6c0 terminal: require opt-in for title reports
Add an explicit libghostty-vt title-report option and keep CSI 21 t
disabled unless an embedder enables it.

Previously, registering the general PTY write callback also caused the
terminal to echo attacker-controlled window titles. This exposed
embedders to command injection after user interaction.

Gate the response in the shared terminal stream, append the C API
option without renumbering existing values, and cover the default,
opt-in, and reset behavior in Zig and C API tests.
2026-08-05 09:17:03 -07:00
Mitchell Hashimoto
bd21ff153e terminal: avoid VS15 cursor underflow (#13631)
Handle VS15 width changes when the wide grapheme base is directly under
the cursor.

A zero cursor distance previously underflowed while locating the spacer
tail. Debug builds panicked and ReleaseFast computed an out-of-bounds
cell pointer before updating it.
2026-08-05 09:10:46 -07:00
Mitchell Hashimoto
fe98aef21c terminal: report DECECM as permanently reset (#12660)
Closes #12505 

This PR allows Ghostty to respond to DECRQM queries for DECECM with the
"permanently reset".

AI disclosure: I used Codex to help inspect the relevant code path and
explain the issue, but I reviewed and made the code changes myself.
2026-08-05 09:03:15 -07:00
Mitchell Hashimoto
33d34cf5ce terminal: avoid VS15 cursor underflow
Handle VS15 width changes when the wide grapheme base is directly under
the cursor. Cover both disabled wraparound and restored pending-wrap
cursor states.

A zero cursor distance previously underflowed while locating the spacer
tail. Debug builds panicked and ReleaseFast computed an out-of-bounds
cell pointer before updating it.

Find the spacer from the wide base instead of subtracting from the
cursor distance. Reposition the cursor from the base column and clamp it
to the active right margin.
2026-08-05 08:55:21 -07:00
Mitchell Hashimoto
dd035284c2 Kitty graphics protocol bugs (#13630)
Specifics in each commit message. This will be part of a security
advisory in 1.4.0 since these patches issues related to overflows, DoS,
unbounded memory allocation, etc.
2026-08-05 08:53:44 -07:00
Mitchell Hashimoto
402b9227de terminal/kitty: reclaim pruned placements
Reclaim pin-backed Kitty graphics placements after their tracked screen
content is pruned. Treat garbage pins as non-renderable until the next
placement command sweeps them.

Placements that scrolled beyond retained history previously remained in
the placement map and tracked-pin set. Long-running graphics output could
accumulate stale state, and remapped garbage pins could appear at an
unrelated fallback location.

Sweep garbage placements before growing the placement map, releasing each
tracked pin while preserving virtual placements. Return no geometry or
visible render position for garbage pins and cover both storage and C API
behavior with regression tests.
2026-08-05 08:37:45 -07:00
Mitchell Hashimoto
d0c516f8f3 terminal/kitty: release replaced placement pins
Release a Kitty graphics placement's tracked pin before replacement.

Repeated updates to an external placement previously leaked tracked pins.

Pass the owning screen to storage and deinitialize the old placement.
2026-08-05 08:28:13 -07:00
Mitchell Hashimoto
590d669c4a terminal/kitty: limit png decoder allocations
Limit individual allocator requests made by PNG decoders to the Kitty
graphics protocol's 400 MiB image ceiling. Add a reusable allocator
wrapper for callers that need per-request bounds.

PNG decoding previously used Wuffs' 4 GiB package limit and checked
the result only after allocation. A tiny PNG with oversized dimensions
could cause a multi-gigabyte RSS spike before being rejected.

Wrap decoder allocators with LimitedAllocator and translate limit
rejections to invalid image data while preserving genuine out-of-memory
errors. Add allocator boundary tests and regression coverage for a
crafted PNG below Wuffs' limit.
2026-08-05 08:24:42 -07:00
Mitchell Hashimoto
f766f303a7 terminal/kitty: validate shared memory ranges
Validate Kitty shared memory byte ranges before mapping and copying
image data. Interpret S as a byte count from O and preserve default
raw-image sizing.

Shared memory transmissions previously multiplied untrusted u32
dimensions before the limit check and sliced mappings with an unchecked
offset. Malformed commands could panic in safe builds or request a
wrapped allocation in fast builds.

Reject oversized dimensions before widening size arithmetic, derive
bounded ranges from the stat size, and enforce max_size before
constructing a slice. Add regression tests for explicit and implicit
offsets, out-of-bounds offsets, and maximum dimensions.
2026-08-05 08:20:41 -07:00