Harden paste process plugin pipeline and cap max non-file paste size input - #4701
Merged
guiyanakuang merged 2 commits intoJul 31, 2026
Merged
Conversation
guiyanakuang
deleted the
refactor/issue-4700-paste-plugin-pipeline-hardening
branch
July 31, 2026 09:04
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.
Closes #4700
Summary
Follow-up hardening after #4698 / #4699, in three parts:
Isolate plugin failures in
PasteReleaseService.releaseLocalPasteData. EachPasteProcessPlugin.processcall is now wrapped inrunCatching: on failure the plugin's transformation is skipped with a warning log and the pipeline continues with the current items. Previously a throwing plugin (e.g.FilesToImagesPluginon a failed file move) aborted the whole loop and left the paste row stuck in LOADING state forever. This is graceful degradation, not rollback — a plugin that failed mid-mutation may still leave its own item imperfect, but the row always reaches a terminal state.Document the plugin order invariants at the
pasteProcessPluginsassembly site inDesktopPasteComponentModule. The order is load-bearing and the constraints were previously only implicit — notablyDiscardOversizedNonFilePluginmust precedeDistinctPlugin(otherwiseFirstPluginmay keep an oversized first item and clear a smaller surviving variant from disk before the oversized one is discarded), plugins placed after the size check must never emit items larger than their already-checked sources, andSortPluginmust stay last because the first item determines the row's type/hash/search content. Mobile assembles the same commonMain plugins and must keep these invariants.Cap the
maxNonFilePasteSizesettings input to 1..64 MB. Without an upper bound the setting could effectively disable the oversized-item guard. TheCounterrule rejects out-of-range values from both the +/- buttons and typed input; the bound is UI-level validation only, consistent with sibling settings.Test plan
./gradlew app:compileKotlinDesktop app:compileTestKotlinDesktopclean./gradlew app:desktopTest --tests "*DiscardOversized*" --tests "*PasteReleaseService*"— 11 tests pass