Repository navigation
Conversation
shoemoney
force-pushed
the
fix/header-name-case-fold-punctuation-collision
branch
2 times, most recently
from
September 17, 2026 07:43
2f15915 to
5bff062
Compare
shoemoney
force-pushed
the
fix/header-name-case-fold-punctuation-collision
branch
2 times, most recently
from
September 17, 2026 14:19
e99d093 to
f7fa0a3
Compare
shoemoney
force-pushed
the
fix/header-name-case-fold-punctuation-collision
branch
3 times, most recently
from
September 30, 2026 16:35
c45a300 to
7eb9988
Compare
Motivation:
compareCaseInsensitiveASCIIBytes(to:) in ByteCollectionUtils.swift folds
case by masking every byte with & 0xdf, clearing bit 0x20. That bit is
what separates an ASCII lowercase letter from its uppercase form, but it
is also the only bit separating five unrelated punctuation byte pairs
from one another: ^(0x5e)/~(0x7e), [(0x5b)/{(0x7b), ](0x5d)/}(0x7d),
\(0x5c)/|(0x7c), and @(0x40)/`(0x60). Masking a byte from any of the
right-hand column produces the same value as its left-hand partner, so
the comparison treats them as identical even though every one of these
ten bytes is a legal tchar character in an HTTP header field name per
RFC 7230 3.2.6, and is accepted as such by NIOHTTP1's own header name
validator. In practice this means two genuinely distinct header names,
e.g. X-Foo^Bar and X-Foo~Bar, compare equal, and the collision reaches
every HTTPHeaders API built on this comparison: first(name:), the
subscript family (including canonicalForm:), contains(name:), and
remove(name:).
Modifications:
Replace the unconditional & 0xdf mask with a small helper that only
clears bit 0x20 when the byte is actually an ASCII lowercase letter,
leaving every other byte untouched. The helper is a single UInt8(ascii:)
range switch, matching the idiom already used elsewhere in NIOHTTP1
(HTTPHeaderValidator.swift, HTTPHeaders+Validation.swift), so both the
fast withContiguousStorageIfAvailable loop and the elementsEqual
fallback stay branch-light.
Result:
Header names differing only by one of these five punctuation pairs are
no longer treated as equal, while ASCII letter case-folding is
unaffected. Added a byte-level test covering all five colliding pairs
plus same-byte and letter-case sanity checks, and an HTTPHeaders-level
test exercising the bug through first(name:), contains(name:),
subscript(canonicalForm:), and remove(name:). Both fail against the old
implementation and pass with the fix; the full NIOHTTP1Tests suite
passes.
Motivation: The comments incorrectly identify every tested punctuation byte as valid in HTTP header names, and two added tests need standard formatting. Modifications: Identify the valid caret/tilde header collision and describe the remaining pairs as general byte-comparison controls. Apply swift-format wrapping. Result: Regression coverage is documented accurately without changing behavior.
shoemoney
force-pushed
the
fix/header-name-case-fold-punctuation-collision
branch
from
October 5, 2026 09:08
7eb9988 to
502bafe
Compare
This branch has not been deployed
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.
Preserve distinct punctuation when comparing ASCII header names.
Motivation:
The unconditional
byte & 0xdfmask treats^and~as equal. Both are valid in HTTP header names, so looking up or removingX-Foo~Barcan incorrectly matchX-Foo^Bar.Modifications:
Fold only ASCII lowercase letters in both comparison paths. Add direct byte-comparison tests and an
HTTPHeadersregression covering lookup, containment, canonical values and removal. The other punctuation pairs in the comparator test are general byte-comparison controls; they are not all valid HTTP header characters.Result:
Distinct punctuation remains distinct while ASCII letters still compare without case sensitivity. No performance measurements are claimed.
Validation after rebasing onto
c1ccdbcc95c0: the two regressions produce nine failed assertions with current main and pass with this patch. All 333NIOHTTP1TestsXCTest tests and 33 Swift Testing tests pass on Apple Swift 6.4 / arm64. Strict formatting checks pass. The supported Swift/platform matrix still requires repository CI.