PercentCodec decoder to disallow non-ASCII characters in input
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/net/PercentCodec.java b/httpcore5/src/main/java/org/apache/hc/core5/net/PercentCodec.java
index 3e17000..2a7f30b 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/net/PercentCodec.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/net/PercentCodec.java
@@ -236,7 +236,11 @@ static String decode(final CharSequence content, final Charset charset, final bo
             } else if (plusAsBlank && c == '+') {
                 bb.put((byte) ' ');
             } else {
-                bb.put((byte) c);
+                if (c > 0x7f) {
+                    bb.put((byte) '?');
+                } else {
+                    bb.put((byte) c);
+                }
             }
         }
         bb.flip();
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/net/TestPercentCodec.java b/httpcore5/src/test/java/org/apache/hc/core5/net/TestPercentCodec.java
index 7c1b72a..c6a2b04 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/net/TestPercentCodec.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/net/TestPercentCodec.java
@@ -116,4 +116,26 @@ void testPercentCodecEncodeIsNotRfc7639Canonical() {
         assertEquals("%7C", PercentCodec.encode("|", StandardCharsets.UTF_8));
     }
 
+    @Test
+    void decodeIllegalChars() {
+        assertEquals(
+                "1?2?3?4",
+                PercentCodec.decode("1\u012E2\u012E3\u012E4", StandardCharsets.UTF_8));
+    }
+
+    @Test
+    void testDecodeDoesNotCombineEscapedBytesAcrossLiteralCharacters() {
+        assertEquals(
+                "\uFFFDx\uFFFD",
+                PercentCodec.decode("%C3x%A4", StandardCharsets.UTF_8));
+    }
+
+    @Test
+    void testEncodeHonorsUtf16Charset() {
+        assertEquals(
+                "%FE%FF%00a%00b%00c",
+                PercentCodec.encode("abc", StandardCharsets.UTF_16));
+
+    }
+
 }