Repository navigation
v0.9.6 — bug-fix: scroll-down regression + unauthenticated accept-loop DoS
Bug-fix patch: a scroll-down regression + an unauthenticated accept-loop DoS
Two fixes over v0.9.5, both from @antonmos. If you're on v0.9.5, or you use second-client preemption on v0.9.3+, upgrade — one of these is a scroll regression, the other an unauthenticated remote DoS.
#179 — scroll-down is no longer inflated ~255× (regression introduced in v0.9.5)
v0.9.5's pin bump moved ironrdp-pdu past its own wheel-rotation decode fix (it now decodes the 9-bit WheelRotationMask as proper two's complement), but didn't delete the vendored compensation (divergence 17) that only existed to correct the old buggy decode — so it began double-correcting. Every downward tick (−1) became −255, a max-speed scroll, while upward scrolling stayed correct. That asymmetry — down runs away, up is fine — is the fingerprint (macrdp #113, in the opposite direction). Worst on the macOS Windows App's fine ±1..±3 trackpad deltas; mstsc was ~13 % too fast on the way down.
Divergence 17 is retired (the delta passes through unchanged), and a new end-to-end round-trip test (encode → decode → MouseEvent, both directions) pins the contract so a future pin bump that changes the decode fails in CI, not in a user's hands.
#180 — an unauthenticated remote client can no longer wedge the accept loop (security; latent since v0.9.3)
The second-client-preemption path awaited a candidate's negotiation unbounded — and that negotiation blocks on socket reads from a peer that has not yet authenticated. A single TCP connection to the port that completed the handshake and then sent nothing parked the accept loop: accepts were already gated off for the rest of the session, and once the live session ended the loop hung on the handoff await with no select! left — no accepts, no event drain, not even a Quit. One silent connection wedged the whole listener until the process restarted, and — like the v0.9.4 find_size DoS — the health watchdog doesn't catch it (the runtime stays healthy; only the accept loop is stuck).
Fixed with two separate bounds — a 10 s cap on the negotiation and a 750 ms cap on the post-session-end handoff wait (the window where the loop services nothing) — plus a regression test that reproduces the hang. The same PR also fixes two more preemption bugs: the server-global eviction event could be drained by, and disconnect, the winner of a takeover (stale events are now discarded before serving a winner), and the anti-storm re-preempt lockout was uncapped and permanently barred a dropped client from reclaiming its own stale session (now capped at 30 s). All three were found by the automated reviewer on upstream Devolutions/IronRDP#1476 and confirmed present in the vendored copy.
Artifacts
macrdp-v0.9.6-aarch64-apple-darwin-app.zip— themacrdp.appbundle (Apple Silicon). Ad-hoc signed, so right-click → Open on first launch (or build a locally-notarized bundle withpackaging/make-app.sh). Includes the smart-card IFD handler + helpers.macrdp-v0.9.6-aarch64-apple-darwin.tar.gz— the baremacrdpbinary.SHA256SUMS—shasum -a 256 -c SHA256SUMSto verify.
Full narrative notes for every release: docs/release-history.md.
Full Changelog: v0.9.5...v0.9.6