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 62f6edfd9 Keep chop from splitting a trailing surrogate pair (#1770)
62f6edfd9 is described below
commit 62f6edfd96008fd10cd22bf854cf4e8d2c008ae2
Author: alhuda <[email protected]>
AuthorDate: Wed Aug 12 21:11:19 2026 +0530
Keep chop from splitting a trailing surrogate pair (#1770)
---
src/main/java/org/apache/commons/lang3/StringUtils.java | 4 ++++
src/test/java/org/apache/commons/lang3/StringUtilsTest.java | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java
b/src/main/java/org/apache/commons/lang3/StringUtils.java
index 3feecd47a..aefc9aa4c 100644
--- a/src/main/java/org/apache/commons/lang3/StringUtils.java
+++ b/src/main/java/org/apache/commons/lang3/StringUtils.java
@@ -794,6 +794,10 @@ public static String chop(final String str) {
return EMPTY;
}
final int lastIdx = strLen - 1;
+ // keep the cut off the middle of a surrogate pair so the result is
never left holding a lone surrogate
+ if (splitsSurrogatePair(str, lastIdx)) {
+ return str.substring(0, lastIdx - 1);
+ }
final String ret = str.substring(0, lastIdx);
final char last = str.charAt(lastIdx);
if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsTest.java
b/src/test/java/org/apache/commons/lang3/StringUtilsTest.java
index 9bccaaf92..e27c9f90e 100644
--- a/src/test/java/org/apache/commons/lang3/StringUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/StringUtilsTest.java
@@ -399,6 +399,10 @@ void testChop() {
{null, null},
{"", ""},
{"a", ""},
+ // U+1F600: a trailing supplementary code point must be
dropped whole, not split into a lone surrogate
+ {"\uD83D\uDE00", ""},
+ {"x\uD83D\uDE00", "x"},
+ {"\uD83D\uDE00x", "\uD83D\uDE00"},
};
for (final String[] chopCase : chopCases) {
final String original = chopCase[0];