fix: harden persistence, capture safety, and configurator validation - #338
Merged
Conversation
Create redo added an enumerate offset on top of already-final indices, so pasting or duplicating two shapes and then undoing/redoing panicked. Delete undo used the same offset, which restacked non-adjacent shapes in the wrong order.
In-place text edit clears the stored string and keeps the live buffer in DrawingState. Autosave, shutdown, and output-switch snapshots read the frame directly, so a pause or quit during editing wrote empty text. Snapshot through the existing cancel-and-restore helper, and defer autosave while text input is active.
Portal captures are full-desktop images. Cropping with logical * this output's scale picks the wrong pixels on mixed-DPI layouts, and zoom kept the uncropped desktop when that crop missed.
The renderer fills a circle at each stylus sample, but FreehandPressure hit testing only walked segments, so a single-point tap could not be selected.
Filename templates and format strings were joined onto the save directory, so a value with / or .. could write outside it. Require a single path component, allowlist the extension, and reject the same escapes in the configurator.
Portal capture accepted any file:// URI, followed symlinks, and deleted the target. Read only regular files under $XDG_RUNTIME_DIR or the portal cache, with O_NOFOLLOW and a 256 MiB cap.
URI-list paste used metadata() and a following open, so a symlink to a regular file was treated as the image. lstat and O_NOFOLLOW keep the paste on the named file.
Config loading read the whole file into memory. Cap both the typed load and the lossless document path at 2 MiB, matching the session snapshot size-guard pattern.
BoardsDraft rebuilt BoardsConfig from defaults, so a save dropped pan_enabled and show_pan_badge. Keep those fields on the draft so an existing false value survives a round trip.
Save used to parse any number and let validate_and_clamp rewrite it. Drawing, arrow, and history fields now reject the same ranges the UI already shows, and a remaining clamp still blocks the write so keybinding arbitration can keep saving.
Comma-splitting accepted any token, so an unparseable shortcut reached save and was dropped by validate_and_clamp. Parse each entry with KeyBinding and mark the row so Save cannot write a binding the overlay would ignore.
An empty Apply Shortcut field used to write Super+g or Ctrl+Shift+g. Treat blank input as an error so a cleared field cannot bind a default the user did not type.
Hiding a GtkStackPage before selecting the next one lets GTK fall back to another child. Match the keybindings page: show needed pages, select the model tab, then hide the rest.
KeybindingField kept its own title strings, so overlay and configurator names drifted. Look up each field's Action and use action_label, and search the same metadata aliases so terms like eyedropper still find the row.
Capture, Performance, Daemon, Arrow, Render Profiles, Tablet, Help Overlay, and Presenter Mode had no screen token, so overlay and tray could not land there. Add the missing destinations and keep help, parse, and the configurator match in sync.
Dropping the JoinHandle after the deadline detaches GTK's main loop. Leak the handle instead so a stuck thread is not abandoned while the process is still running.
A capture with no target output used to apply to whichever output was active, and ARGB crop sizes could wrap before the allocation. Require both sides of the output id, and use checked arithmetic for the crop buffer.
Stale Phase 2 dead_code allows hid live capture types, and silent onboarding saves hid migrate/recover failures. Document the Cairo buffer casts and keep mixed-DPI geometry helpers available for tests.
--open tablet and the help list advertised a tab that does not exist without the feature. Keep the destination, help text, and parse table behind the same gate.
Save now rejects unparseable keybindings before writing. Cover that the document stays and the field error is shown, instead of only checking a warning status.
The Screenshot portal does not promise a temp directory, so refusing paths outside $XDG_RUNTIME_DIR broke legitimate captures. Keep O_NOFOLLOW and the size cap, and delete only files under the runtime dir or portal cache.
Forgetting the JoinHandle at the deadline leaked a handle that could never be joined. Drop it so the OS can reap the thread if it later finishes.
A monitor added, moved, or destroyed to the left used to leave a stale screenshot origin. Recompute on add and update, and exclude the dying output in output_destroyed because SCTK 0.20 still lists it.
Portal tasks snapshot crop geometry before the screenshot returns, and output-id matching misses a monitor added or moved to the left. Track a layout generation, fail closed on an unknown origin unless the image is this output's size, and discard stale results.
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.
Summary
invalid values, and opening clipboard and portal files without following symlinks.
file://responses from any location while deleting files only from known portal temporary roots.