Skip to content

Fix crashes and lost messages - #2

Merged
KimNorgaard merged 1 commit into
mainfrom
fix-bug-hunt
Oct 3, 2026
Merged

KimNorgaard merged 1 commit into
mainfrom
fix-bug-hunt

Conversation

@KimNorgaard

@KimNorgaard KimNorgaard commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Fixes the bugs from a review of the codebase. Two crashes come from normal keyboard use, and any member of a space could crash the client with an image. Messages could also be dropped silently. Rebased on #1, which already covers escape stripping and card link schemes.

  • Clamp the switcher pick so no matches can't index matches[-1]
  • Reset the thread cursor on space open, and make enter go through target()
  • Check image dimensions with DecodeConfig before decoding, and cut GIFs to a bounded number of frames with gifPrefix
  • Merge messages that arrive while a space loads instead of replacing them
  • Fetch the whole thread when a live reply arrives for a thread outside the loaded history
  • Fetch an unknown space before handling its first message
  • Clear loadingOlder on errors so one failed page doesn't block older history
  • Run sender names, attachment names and quote labels through clean. The renderer turns OSC 8 into links, so stripC1 on the frame doesn't catch them.
  • Ignore OAuth callback requests without our state, such as /favicon.ico, and never block on a repeated redirect
  • Keep the first selected block's first line in view
  • Bold both words in *a* *b*
  • Keep the selection when a message above it is deleted
  • Drop a pending edit or quote on space switch
  • Keep the baked-in OAuth client when config.json only sets a topic (README updated)

Known gap: a delete or edit event that arrives while a space loads can still be overwritten by the load result.

Tested with:

just check

🤖 Generated with Claude Code

A review of the codebase found these bugs.

Crashes:
- The switcher's down key set pick to -1 with no matches, and the next
  refilter indexed matches[-1].
- Opening a space kept the old thread cursor, so an event during the load
  left it past the end and enter indexed out of range.
- Image and GIF decoding allocated by the declared size. A small file could
  declare gigabytes. Sizes are now checked with DecodeConfig, and GIFs are
  cut to a bounded number of frames before decoding.

Lost or wrong messages:
- Messages that arrived while a space loaded were replaced by the load
  result. They are now merged in.
- A live reply to a thread outside the loaded history showed without its
  root, and loading older history then dropped the full thread. The thread
  is now fetched when its first reply arrives.
- The first message in a new space was dropped when it beat the membership
  event. The space is now fetched first.
- A failed page of older history blocked further loads until restart.

Untrusted content:
- Sender names, attachment names and quote labels go through clean. The
  renderer turns OSC 8 sequences into links, so stripC1 on the frame
  doesn't cover them.
- The login callback ignores requests without our state, such as
  /favicon.ico, instead of failing the login, and never blocks on a
  repeated redirect.

Smaller fixes:
- Selecting the first thread or message no longer scrolls its first line
  out of view.
- "*a* *b*" bolds both words.
- Deleting a message keeps the selection on the same thread or message.
- Switching spaces drops a pending edit or quote.
- A config.json with only a topic keeps the baked-in OAuth client.
@KimNorgaard KimNorgaard changed the title Fix crashes, lost messages and unsafe rendering Fix crashes and lost messages Oct 3, 2026
@KimNorgaard
KimNorgaard merged commit 7270117 into main Oct 3, 2026
1 check passed
@KimNorgaard
KimNorgaard deleted the fix-bug-hunt branch October 3, 2026 11:59
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