-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Fix crash when URLDecodeException is thrown from parseUrl #5231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughparseUrl in URLUtils.kt now catches all Exceptions (previously only URLParserException), making it return null for any parsing error. A unit test was added to assert parseUrl returns null for a URL with an encoded embedded URL in a query parameter. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
ktor-http/common/test/io/ktor/tests/http/UrlTest.kt (1)
355-364: New malformed-URL regression case looks correctThe new assertion for
parseUrl("https://example.com?url=https%3A%2F%2Fwww.google.com%2")returningnullis consistent with the documented behavior ofparseUrl(“returnsnullotherwise”) and with the updated implementation that maps decoding failures tonull. This is a good targeted regression to cover theURLDecodeExceptionpath.If you ever touch this block again, consider switching all three
assertEquals(null, parseUrl(...))calls in this test toassertNull(...)for readability, but that’s purely optional and not required for this PR.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
ktor-http/common/src/io/ktor/http/URLUtils.kt(1 hunks)ktor-http/common/test/io/ktor/tests/http/UrlTest.kt(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.kt
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.kt: Follow Kotlin official style guide (https://kotlinlang.org/docs/coding-conventions.html)
Use star imports forio.ktor.*packages
Document all public APIs including parameters, return types, and exceptions
Mark internal APIs with@InternalAPIannotation
Run./gradlew lintKotlinand fix all linting issues before giving control back to the user
Use./gradlew formatKotlinto automatically fix formatting issues
Run./gradlew updateLegacyAbiafter making ABI changes to update ABI signature files
Binary compatibility is enforced - all public API changes must be tracked in the/api/directories
Validate ABI with./gradlew checkLegacyAbiand update with./gradlew updateLegacyAbi
API changes must be intentional and well-documented
Error handling follows Kotlin conventions with specific Ktor exceptions
Files:
ktor-http/common/test/io/ktor/tests/http/UrlTest.ktktor-http/common/src/io/ktor/http/URLUtils.kt
**/test/**/*.kt
📄 CodeRabbit inference engine (CLAUDE.md)
Follow test naming pattern:
DescribeWhatIsBeingTested
Files:
ktor-http/common/test/io/ktor/tests/http/UrlTest.kt
🧠 Learnings (2)
📚 Learning: 2025-11-25T09:38:19.393Z
Learnt from: CR
Repo: ktorio/ktor PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:38:19.393Z
Learning: Applies to **/*.kt : Error handling follows Kotlin conventions with specific Ktor exceptions
Applied to files:
ktor-http/common/src/io/ktor/http/URLUtils.kt
📚 Learning: 2025-09-30T07:52:14.769Z
Learnt from: yschimke
Repo: ktorio/ktor PR: 4013
File: ktor-client/ktor-client-android/jvm/src/io/ktor/client/engine/android/Android14URLConnectionFactory.kt:24-26
Timestamp: 2025-09-30T07:52:14.769Z
Learning: In the Ktor Android HTTP client engine (ktor-client-android), prefer using `URI.create(urlString).toURL()` over the `URL(urlString)` constructor when opening connections with Android's HttpEngine, as it avoids deprecated APIs and the different exception behavior (IllegalArgumentException vs MalformedURLException) is acceptable.
Applied to files:
ktor-http/common/src/io/ktor/http/URLUtils.kt
🧬 Code graph analysis (1)
ktor-http/common/test/io/ktor/tests/http/UrlTest.kt (1)
ktor-http/common/src/io/ktor/http/URLUtils.kt (1)
parseUrl(41-47)
URLBuilder.takeFrom has a catch (Throwable) but the build() method does a parameters.build() which can throw a URLDecodeException (and that is not a URLParserException so the parseUrl catch block wouldn't catch it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
ktor-http/common/src/io/ktor/http/URLUtils.kt (1)
41-46: parseUrl now safely handles decode failures without crashing callersCatching
Exceptionhere makesparseUrlrobust againstURLDecodeExceptionand other parsing-time failures, keeping its contract of returningnullon invalid/unsafely encoded URLs while avoiding the previous crash. This aligns with the intent of a “safe parse” helper and avoids the earlier problem of catchingThrowable.If you want to be stricter about not masking unexpected bugs, you could optionally narrow this to Ktor’s known parsing/decode exceptions, e.g.
URLParserExceptionandURLDecodeException, instead of allException, but the current change is already an improvement and consistent with the API docs. Based on learnings, error handling should generally rely on Ktor-specific exceptions where practical.ktor-http/common/test/io/ktor/tests/http/UrlTest.kt (1)
354-364: New parseUrl test case correctly validates behavior on invalid percent-encodingThe additional assertion covers the case where query decoding fails (truncated
%2), and verifies thatparseUrlnow returnsnullinstead of throwing, matching the updated error-handling behavior. This is a good regression test for the crash described in the PR.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
ktor-http/common/src/io/ktor/http/URLUtils.kt(1 hunks)ktor-http/common/test/io/ktor/tests/http/UrlTest.kt(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.kt
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.kt: Follow Kotlin official style guide (https://kotlinlang.org/docs/coding-conventions.html)
Use star imports forio.ktor.*packages
Document all public APIs including parameters, return types, and exceptions
Mark internal APIs with@InternalAPIannotation
Run./gradlew lintKotlinand fix all linting issues before giving control back to the user
Use./gradlew formatKotlinto automatically fix formatting issues
Run./gradlew updateLegacyAbiafter making ABI changes to update ABI signature files
Binary compatibility is enforced - all public API changes must be tracked in the/api/directories
Validate ABI with./gradlew checkLegacyAbiand update with./gradlew updateLegacyAbi
API changes must be intentional and well-documented
Error handling follows Kotlin conventions with specific Ktor exceptions
Files:
ktor-http/common/src/io/ktor/http/URLUtils.ktktor-http/common/test/io/ktor/tests/http/UrlTest.kt
**/test/**/*.kt
📄 CodeRabbit inference engine (CLAUDE.md)
Follow test naming pattern:
DescribeWhatIsBeingTested
Files:
ktor-http/common/test/io/ktor/tests/http/UrlTest.kt
🧠 Learnings (5)
📚 Learning: 2025-11-25T09:38:19.393Z
Learnt from: CR
Repo: ktorio/ktor PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:38:19.393Z
Learning: Applies to **/*.kt : Error handling follows Kotlin conventions with specific Ktor exceptions
Applied to files:
ktor-http/common/src/io/ktor/http/URLUtils.kt
📚 Learning: 2025-09-30T07:52:14.769Z
Learnt from: yschimke
Repo: ktorio/ktor PR: 4013
File: ktor-client/ktor-client-android/jvm/src/io/ktor/client/engine/android/Android14URLConnectionFactory.kt:24-26
Timestamp: 2025-09-30T07:52:14.769Z
Learning: In the Ktor Android HTTP client engine (ktor-client-android), prefer using `URI.create(urlString).toURL()` over the `URL(urlString)` constructor when opening connections with Android's HttpEngine, as it avoids deprecated APIs and the different exception behavior (IllegalArgumentException vs MalformedURLException) is acceptable.
Applied to files:
ktor-http/common/src/io/ktor/http/URLUtils.kt
📚 Learning: 2025-11-25T09:38:19.393Z
Learnt from: CR
Repo: ktorio/ktor PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:38:19.393Z
Learning: Applies to **/*.kt : Document all public APIs including parameters, return types, and exceptions
Applied to files:
ktor-http/common/src/io/ktor/http/URLUtils.kt
📚 Learning: 2025-06-23T12:49:56.883Z
Learnt from: CR
Repo: ktorio/ktor PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-06-23T12:49:56.883Z
Learning: Error handling should follow Kotlin conventions and use specific Ktor exceptions.
Applied to files:
ktor-http/common/src/io/ktor/http/URLUtils.kt
📚 Learning: 2025-06-09T07:09:43.170Z
Learnt from: bjhham
Repo: ktorio/ktor PR: 4916
File: ktor-server/ktor-server-plugins/ktor-server-di/common/src/io/ktor/server/plugins/di/DeferredDependencyMap.kt:16-24
Timestamp: 2025-06-09T07:09:43.170Z
Learning: In the `tryGetCompleted` extension function on `Deferred<T>` in ktor-server/ktor-server-plugins/ktor-server-di/common/src/io/ktor/server/plugins/di/DeferredDependencyMap.kt, exceptions should be thrown if the Deferred completed with an error. The "try" in the function name refers to trying to get a completed value non-blockingly, not to exception handling. The function should return null if not completed, the value if completed successfully, or throw the exception if completed with an error.
Applied to files:
ktor-http/common/src/io/ktor/http/URLUtils.kt
🧬 Code graph analysis (1)
ktor-http/common/test/io/ktor/tests/http/UrlTest.kt (1)
ktor-http/common/src/io/ktor/http/URLUtils.kt (1)
parseUrl(41-47)
|
@bjhham thanks for the approval! The test failures don't seem related, how should I proceed? |
|
Don't worry about the tests, we've got some flakiness problems atm. I'll just rerun them until they pass then merge 👍 |
URLBuilder.takeFrom has a catch (Throwable) but the build() method does a parameters.build() which can throw a URLDecodeException (and that is not a URLParserException so the parseUrl catch block wouldn't catch it
Subsystem
Common
Motivation
parseUrl should not crash my app
Solution
Catch the exception