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 085c2dd9e Pad BMP code points to four hex digits in 
UnicodeEscaper.toUtf16Escape (#1858)
085c2dd9e is described below

commit 085c2dd9e8ad82750e6d0cca0492d6bf2f0e16db
Author: alhuda <[email protected]>
AuthorDate: Tue Nov 3 19:01:36 2026 +0530

    Pad BMP code points to four hex digits in UnicodeEscaper.toUtf16Escape 
(#1858)
    
    The BMP branch of the protected toUtf16Escape hook returned "\\u" +
    Integer.toHexString, so code points below U+1000 produced short escapes
    such as \u41 that no \u reader decodes, while translate() pads the same
    code point through HEX_DIGITS. JavaUnicodeEscaper overrode the hook with
    the surrogate-pair form only and threw ArrayIndexOutOfBoundsException
    for every BMP code point.
    
    Left-pad the BMP hex to four digits and drop the JavaUnicodeEscaper
    override, which is redundant since the base method emits the
    surrogate-pair form itself. translate() output is unchanged.
---
 .../lang3/text/translate/JavaUnicodeEscaper.java   | 13 -------
 .../lang3/text/translate/UnicodeEscaper.java       |  4 ++-
 ...scaperTest.java => JavaUnicodeEscaperTest.java} | 42 +++++++---------------
 .../lang3/text/translate/UnicodeEscaperTest.java   | 13 +++++++
 4 files changed, 29 insertions(+), 43 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/lang3/text/translate/JavaUnicodeEscaper.java 
b/src/main/java/org/apache/commons/lang3/text/translate/JavaUnicodeEscaper.java
index 4ddca9ad4..0dbe5d7ed 100644
--- 
a/src/main/java/org/apache/commons/lang3/text/translate/JavaUnicodeEscaper.java
+++ 
b/src/main/java/org/apache/commons/lang3/text/translate/JavaUnicodeEscaper.java
@@ -91,17 +91,4 @@ public JavaUnicodeEscaper(final int below, final int above, 
final boolean betwee
         super(below, above, between);
     }
 
-    /**
-     * Converts the given code point to a hexadecimal string of the form 
{@code "\\uXXXX\\uXXXX"}
-     *
-     * @param codePoint
-     *            a Unicode code point.
-     * @return The hexadecimal string for the given code point.
-     */
-    @Override
-    protected String toUtf16Escape(final int codePoint) {
-        final char[] surrogatePair = Character.toChars(codePoint);
-        return "\\u" + hex(surrogatePair[0]) + "\\u" + hex(surrogatePair[1]);
-    }
-
 }
diff --git 
a/src/main/java/org/apache/commons/lang3/text/translate/UnicodeEscaper.java 
b/src/main/java/org/apache/commons/lang3/text/translate/UnicodeEscaper.java
index 64bff2819..6725fe50c 100644
--- a/src/main/java/org/apache/commons/lang3/text/translate/UnicodeEscaper.java
+++ b/src/main/java/org/apache/commons/lang3/text/translate/UnicodeEscaper.java
@@ -19,6 +19,8 @@
 import java.io.IOException;
 import java.io.Writer;
 
