From dc88bd5f3e56e3b11ec73c5c7bb2138f9fe30d53 Mon Sep 17 00:00:00 2001 From: Javid Khan Date: Tue, 20 Oct 2026 14:05:44 +0530 Subject: [PATCH] reject sign characters in UnicodeUnescaper hex digits Integer.parseInt(s, 16) accepts a leading '+' or '-', so the four characters after \u were not required to be hex digits. \u-03C decoded to U+FFC4 and \u++03C decoded to '<'. Throw IllegalArgumentException for any non-hex character, as is already done for other malformed values. --- .../apache/commons/text/translate/UnicodeUnescaper.java | 9 ++++++++- .../commons/text/translate/UnicodeUnescaperTest.java | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/text/translate/UnicodeUnescaper.java b/src/main/java/org/apache/commons/text/translate/UnicodeUnescaper.java index 00b1298b83..b4ed585ab7 100644 --- a/src/main/java/org/apache/commons/text/translate/UnicodeUnescaper.java +++ b/src/main/java/org/apache/commons/text/translate/UnicodeUnescaper.java @@ -19,6 +19,8 @@ import java.io.IOException; import java.io.Writer; +import org.apache.commons.lang3.CharUtils; + /** * Translates escaped Unicode values of the form \\u+\d\d\d\d back to * Unicode. It supports multiple 'u' characters and will work with or @@ -54,7 +56,12 @@ public int translate(final CharSequence input, final int index, final Writer wri if (index + i + 4 <= input.length()) { // Get 4 hex digits final CharSequence unicode = input.subSequence(index + i, index + i + 4); - + // Integer.parseInt also accepts a leading sign, which is not a hex digit + for (int j = 0; j < unicode.length(); j++) { + if (!CharUtils.isHex(unicode.charAt(j))) { + throw new IllegalArgumentException("Unable to parse unicode value: " + unicode); + } + } try { final int value = Integer.parseInt(unicode.toString(), 16); writer.write((char) value); diff --git a/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java b/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java index 2879f56c1e..bb4e8e2dd3 100644 --- a/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java +++ b/src/test/java/org/apache/commons/text/translate/UnicodeUnescaperTest.java @@ -34,6 +34,14 @@ void testLessThanFour() { assertThrows(IllegalArgumentException.class, () -> escaper.translate(input)); } + @Test + void testSignNotHexDigit() { + final UnicodeUnescaper escaper = new UnicodeUnescaper(); + assertThrows(IllegalArgumentException.class, () -> escaper.translate("\\u-03C")); + assertThrows(IllegalArgumentException.class, () -> escaper.translate("\\u++03C")); + assertThrows(IllegalArgumentException.class, () -> escaper.translate("\\u+-03C")); + } + @Test void testTooShort() { assertThrows(IllegalArgumentException.class, () -> new UnicodeUnescaper().translate("\\u"));