Repository navigation
Validate the server's view and cursor shapes, and bound the client zoom - #67
Merged
Merged
Conversation
A server could send a StreamConfig whose view was tiny next to its stream, such as 2x2 for 1920x1080. The UI derives its integer zoom from the view, so that asked the decoder for a zoom in the hundreds, and the CPU tier then tried to allocate terabytes and aborted. Both StreamConfig paths now build their geometry through Config::new, which rejects a view that is zero, larger than the decoder limit, or less than half the stream. Servers send the full-quality size the stream is scaled from, so the factor is conservative slack. The worker clamps the zoom so a frame holds at most an 8K display's worth of pixels and no side past 8192. With the fixed GPU display ring and the bounded frame channel, a server can then cost at most what a real 8K session does. BgraFrame::zoomed uses checked arithmetic and reserves its buffer fallibly, showing the frame unzoomed when it cannot. A zoom the GPU decoder refused is not asked for again on every frame, and the display images no longer leak their VkImage and memory when allocation or binding fails. A StreamConfig that changes the stream size drops the zoom to 1, and the UI forgets its last request so it asks again for the new view. Cursor shapes are read only when the payload is exactly width*height*4 with both sides at most 1024. Anything else is skipped unread and passed on empty, which the UI already treats as a shape it cannot show. Shapes replace each other in a single slot instead of queueing on the status channel. remote_cursor refuses a hotspot outside the image, for which GTK returns no cursor that the bindings would wrap as a valid one. Tests run the real worker session on the CPU tier against a fake server over an in-memory stream, including a real encoded frame decoded at a clamped zoom.
[Medium impact] The PR appears safe to merge; no actionable issues were found. SummaryThe PR bounds server-supplied geometry and client zoom, and limits cursor memory use.
No actionable issues were found. Tests were inspected but not run.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A connected server could send a StreamConfig whose view was far smaller than its stream, for example 2x2 against 1920x1080. The client derives its integer decoder zoom from the view, so this asked for a zoom in the hundreds, and the CPU tier then tried to allocate terabytes and aborted. A server could also send a cursor hotspot outside the image. GTK returns no cursor for it, and the bindings wrap that NULL as a valid
gdk::Cursor, which is undefined behaviour in a release build. Cursor payloads of up to 64 MiB were copied and queued before any check.BgraFrame::zoomeduses checked arithmetic and reserves its buffer fallibly, showing the frame unzoomed when it cannot. A zoom the GPU refused is not retried every frame, andexportable_bgrafrees its image and memory on its error paths. A StreamConfig that changes the stream size drops the zoom to 1, and the UI asks again for the new view.remote_cursorrejects hotspots outside the image.Validation:
zoomed, and the hotspot bounds. Before the fix, the hotspot test panicked inside gdk4 and thezoomedtest aborted on the allocation.gliff-probe stream-benchon an AMD Radeon 840M laptop ran within a frame per second of the v0.4.0 probe on both tiers, with no errors.scripts/check.shpasses.This covers the client StreamConfig bounds that #29 lists as still open. It conflicts with #47 and #80 in the client. I am happy to rebase whichever lands second.
Opus 5.5 high, on behalf of TechLuddite.
Implemented with Claude Opus 5.5 at high effort and reviewed by GPT-6.1 (Codex) at high reasoning effort over four passes, then re-reviewed on 2026-10-19 by Claude, GPT-6.1 and Grok 4.7 at medium effort.