<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slosh.git/src/jsonval.c, branch v0.1.7</title>
<subtitle>an opinionated terminal multiplexer in C with programmable pane chrome</subtitle>
<id>https://git.sl0p.foo/slosh.git/atom/src/jsonval.c?h=v0.1.7</id>
<link rel='self' href='https://git.sl0p.foo/slosh.git/atom/src/jsonval.c?h=v0.1.7'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/'/>
<updated>2026-08-19T20:48:31Z</updated>
<entry>
<title>parsers: fix seven bugs found by fuzzing</title>
<updated>2026-08-19T20:48:31Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-19T20:48:31Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=009350acbcd4360680b8fa228d8cd03a2f2b5e93'/>
<id>urn:sha1:009350acbcd4360680b8fa228d8cd03a2f2b5e93</id>
<content type='text'>
kdl: heap-buffer-overflow on trailing backslash in a string (a"\)
jsonval: heap-buffer-overflow on truncated \uXXXX escape ("\u)
jsonval: UB float-to-long cast on out-of-range numbers (2e22)
expr: UB signed overflow in arithmetic ops — wrap as uint32
expr: INT32_MIN / -1 SIGFPE guard in OP_DIV/OP_MOD
expr: stack overflow on deep nesting — add MAX_DEPTH 256
expr: 64-bit + saturation in OP_DIST to prevent squared overflow
input: NULL memcpy in input_timeout's re-parse path
input: signed overflow in CSI and SGR mouse parameter accumulation
</content>
</entry>
<entry>
<title>sl0ppty: clang-format the tree</title>
<updated>2026-08-17T12:22:38Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-17T12:22:38Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=ec91ccffe631ae34b111bf6161fd0e3c487f684c'/>
<id>urn:sha1:ec91ccffe631ae34b111bf6161fd0e3c487f684c</id>
<content type='text'>
The bumpy one. `make fmt` over every `.c` and `.h` outside `vendor/`: 32 files,
1,843 lines rewritten, no behaviour changed. Nothing here is worth reading -- the
next commit adds it to `.git-blame-ignore-revs` so `git blame` walks past it.

Two thirds of it is alignment the formatter now owns: trailing comments in a
struct, continuation lines under a signature. The rest is the hand-packed tables
opening up to one entry per line -- `ACTIONS`, `NAMED_KEYS`, `ACTION_HELP`. That
is a real loss of density and a real gain in diffs: adding an action was a reflow
of the block and is now one line. Anything worth keeping packed can be fenced with
`// clang-format off`; nothing was, on the grounds that a table is the thing a
formatter is for.

**One change is not formatting.** `src/config.h` had three trailing comments glued
onto one field:

    uint16_t hover_delay_ms; /* how long the pointer must rest to arm a guide */
    /* how long an announcement stays up */ /* rows per wheel notch */

-- `toast_ms`'s and `scroll_lines`' comments, landed on their neighbour by an
earlier edit, documenting the wrong things ever since. It is in this commit
because it is what caught it: clang-format could not settle on that line, wrapping
it one way and then re-indenting the wrap on a second pass, so `make fmt` was not
idempotent. The comments are back where they belong and it is.

Verified after the reformat, not before: `make clean &amp;&amp; make all` is
warning-free, `make retest` is 1801 checks green, and `make fmt` twice in a row
changes nothing the second time. A formatter that alters behaviour would be worse
than none, so the gate was the whole suite rather than a reading of the diff.
</content>
</entry>
<entry>
<title>sl0ptty: M3 — tabs, purposes, and the JSON control API</title>
<updated>2026-08-13T20:58:24Z</updated>
<author>
<name>sl0p</name>
<email>sl0p@sl0p.foo</email>
</author>
<published>2026-08-13T20:58:24Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=7d416d95cb49f783f8c4ee6eddd5c2cdcd81bb40'/>
<id>urn:sha1:7d416d95cb49f783f8c4ee6eddd5c2cdcd81bb40</id>
<content type='text'>
Tabs are layout trees, one per tab, and panes in every tab keep running: fds,
pumping and reaping span all of them, only the current one is composed. A
one-row strip shows them (M5 makes it the real status bar) and each label
registers a hit, so clicking a tab switches to it through the same mechanism
as every other click.

  C-a c  new tab      C-a n / C-a p  cycle      C-a 1..9  select

Purposes on panes and tabs with D8's trust model implemented as a lock:
declared (from a layout or an operator) outranks in-band, cannot be overridden,
and everything is sanitised to [A-Za-z0-9_.:/-] on ingest — 'project:foo
bar/../$(rm -rf)' becomes 'project:foobar/../rm-rf'. The in-band path arrives
with the OSC scanner in M4 and always passes declared:false; the refusal is
already tested.

The control API is now JSON in, JSON out:

  {"cmd":"new-tab","name":"agent","purpose":"project:x.deadbeef"}
  {"ok":true,"id":2}

with panes/tabs/snapshot/send/raw/resize/split/focus/close/select-tab/
set-name/set-purpose/alive/quit. Panes are addressed by id, not by 'the
focused one', so a background tab can be scripted. The bare-verb form stays as
a harness alias and runs the same code, so the tests cannot drift from the API.
Adds a small JSON reader (jsonval.c) — we could only emit until now.

129 checks green.
</content>
</entry>
</feed>
