This is an automated email from the ASF dual-hosted git repository.

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new f015a7ed9 reject hex letters in NumericEntityUnescaper decimal scan 
(#1739)
f015a7ed9 is described below

commit f015a7ed9934c5fcb73901c47420ef0005ec0af4
Author: alhuda <[email protected]>
AuthorDate: Sat Jul 4 00:29:45 2026 +0530

    reject hex letters in NumericEntityUnescaper decimal scan (#1739)
---
 .../commons/lang3/text/translate/NumericEntityUnescaper.java     | 6 ++++--
 .../commons/lang3/text/translate/NumericEntityUnescaperTest.java | 9 +++++++++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaper.java
 
b/src/main/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaper.java
index 00e94a024..d0ec84a5e 100644
--- 
a/src/main/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaper.java
+++ 
b/src/main/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaper.java
@@ -120,8 +120,10 @@ public int translate(final CharSequence input, final int 
index, final Writer out
                 }
             }
             int end = start;
-            // Note that this supports character codes without a ; on the end
-            while (end < seqEnd && CharUtils.isHex(input.charAt(end))) {
+            // Note that this supports character codes without a ; on the end.
+            // A decimal entity (&#...) only holds decimal digits; a-f are hex 
digits and must
+            // not be consumed here, otherwise the following text is swallowed 
into a failed parse.
+            while (end < seqEnd && (isHex ? CharUtils.isHex(input.charAt(end)) 
: CharUtils.isAsciiNumeric(input.charAt(end)))) {
                 end++;
             }
             final boolean semiNext = end != seqEnd && input.charAt(end) == ';';
diff --git 
a/src/test/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaperTest.java
 
b/src/test/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaperTest.java
index ccb02483b..1029e53c2 100644
--- 
a/src/test/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaperTest.java
+++ 
b/src/test/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaperTest.java
@@ -55,6 +55,15 @@ void testSupplementaryUnescaping() {
         assertEquals(expected, result, "Failed to unescape numeric entities 
supplementary characters");
     }
 
+    @Test
+    void testDecimalEntityFollowedByHexLetter() {
+        // A decimal entity ends at the first non-decimal character, so a 
following a-f letter is text, not part of the number.
+        final NumericEntityUnescaper neu = new 
NumericEntityUnescaper(NumericEntityUnescaper.OPTION.semiColonOptional);
+        assertEquals("0abc", neu.translate("&#48abc"), "Failed to stop a 
decimal entity at a trailing hex letter");
+        assertEquals("Test 0 not test", neu.translate("Test &#48 not test"), 
"Failed on a decimal entity terminated by a space");
+        assertEquals("0xyz", neu.translate("&#48xyz"), "Failed on a decimal 
entity terminated by a non-hex letter");
+    }
+
     @Test
     void testUnfinishedEntity() {
         // parse it

Reply via email to