Skip to content

fix: repair malformed percent escapes before Url.toUri()'s Uri hand-off#133

Merged
OmarAlJarrah merged 2 commits into
mainfrom
a4-touri-repair
Jul 19, 2026
Merged

fix: repair malformed percent escapes before Url.toUri()'s Uri hand-off#133
OmarAlJarrah merged 2 commits into
mainfrom
a4-touri-repair

Conversation

@OmarAlJarrah

Copy link
Copy Markdown
Member

Summary

  • Url.toUri() re-parsed the canonical href through the strict RFC 3986 Uri engine, which fatally rejects any % not followed by two hex digits. WHATWG's percent-encode sets never reserve % itself, so a Url can hold a bare or malformed escape (e.g. http://h/a%zzb, or a trailing http://h/a%) that parsed fine as a Url but threw converting to a Uri.
  • Url.relativize() calls toUri() internally and inherited the same failure.
  • Fixed by escaping any % that fails to introduce a valid %XX 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.

Test plan

  • ./gradlew :kuri:jvmTest (new regression tests for toUri() and relativize() using both issue repros pass; full suite green)
  • ./gradlew :kuri:ktlintCheck
  • ./gradlew :kuri:detekt
  • ./gradlew :kuri:jvmApiCheck and :kuri:klibApiCheck (no public API shape change; the full aggregate apiCheck also runs androidApiCheck, which fails to configure in this environment for an unrelated reason — no ANDROID_HOME/Android SDK available here)
  • ./gradlew :kuri:jsNodeTest
  • ./gradlew :kuri:macosArm64Test (native target compiles and passes)

Closes #103

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
@OmarAlJarrah
OmarAlJarrah merged commit bb3c1cd into main Jul 19, 2026
13 checks passed
@OmarAlJarrah
OmarAlJarrah deleted the a4-touri-repair branch July 19, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

kuri: Url.toUri() is not total, it throws for a well-formed Url whose href contains a literal percent sign

1 participant