Commit Graph

16581 Commits

Author SHA1 Message Date
ghostty-vouch[bot]
78a9731c9d Update VOUCHED list (#13299)
Triggered by
[comment](https://github.com/ghostty-org/ghostty/issues/13296#issuecomment-4948155117)
from @00-kat.

Vouch: @Arvin7liu

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-11 17:50:36 +00:00
Mitchell Hashimoto
53bd14fecf terminal: update page serial to be treated as a generation marker (correctness) (#13282)
This changes our `page_serial` semantics from monotonic min to a
generation marker (any change means you should reload). This fixes a
number of real bugs that search had.

In reality, this invariant was already broken and not true. So this PR
comes to reality with that and fixes all our usage. The most visible
failures were panics when selecting cached search results after
partially erasing a history page or splitting a page, but the same bug
class affected viewport search fingerprints and asynchronous render
highlights.

It was mostly search, for now, but this type of fix is important for
some upcoming work I'm playing around with regarding deferred reflow and
disk offload.

## Page Serial Semantics

`Node.serial` is now explicitly a page generation. It changes whenever a
node is allocated or reused, and whenever an in-place mutation changes
the meaning or valid range of its row coordinates.

`page_serial_min` is renamed to `page_serial_epoch` to reflect its
remaining purpose. Only a whole-list reset advances the epoch. A serial
below the epoch is definitely stale and can be rejected in O(1); a
serial at or above it is only potentially valid and is checked against
the live list using its captured pointer and generation.

## Performance

The generation bump is constant work per node whose layout is already
being changed. There is no additional page-list scan on normal row
append or scrollback pruning.

I did add a new field to the render state, so I ran render state
benchmarks we already have that shows a very slight slowdown but this is
acceptable especially given recent speedups outweigh this significantly:

| render measurement | before | after | change |
|--------------------|--------|-------|--------|
| full rebuild | 2.915 us/update | 2.926 us/update | +0.27% |
| lock-held rebuild | 2.472 us/update | 2.489 us/update | +0.53% (within
noise) |
| clean update | 19.03 ns/update | 19.30 ns/update | +1.43% (+0.27 ns) |
| one dirty row | 52.97 ns/update | 53.40 ns/update | +0.96% (within
noise) |
| flattened highlight miss | 86.77 ns/update | 86.87 ns/update | +0.19%
(within noise) |
| flattened highlight match | 88.38 ns/update | 90.26 ns/update | +2.00%
(+1.88 ns) |

## LLM Notes

This work was done in concert with Codex. I reviewed and reshaped the
serial model, implementation, tests, documentation, and performance
analysis throughout. This PR message is hand-written.
2026-07-10 09:54:42 -07:00
Mitchell Hashimoto
89eca063e9 terminal/search: avoid pruning history on reload
reloadActive previously pruned every cached history result whenever the
active area changed. Search reconciliation runs under the terminal lock,
so this scaled with both result and page counts on a frame-paced path.

Validate only the selected history result during reload. Keep full
pruning before selection navigation so stale candidates are removed
before their coordinates are tracked.
2026-07-10 09:50:40 -07:00
Mitchell Hashimoto
0bad91adb8 terminal: renew generations for direct row shifts
Screen scroll fast paths and Terminal line insertion/deletion move Row
values directly instead of using PageList erasure helpers. Their node
generations therefore stayed valid after cached row coordinates changed.

Expose the PageList layout invalidator to sibling terminal modules and
renew each affected existing page once before full-row rotations or
swaps. Keep partial-width cell moves on the content-only path and cover
same-page, cross-page, and fresh-tail behavior.
2026-07-10 09:29:11 -07:00
Mitchell Hashimoto
d4ac93a039 terminal: add clipboard_set effect for OSC 52 clipboard writes (#13182)
libghostty-vt was already parsing OSC 52 into the clipboard_contents
action but the stream handler dropped, so there was no way to observe
clipboard writes (in this case, a program using go-libghostty). This
adds a clipboard_set effect following the existing bell/title_changed
pattern and expose it through the C API as
`GHOSTTY_TERMINAL_OPT_CLIPBOARD_SET`.

The callback receives the OSC 52 kind byte and the base64 payload
exactly as received; decoding and kind interpretation are left to the
embedder, matching how decoding is typically deferred.

Note this intentionally does not deal with clipboard read requests given
the security implications.

AI disclosure: Fable (via Claude Code) did the majority of the work
here, I validated it on the client side and fully understand the pattern
we're fitting into.
2026-07-10 09:27:21 -07:00
Mitchell Hashimoto
634ef71986 terminal: make clipboard writes protocol neutral
#13182

Replace the OSC 52-specific kind and encoded payload callback with an
atomic clipboard write containing a normalized destination and decoded
MIME representations. This keeps protocol details out of embedders and
lets iTerm2 Copy use the same semantic path.

Represent clears with an empty content list, preserve binary payloads,
and return a generic result for protocols that acknowledge writes. Add
the C ABI descriptors, layout metadata, and effects example so future
multipart protocols can reuse the callback without another API break.
2026-07-10 09:17:59 -07:00
Mitchell Hashimoto
f6d9a582e4 terminal: rename page serial floor as epoch
page_serial_min no longer represented the minimum live page serial.
Its name still suggested an ordering relationship and obscured the
remaining reset-only invalidation behavior.

Rename the field to page_serial_epoch and document its O(1) rejection
and ScreenSearch bulk-pruning utility. Explicitly verify that ordinary
bounded pruning does not begin a new whole-list epoch.
2026-07-10 08:29:31 -07:00
Mitchell Hashimoto
4aa3c1051d terminal: vectorize APC payload scanning (#13281)
Kitty graphics payloads are dispatched in bulk, but finding each slice
boundary still examines every byte with a scalar loop. This leaves large
direct base64 image transmissions parser-bound.

Scan ordinary APC bytes using the vector width recommended for the
compile target. Keep the scalar scan both as the tail and as the full
fallback when the target has no recommended vector width. Test
state-machine boundaries against byte-at-a-time parsing.

A ReleaseFast APC parser benchmark over the same 64 MiB Kitty graphics
corpus, with 10 warmups and 30 measured runs, produced:

```
                  mean       median
  scalar        37.6 ms      32.6 ms
  vectorized    22.3 ms      19.0 ms
```
Hyperfine reports the vectorized version as **1.69 times faster
overall**, with the median runtime improving by approximately 42
percent.

AI Disclosure: This patch was created with the assistance of GPT-5.6
2026-07-10 08:11:30 -07:00
Mitchell Hashimoto
dd956f37cc terminal: renew generations for shifted rows
Single-row erasure and trailing blank-row trimming can remap or remove
stored row coordinates while retaining the same node. External pointer-
plus-generation references could therefore survive these less common
PageList mutation paths.

Renew each affected node inside the traversal that already changes it,
and signal compression activity only when row erasure begins in
history. This adds constant work per touched page without another list
scan or normal append cost.
2026-07-10 07:34:01 -07:00
Mitchell Hashimoto
d0a26d1460 terminal: reschedule compression after page replacement
Compaction and capacity growth publish fresh page generations, so an
active incremental traversal can detect them. They did not update the
separate activity token, however, and a completed compressor could
remain idle after either operation restored or replaced a cold page.

Mark successful replacements as compression activity without resetting
the exact continuation marker. The next scheduled step can retain valid
progress or restart through the existing generation checks.
2026-07-10 07:34:01 -07:00
Mitchell Hashimoto
a89c6133c5 terminal/search: validate history before reload
ScreenSearch reloaded active state before pruning stale flattened
history. Reload could compare a shifted tracked selection against
cached page coordinates and panic before the later validation step ran.

Prune history immediately after dimension reconciliation in
reloadActive, before any cached coordinate is inspected or converted to
a pin. Selection now relies on that ordering and avoids a redundant
second prune.
2026-07-10 07:34:01 -07:00
Mitchell Hashimoto
c9ad708ef7 terminal: validate flattened highlight generations
RenderState applied flattened highlights after releasing the terminal
lock and matched them to copied rows by node address alone. A recycled
address could therefore make a stale asynchronous highlight decorate
unrelated content.

Capture the live node generation with each render row and require both
the pointer and copied generation to match. Validation remains lock-
free and never dereferences a potentially stale node.
2026-07-10 07:34:01 -07:00
Mitchell Hashimoto
c243d89bdf terminal/search: include generations in viewport fingerprints
ViewportSearch compared only cached node addresses when deciding
whether to reuse its owned search window. An in-place layout change or
pool address reuse could therefore make stale text and coordinates
appear current.

Snapshot each node generation with its pointer and compare only those
captured values. This detects a renewed generation at the same address
without ever dereferencing cached node pointers.
2026-07-10 07:34:01 -07:00
Mitchell Hashimoto
83aada2056 terminal/search: preserve serial order in reverse matches
Reverse multi-page highlight construction reordered node and row-
bound columns but left captured page generations in their original
order. Every cross-page result therefore paired each node with another
page generation and could be rejected as stale despite remaining live.

Reverse the serial column with the other flattened chunk metadata and
cover the node-plus-generation pairing in the existing boundary match
test.
2026-07-10 07:34:00 -07:00
Mitchell Hashimoto
91a63e5287 terminal: invalidate split source page refs
PageList.split moved the source suffix into a fresh target but left
the shortened source on its old generation. Cached matches in that
suffix could therefore pass validation against the live source pointer
and reach pin tracking with invalid coordinates.

Renew the source generation only after target cloning succeeds, and
mark compression activity so restored history is reconsidered. The
conservative floor keeps bounded pruning safe even when the renewed
source and fresh target precede older successors.
2026-07-10 07:34:00 -07:00
Mitchell Hashimoto
a804e3ac78 terminal: invalidate partially erased page refs
Partial history erasure shifted retained rows while preserving the
node generation. Cached flattened matches then passed pointer-plus-
generation validation and could be tracked with coordinates beyond the
shortened page.

Renew the generation before reinitializing or shifting a page layout,
and mark compression activity so an incremental pass restarts and
revisits a restored cold page. The conservative serial floor permits
the fresh generation to remain before older live successors without
rejecting them.
2026-07-10 07:34:00 -07:00
Mitchell Hashimoto
f1a5fab452 terminal: keep page serial floor conservative
Page generations are not ordered with the page list because splits
and in-place replacements insert fresh generations before older live
pages. Advancing page_serial_min while pruning could therefore reject
live successors and fail PageList integrity checks.

Keep the floor as a whole-list invalidation epoch and use the existing
pointer-plus-generation membership check for ordinary removals. Add
bounded pruning coverage for split and replacement ordering, and verify
reset still rejects a stale generation when its node address is reused.
2026-07-10 07:34:00 -07:00
Tim Culverhouse
8c523ed039 terminal: vectorize APC payload scanning
Kitty graphics payloads are dispatched in bulk, but finding each slice
boundary still examines every byte with a scalar loop. This leaves large
direct base64 image transmissions parser-bound.

Scan ordinary APC bytes using the vector width recommended for the compile
target. Keep the scalar scan both as the tail and as the full fallback when
the target has no recommended vector width. Test state-machine boundaries
against byte-at-a-time parsing.

A ReleaseFast APC parser benchmark over the same 64 MiB Kitty graphics
corpus, with 10 warmups and 30 measured runs, produced:

                  mean       median
  scalar        37.6 ms      32.6 ms
  vectorized    22.3 ms      19.0 ms

Hyperfine reports the vectorized version as 1.69 times faster overall, with
the median runtime improving by approximately 42 percent.
2026-07-10 09:29:15 -05:00
Mitchell Hashimoto
3f2b7946d7 Misc runtime safety fixes (#13278)
All found by GPT 5.6. I'm still going through manual review of each one
now and will remove or rewrite the ones that are pointless or
unreachable (if any, I prompted it to ignore those too).
2026-07-10 06:58:02 -07:00
Mitchell Hashimoto
9b466e9c55 terminal: fix count-limited page iteration
Count-limited PageIterator traversal took the minimum of the page and requested lengths, then tested whether that minimum exceeded the request. The condition was impossible, so iteration never crossed a page. Reverse traversal also excluded the current row and subtracted one from row zero, causing a runtime safety panic.

Count the current row in both directions, consume the returned length, and move to an adjacent page only when the request has rows remaining. Returned chunks now preserve their half-open bounds at row zero and across page boundaries.
2026-07-10 06:54:20 -07:00
Mitchell Hashimoto
73ac36fa56 terminal/search: discard destroyed screen state
Search selection could run after the terminal removed a screen but before the next refresh reconciled the cached searchers. Reloading that stale ScreenSearch dereferenced freed PageList nodes, while normal cleanup also tried to untrack pins from the destroyed list.

Reconcile under the terminal lock before selecting, track ScreenSet generations so allocator address reuse cannot hide replacements, and release stale search buffers without touching pins already freed with the screen. Cleanup now takes the same lock when live pins must be untracked.
2026-07-10 06:54:20 -07:00
Mitchell Hashimoto
86e1f7b8b5 terminal/search: reject replaced result pages
History pruning only compared cached serials with page_serial_min. Replacing a historical node through compaction left its old serial above that cutoff, so selecting the cached match attempted to track a destroyed node and hit the PageList validity assertion.

Validate every flattened chunk by finding the live node and matching its serial without dereferencing stale pointers. Remove only the invalid result and adjust any later selection index so unrelated older results remain available.
2026-07-10 06:47:10 -07:00
Mitchell Hashimoto
5d8eb78b73 terminal/search: reset pins while feeding
PageListSearch.feed changed only the node of its tracked progress pin. If the preceding history page had fewer rows or columns after a split, the retained bottom-right coordinates fell outside that page and the next PageList integrity check panicked.

Reset both coordinates to the new node's actual bottom-right cell whenever feed advances. The progress pin now remains valid across heterogeneous page sizes.
2026-07-10 06:47:10 -07:00
Mitchell Hashimoto
d239f98056 terminal/search: drop pruned selections
Partial history erasure can remove a page without marking tracked pins as garbage because they move coherently to the next page. ScreenSearch therefore retained a selection whose cached history result was subsequently removed by pruneHistory. Selecting again indexed an empty history result list and panicked.

Clear the tracked selection when its combined result index falls within the history suffix being pruned. Retained active and newer history selections keep their existing indices.
2026-07-10 06:47:10 -07:00
Mitchell Hashimoto
cfce1cd56c terminal: duplicate hyperlinks before replacement
startHyperlink accepts borrowed URI and ID slices. When those slices came from the current cursor hyperlink, startHyperlinkOnce ended and freed that hyperlink before duplicating the replacement, then dereferenced the released URI and segfaulted.

Duplicate the new hyperlink before ending the prior one. Aliased inputs remain valid through the copy, and allocation failure leaves the existing cursor hyperlink intact.
2026-07-10 06:47:10 -07:00
Mitchell Hashimoto
dace6d1c6d terminal: handle aliased title updates
setTitle can receive the slice returned by getTitle. Clearing the list retained its allocation, so appending that same slice used memcpy with aliased source and destination ranges and panicked in runtime-safe builds.

Resize the list within its reserved capacity and copy the value forward before writing the sentinel. This supports the complete current value and its subslices without weakening allocation-failure atomicity.
2026-07-10 06:47:10 -07:00
Mitchell Hashimoto
a14a619ceb terminal: handle aliased pwd updates
setPwd can receive the slice returned by getPwd. Clearing the list retained its allocation, so appending that same slice used memcpy with aliased source and destination ranges and panicked in runtime-safe builds.

Resize the list within its reserved capacity and copy the value forward before writing the sentinel. This supports the complete current value and its subslices without weakening allocation-failure atomicity.
2026-07-10 06:47:09 -07:00
Mitchell Hashimoto
0c299000f8 terminal: preserve aliased selection pins
Screen.select accepted an already tracked selection by value. Passing the screen's current selection back into the setter caused the old selection cleanup to free the same pin pair that the replacement retained, so the next selection operation dereferenced stale pool entries and panicked.

When replacing tracked state, release only old pins that are not also owned by the replacement. Exact and partial aliases now retain their shared pins while ordinary replacements still reclaim both old entries.
2026-07-10 06:47:09 -07:00
Mitchell Hashimoto
91f0cf67d5 terminal: preserve tabstops on resize failure
Terminal.resize deinitialized the current tab stops before allocating their replacement. If a resize beyond the inline tab-stop capacity ran out of memory, the terminal retained an undefined tab-stop value and normal deinitialization dereferenced a poisoned pointer.

Allocate and initialize the replacement first, then release the old tab stops only after allocation succeeds. A failed resize now retains the original tab stops and remains safe to destroy.
2026-07-10 06:47:09 -07:00
Mitchell Hashimoto
fdd255c782 terminal: reserve title terminator atomically
setTitle appended the title bytes and terminating NUL with separate fallible operations. If only the terminator allocation failed, it returned OutOfMemory but left a nonempty unterminated buffer that made getTitle panic on its sentinel check.

Reserve checked capacity before clearing the existing title, then append both the title and terminator without further allocation. Allocation failure now leaves the prior valid title intact.
2026-07-10 06:47:09 -07:00
Mitchell Hashimoto
1d5b6f90e5 terminal: reserve pwd terminator atomically
setPwd appended the path bytes and terminating NUL with separate fallible operations. If only the terminator allocation failed, the function returned OutOfMemory but left a nonempty unterminated buffer that made getPwd panic on its sentinel check.

Reserve checked capacity for the complete sentinel-terminated value before clearing the old state, then use infallible appends. Allocation failure now leaves a valid prior value instead of exposing partial data.
2026-07-10 06:47:09 -07:00
Mitchell Hashimoto
04810273af terminal: wrap implicit hyperlink identifiers
Implicit OSC 8 hyperlinks incremented a u32 identifier with checked arithmetic even though the cursor contract allows the sequence to wrap. Reaching the maximum identifier therefore caused a runtime safety panic before the link could be installed.

Use wrapping arithmetic for both the successful increment and the error rollback. The identifier now returns to zero at the boundary, while failed allocation attempts still restore the original value.
2026-07-10 06:47:09 -07:00
Mitchell Hashimoto
b287f6d1ab terminal: handle stored grapheme boundaries
With mode 2027 disabled, the printer attaches zero-width codepoints without applying Unicode grapheme boundaries. Enabling the mode later and printing another non-ASCII codepoint asserted that every stored pair was part of one grapheme and panicked when it was not.

Feed all stored codepoints through the grapheme state machine and let it reset at existing boundaries before testing the new codepoint. The deterministic print comparison can now exercise live mode changes without clearing the screen first.
2026-07-10 06:47:09 -07:00
Mitchell Hashimoto
e727a36589 terminal: clear rows using stored page width
Screen.clearRows sliced backing cells using the desired PageList width.
During incomplete reflow, clearing a narrower stored page extended the
slice past its row and tripped clearCells runtime validation before any
cells were cleared.

Obtain cells from the owning page and use its stored width for whole-row
managed-memory bookkeeping. Mixed-width history rows now clear safely.
2026-07-10 06:44:21 -07:00
Mitchell Hashimoto
b6f34be44f terminal: clamp mirrored selection corners
Rectangle orientation swaps endpoint columns when a selection is mirrored.
During incomplete reflow, copying a column from a wider page onto the
narrower corner page created an invalid pin that panicked when resolved.

Clamp every swapped column to the page that owns the oriented corner.
Top-left and bottom-right calculations now always return valid pins.
2026-07-10 06:44:21 -07:00
Mitchell Hashimoto
6071606577 terminal: clamp cloned selections to page width
Screen.clone clipped selections with the desired screen width or copied
rectangle columns unchanged. PageList.clone preserves stored page widths,
so a clipped boundary on a narrower page produced an invalid tracked pin
and panicked during runtime validation.

Build fallback pins from the first or last cloned node and clamp rectangle
columns to that node. Clipped selections now remain valid during reflow.
2026-07-10 06:44:21 -07:00
Mitchell Hashimoto
08e376f239 terminal: bound selection drag geometry
Selection drags converted caller-provided floating-point positions directly
to u32 and multiplied geometry dimensions without checking their range.
Non-finite positions, oversized values, overflowing dimensions, or empty
core geometry could therefore panic in runtime safety builds.

Clamp pixel positions to the representable u32 range, reject empty
geometry, and saturate the pixel span when dimensions overflow. Valid
drags keep their existing threshold behavior.
2026-07-10 06:44:21 -07:00
Mitchell Hashimoto
a55850c981 terminal: use previous page width for cursor cells
cursorCellEndOfPrev moved its pin to the previous row but then set the
column from the desired screen width. If incomplete reflow left that
previous page narrower, resolving the cell used an out-of-bounds column
and panicked in runtime safety builds.

Set the column from the page reached by the cursor pin so the returned
cell is always the actual final cell of that row.
2026-07-09 20:58:14 -07:00
Mitchell Hashimoto
a9f5b7eba2 terminal: clamp selection rows to page width
containedRowCached built full-row and rectangular selections using
the desired screen width. During incomplete reflow, an intermediate
narrower page received endpoints beyond its cell range, and consumers
could panic when resolving the returned pins.

Use the owning page width for full rows and clamp rectangular bounds to
that width. Every contained-row selection now returns resolvable pins.
2026-07-09 20:56:44 -07:00
Mitchell Hashimoto
fa8cae88b2 terminal: use destination width for line selection
Semantic line selection moved to the previous row when the next row
started with different content, then assigned the previous pin an x
coordinate from the next page. During incomplete reflow, a wider next
page produced an out-of-bounds pin and a runtime safety panic.

Set the end column from the page that owns the destination pin. Line
selection now remains valid while crossing mixed-width page boundaries.
2026-07-09 20:54:09 -07:00
Mitchell Hashimoto
3d08161b50 terminal: handle empty tabstop ranges
Tabstops.reset subtracted one from the column count before iterating
default stops. Although init and resize accept zero columns, resetting
that state with a nonzero interval underflowed and panicked.

Return after clearing when the grid has fewer than two columns. Empty
and single-column tabstop sets now preserve the normal no-stop result.
2026-07-09 20:50:23 -07:00
Mitchell Hashimoto
8f1c2fe959 terminal: handle backwards selection timestamps
SelectionGesture passed caller-supplied repeat timestamps directly to
Instant.since. A C API client or non-monotonic timer could provide an
earlier timestamp after a later one, causing a runtime safety panic
while converting negative elapsed seconds to u64.

Compare instants before calculating elapsed time and treat backwards
timestamps as failed repeats. The next press becomes a new single-click
anchor, matching other invalid repeat inputs.
2026-07-09 20:48:58 -07:00
Mitchell Hashimoto
0cb004734e terminal: ignore empty cell clears
Screen.clearCells accepted a slice but its runtime safety validation
indexed the first and last elements unconditionally. Passing an empty
range therefore panicked before the otherwise valid no-op clear.

Return immediately for an empty slice so validation and managed-memory
bookkeeping only run when there are cells to clear.
2026-07-09 20:38:29 -07:00
Mitchell Hashimoto
d6e24d9856 terminal: make pin traversal width-aware
Pin movement assumed every page had the same column count. During an
incomplete reflow, crossing into a narrower page could produce an
out-of-bounds x coordinate, while wrapped movement could land on the
wrong row or stop early.

Use destination page widths while moving vertically or wrapping, and
reject points that exceed the resolved page. Add synthetic mixed-width
coverage for movement, wrapping, overflow, and point conversion.
2026-07-09 20:38:28 -07:00
Mitchell Hashimoto
30b42f42a3 terminal: reject unrepresentable pin coordinates
pointFromPin accumulated scrollback rows directly into the u32 Y
field. An unbounded PageList with more than 2^32 rows could overflow
while converting a valid pin and panic in runtime safety builds.

Use checked additions for every cross-page row contribution. If the
pin cannot fit in point.Coordinate, return null through the existing
out-of-range result instead of trapping.
2026-07-09 20:38:18 -07:00
Mitchell Hashimoto
e6e4a9fdc1 terminal: widen cell screen coordinates
Cell.screenPoint accumulated page row counts in CellCountInt even
though screen point Y coordinates are u32. Once scrollback crossed
65,535 rows, walking back through page metadata overflowed and trapped
in runtime safety builds.

Accumulate directly in u32 so page-local u16 row counts widen before
addition and the result uses the full range promised by point.Coordinate.
2026-07-09 20:23:06 -07:00
Mitchell Hashimoto
afbf5ba156 terminal: handle minimum prompt scroll delta
Prompt scrolling negated negative deltas to count the requested jumps.
minInt(isize) has no positive signed representation, so a caller could
trigger a runtime safety panic before the search for an earlier prompt
started.

Use @abs to produce the full unsigned magnitude. An extreme negative
request now follows the normal prompt traversal and clamps at the oldest
available prompt.
2026-07-09 20:20:46 -07:00
Mitchell Hashimoto
c753fe4a4f terminal: handle minimum row scroll delta
PageList.scroll negated negative row deltas to obtain their
magnitude. minInt(isize) has no positive signed representation, so
callers could trigger a runtime safety panic before the existing
traversal had a chance to clamp at the top.

Use @abs to calculate an unsigned magnitude that represents every isize
value. The same value now drives both cached-pin and general traversal
paths.
2026-07-09 20:19:37 -07:00
Mitchell Hashimoto
35e1a0160c build(deps): bump cachix/install-nix-action from 31.10.6 to 31.10.7 (#13271)
Bumps
[cachix/install-nix-action](https://github.com/cachix/install-nix-action)
from 31.10.6 to 31.10.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cachix/install-nix-action/releases">cachix/install-nix-action's
releases</a>.</em></p>
<blockquote>
<h2>v31.10.7</h2>
<h2>What's Changed</h2>
<ul>
<li>nix: 2.34.7 -&gt; 2.34.8 by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/cachix/install-nix-action/pull/278">cachix/install-nix-action#278</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/cachix/install-nix-action/compare/v31.10.6...v31.10.7">https://github.com/cachix/install-nix-action/compare/v31.10.6...v31.10.7</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a49548c11d"><code>a49548c</code></a>
Merge pull request <a
href="https://redirect.github.com/cachix/install-nix-action/issues/278">#278</a>
from cachix/create-pull-request/patch</li>
<li><a
href="147e749b5f"><code>147e749</code></a>
nix: 2.34.7 -&gt; 2.34.8</li>
<li><a
href="23cf0fec1d"><code>23cf0fe</code></a>
Merge pull request <a
href="https://redirect.github.com/cachix/install-nix-action/issues/276">#276</a>
from cachix/dependabot/github_actions/actions/checkout-7</li>
<li><a
href="8bdfc70a3e"><code>8bdfc70</code></a>
chore(deps): bump actions/checkout from 6 to 7</li>
<li>See full diff in <a
href="8aa03977d8...a49548c11d">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cachix/install-nix-action&package-manager=github_actions&previous-version=31.10.6&new-version=31.10.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2026-07-09 20:04:02 -07:00
Mitchell Hashimoto
6236d3859c Misc runtime safety fixes (#13275)
Runtime safety violating scenarios found by GPT 5.6. Verified each one
manually. See each commit.

I'm going to keep searching so not going to merge this yet.
2026-07-09 20:03:10 -07:00