fix: repair malformed percent escapes before Url.toUri()'s Uri hand-off#133
Merged
Conversation
Url.toUri() re-parsed the canonical href through the strict RFC 3986 Uri engine, which treats a `%` not followed by two hex digits as a fatal error. WHATWG's percent-encode sets never reserve `%` itself, so a Url can legitimately carry a bare or malformed `%` escape (e.g. "http://h/a%zzb" or a trailing "http://h/a%") that parsed fine as a Url but blew up converting to a Uri. Url.relativize() calls toUri() internally and inherited the same failure. Escape any `%` that doesn't introduce a valid triplet to `%25` before handing the href to the Uri parser, leaving every already-valid triplet untouched, so toUri() is total for any valid Url. Closes #103
This was referenced Jul 19, 2026
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
Url.toUri()re-parsed the canonicalhrefthrough the strict RFC 3986Uriengine, which fatally rejects any%not followed by two hex digits. WHATWG's percent-encode sets never reserve%itself, so aUrlcan hold a bare or malformed escape (e.g.http://h/a%zzb, or a trailinghttp://h/a%) that parsed fine as aUrlbut threw converting to aUri.Url.relativize()callstoUri()internally and inherited the same failure.%that fails to introduce a valid%XXtriplet to%25before handing the href to theUriparser, leaving every already-valid triplet untouched, sotoUri()is total for any validUrl.Test plan
./gradlew :kuri:jvmTest(new regression tests fortoUri()andrelativize()using both issue repros pass; full suite green)./gradlew :kuri:ktlintCheck./gradlew :kuri:detekt./gradlew :kuri:jvmApiCheckand:kuri:klibApiCheck(no public API shape change; the full aggregateapiCheckalso runsandroidApiCheck, which fails to configure in this environment for an unrelated reason — noANDROID_HOME/Android SDK available here)./gradlew :kuri:jsNodeTest./gradlew :kuri:macosArm64Test(native target compiles and passes)Closes #103