docs(attachment): correct the defuse loop's termination argument - #4055
Open
dwin-gharibi wants to merge 1 commit into
Open
docs(attachment): correct the defuse loop's termination argument#4055dwin-gharibi wants to merge 1 commit into
dwin-gharibi wants to merge 1 commit into
Conversation
maxDefusePasses claimed "each pass strictly shortens the body (a match is always longer than nothing and is replaced by a constant)". That is false: delimiterPlaceholder is 41 bytes and `</document-x>` is 13, so a pass usually grows the body. Measured, the first pass on `</document-x>` takes it from 13 to 42 bytes. Termination actually comes from the placeholder containing neither < nor >, so it can never form part of a new match and every pass strictly reduces the count of delimiter-shaped tokens. The bound is belt-and-braces, not the guarantee. The defuseDelimiters comment was wrong in the other direction: it said `</TAG</TAG>>` collapses "only after the second pass". The pattern runs to the first >, so that prefix is a single match and collapses in one pass. Behavior is unchanged; only the reasoning was wrong, and it is the reasoning someone would rely on when tuning the constant. Adds a test pinning the real invariant, since a comment can drift again and a test cannot: it fails if the placeholder ever gains angle brackets, and checks adversarial bodies converge inside the bound with no live delimiter left.
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.
maxDefusePassesjustified its bound with "each pass strictly shortens the body". That is false —the placeholder is longer than the delimiters it replaces, so a pass usually grows the body.
The loop is fine; the stated reason it works is not.
Closes #4054.
Behaviour is unchanged
No production logic is touched. This corrects reasoning and adds a test that pins it.
What was wrong
One.
maxDefusePasses:delimiterPlaceholderis 41 bytes;</document-x>is 13. Measured:Two.
defuseDelimiters:envelopeTagReruns to the first>, so that whole prefix is one match and collapses in onepass. Verified: the residue shape is already stable after pass 1.
The real argument
delimiterPlaceholdercontains neither<nor>, so it can never form part of a new match.Every pass therefore strictly reduces the count of delimiter-shaped tokens in the body, and that
count is a non-negative integer — so the loop reaches a fixed point. The bound is belt-and-braces,
not the guarantee.
Why this matters more than a typo
defuseDelimitersreturns whatever it has when the bound is hit — silently, no error. Theplaceholder's character set is therefore load-bearing, and nothing said so. A cosmetic change to
something like
<removed>would break the invariant, let the loop exhaust its bound, and returna live delimiter inside the envelope — the exact break-out the escaping exists to prevent.
Tests
A comment can drift again; a test cannot.
defuse_convergence_test.goadds:TestDelimiterPlaceholderCannotFormAMatch— fails if the placeholder ever gains angle bracketsor starts matching
envelopeTagRe.TestDefuseDelimitersConverges— 15 adversarial bodies (deep nesting, split brackets, mixedcase, trailing attributes, self-closing, whitespace padding, prefix-extending tags, a body
pre-seeded with the placeholder). Each must reach a fixed point inside the bound and leave
no live delimiter. Convergence is asserted separately from survivor-freedom because hitting the
bound is silent, so a regression there would otherwise only surface much later as a break-out.
The tripwire was mutation-tested rather than assumed: setting
delimiterPlaceholder = "<docker-agent: envelope delimiter removed>"makes it fail withpkg/attachmentpasses andgo vetis clean.Confirmed not a security fix
Eighteen adversarial inputs were probed before filing; all were fully defused with zero survivors.
There is no break-out to fix here, and this PR should not be read as one.