+import org.apache.commons.lang3.StringUtils;
+
 /**
  * Translates code points to their Unicode escaped value.
  *
@@ -112,7 +114,7 @@ protected UnicodeEscaper(final int below, final int above, 
final boolean between
      */
     protected String toUtf16Escape(final int codePoint) {
         if (Character.isBmpCodePoint(codePoint)) {
-            return "\\u" + hex(codePoint);
+            return "\\u" + StringUtils.leftPad(hex(codePoint), 4, '0');
         }
         final char[] surrogatePair = Character.toChars(codePoint);
         return "\\u" + hex(surrogatePair[0]) + "\\u" + hex(surrogatePair[1]);
diff --git 
a/src/test/java/org/apache/commons/lang3/text/translate/UnicodeEscaperTest.java 
b/src/test/java/org/apache/commons/lang3/text/translate/JavaUnicodeEscaperTest.java
similarity index 51%
copy from 
src/test/java/org/apache/commons/lang3/text/translate/UnicodeEscaperTest.java
copy to 
src/test/java/org/apache/commons/lang3/text/translate/JavaUnicodeEscaperTest.java
index 6d2094943..e4842cc14 100644
--- 
a/src/test/java/org/apache/commons/lang3/text/translate/UnicodeEscaperTest.java
+++ 
b/src/test/java/org/apache/commons/lang3/text/translate/JavaUnicodeEscaperTest.java
@@ -23,42 +23,26 @@
 import org.junit.jupiter.api.Test;
 
 /**
- * Tests for {@link org.apache.commons.lang3.text.translate.UnicodeEscaper}.
+ * Tests for {@link 
org.apache.commons.lang3.text.translate.JavaUnicodeEscaper}.
  */
 @Deprecated
-class UnicodeEscaperTest extends AbstractLangTest {
-
-    @Test
-    void testAbove() {
-        final UnicodeEscaper ue = UnicodeEscaper.above('F');
-        final String input = "ADFGZ";
-        final String result = ue.translate(input);
-        assertEquals("ADF\\u0047\\u005A", result, "Failed to escape Unicode 
characters via the above method");
-    }
-
-    @Test
-    void testBelow() {
-        final UnicodeEscaper ue = UnicodeEscaper.below('F');
-        final String input = "ADFGZ";
-        final String result = ue.translate(input);
-        assertEquals("\\u0041\\u0044FGZ", result, "Failed to escape Unicode 
characters via the below method");
-    }
-
-    @Test
-    void testBetween() {
-        final UnicodeEscaper ue = UnicodeEscaper.between('F', 'L');
-        final String input = "ADFGZ";
-        final String result = ue.translate(input);
-        assertEquals("AD\\u0046\\u0047Z", result, "Failed to escape Unicode 
characters via the between method");
-    }
+class JavaUnicodeEscaperTest extends AbstractLangTest {
 
     @Test
     void testSupplementary() {
-        final UnicodeEscaper ue = UnicodeEscaper.above(0x7f);
+        final JavaUnicodeEscaper jue = JavaUnicodeEscaper.above(0x7f);
         // U+10437 (DESERET SMALL LETTER YEE) encodes to surrogate pair U+D801 
U+DC37.
         final String input = new String(Character.toChars(0x10437));
-        final String result = ue.translate(input);
+        final String result = jue.translate(input);
         assertEquals("\\uD801\\uDC37", result, "Supplementary code point must 
escape to a surrogate pair");
-        assertEquals(input, new UnicodeUnescaper().translate(result), "Escaped 
supplementary code point must round-trip");
+        assertEquals("\\uD801\\uDC37", jue.toUtf16Escape(0x10437), 
"toUtf16Escape must emit the surrogate pair form");
+    }
+
+    @Test
+    void testToUtf16EscapeBmp() {
+        final JavaUnicodeEscaper jue = new JavaUnicodeEscaper(0, 
Integer.MAX_VALUE, true);
+        assertEquals("\\u0041", jue.toUtf16Escape('A'), "BMP code point must 
escape to a single \\uXXXX");
+        assertEquals("\\uFFFF", jue.toUtf16Escape(0xFFFF), "BMP code point 
must escape to a single \\uXXXX");
+        assertEquals(jue.translate("A"), jue.toUtf16Escape('A'), 
"toUtf16Escape must match the translate output");
     }
 }
diff --git 
a/src/test/java/org/apache/commons/lang3/text/translate/UnicodeEscaperTest.java 
b/src/test/java/org/apache/commons/lang3/text/translate/UnicodeEscaperTest.java
index 6d2094943..523addb2d 100644
--- 
a/src/test/java/org/apache/commons/lang3/text/translate/UnicodeEscaperTest.java
+++ 
b/src/test/java/org/apache/commons/lang3/text/translate/UnicodeEscaperTest.java
@@ -52,6 +52,19 @@ void testBetween() {
         assertEquals("AD\\u0046\\u0047Z", result, "Failed to escape Unicode 
characters via the between method");
     }
 
+    @Test
+    void testToUtf16EscapeBmp() {
+        final UnicodeEscaper ue = new UnicodeEscaper();
+        // A BMP code point below U+1000 needs zero padding to keep the four 
digit \\uXXXX form.
+        assertEquals("\\u0000", ue.toUtf16Escape(0), "Code point 0 must escape 
to four hex digits");
+        assertEquals("\\u000A", ue.toUtf16Escape('\n'), "Code point 0xA must 
escape to four hex digits");
+        assertEquals("\\u0041", ue.toUtf16Escape('A'), "Code point 0x41 must 
escape to four hex digits");
+        assertEquals("\\u0FFF", ue.toUtf16Escape(0xFFF), "Code point 0xFFF 
must escape to four hex digits");
+        assertEquals("\\uFFFF", ue.toUtf16Escape(0xFFFF), "Code point 0xFFFF 
must escape to four hex digits");
+        assertEquals(ue.translate("A"), ue.toUtf16Escape('A'), "toUtf16Escape 
must match the translate output");
+        assertEquals("A", new 
UnicodeUnescaper().translate(ue.toUtf16Escape('A')), "Escaped BMP code point 
must round-trip");
+    }
+
     @Test
     void testSupplementary() {
         final UnicodeEscaper ue = UnicodeEscaper.above(0x7f);

Reply via email to