Skip to content

Commit

Permalink
fix(independent-projects): throw IllegalArgumentException on failed U…
Browse files Browse the repository at this point in the history
…RL decoding

Previously, URLUtils.decode threw a RuntimeException when encountering invalid percent-encoded values.

Now, it throws an IllegalArgumentException, ensuring that malformed input is correctly recognized as a client error.

Test coverage added for:
- Invalid percent encoding (e.g., %zz, %2)
- Gray-area invalid UTF-8 cases (e.g., %80)
- Properly encoded values (e.g., %20, form-encoded +, Japanese characters)

Fixes quarkusio#46197

(cherry picked from commit ed6ec4b)
  • Loading branch information
Luis Rubiera authored and gsmet committed Feb 14, 2025
1 parent 8588d0d commit dfa9cda
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ public static String decode(String s, Charset enc, boolean decodeSlash, boolean
return s;
}

private static RuntimeException failedToDecodeURL(String s, Charset enc, Throwable o) {
return new RuntimeException("Failed to decode URL " + s + " to " + enc, o);
private static IllegalArgumentException failedToDecodeURL(String s, Charset enc, Throwable o) {
return new IllegalArgumentException("Failed to decode URL " + s + " to " + enc, o);
}

private static byte[] expandBytes(byte[] bytes) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.jboss.resteasy.reactive.common.util;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.nio.charset.StandardCharsets;

import org.junit.jupiter.api.Test;

class URLUtilsTest {
@Test
void decodeInvalidPercentEncoding() {
String incomplete = "invalid%2";
String invalidHex = "invalid%zz";

assertThrows(IllegalArgumentException.class,
() -> URLUtils.decode(incomplete, StandardCharsets.UTF_8, true, new StringBuilder()));
assertThrows(IllegalArgumentException.class,
() -> URLUtils.decode(invalidHex, StandardCharsets.UTF_8, true, new StringBuilder()));
}

@Test
void decodeGrayAreaInvalidUtf8() {
String invalidUtf8 = "invalid%80";

// This is a gray area: %80 is not valid in UTF-8 as a standalone byte,
// but Java's default decoding behavior does not throw an exception.
// Instead, it replaces it with a special character (�).
//
// To enforce strict decoding, CharsetDecoder with CodingErrorAction.REPORT
// should be used inside URLUtils.decode.
String decoded = URLUtils.decode(invalidUtf8, StandardCharsets.UTF_8, true, new StringBuilder());

assertEquals("invalid�", decoded); // Note: This may vary depending on the JVM.
}

@Test
void decodeValidValues() {
String path = "test%20path";
String formEncoded = "test+path";
String japanese = "%E3%83%86%E3%82%B9%E3%83%88"; // テスト

assertEquals("test path",
URLUtils.decode(path, StandardCharsets.UTF_8, true, new StringBuilder()));
assertEquals("test path",
URLUtils.decode(formEncoded, StandardCharsets.UTF_8, true, true, new StringBuilder()));
assertEquals("テスト",
URLUtils.decode(japanese, StandardCharsets.UTF_8, true, new StringBuilder()));
}
}

0 comments on commit dfa9cda

Please sign in to comment.