8354490: Pattern.CANON_EQ causes a pattern to not match a string with a UNICODE variation

Reviewed-by: rriggs, naoto
This commit is contained in:
Xueming Shen 2025-07-01 00:58:43 +00:00
parent 9d518b3213
commit 61a590e9be
2 changed files with 16 additions and 4 deletions

View File

@ -4154,7 +4154,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
if (predicate.is(ch0))
return next.match(matcher, j, seq);
} else {
while (i + n < j) {
while (i + n <= j) {
String nfc = Normalizer.normalize(
seq.toString().substring(i, j), Normalizer.Form.NFC);
if (nfc.codePointCount(0, nfc.length()) == 1) {
@ -4163,13 +4163,10 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
return true;
}
}
ch0 = Character.codePointBefore(seq, j);
j -= Character.charCount(ch0);
}
}
if (j < matcher.to)
return false;
} else {
matcher.hitEnd = true;
}

View File

@ -2324,6 +2324,21 @@ public class RegExTest {
check(p, "test\u00e4\u0300\u0323", true);
Object[][] data = new Object[][] {
// JDK-8354490
// emoji + emoji_component pair forms a single grapheme but remains
// as 2 separate characters in nfc. match & find should still work with the
// CANON_EQ flag, as long as the character class is appropriately specified.
{"^[^/]*\\.[^/]*$", "\u2764\ufe0ffile.txt", "m", true},
{ "\\p{IsEmoji}", "ab\u2764\ufe0fcd", "f", true },
{ "[\\p{IsEmoji}]", "ab\u2764\ufe0fcd", "f", true },
{ "\\p{IsEmoji}\\p{IsEmoji_Component}", "\u2764\ufe0f", "m", true },
{ "[\\p{IsEmoji}\\p{IsEmoji_Component}]{2}", "\u2764\ufe0f", "m", true },
// greek with extra combining character
{"\\p{IsGreek}", "\u1f80\u0345", "f", true},
{"[\\p{IsGreek}]", "\u1f80\u0345", "f", true},
{"\\p{IsGreek}\\p{IsAlphabetic}", "\u1f80\u0345", "m", true},
{"\\p{IsAlphabetic}*", "\u1f80\u0345", "m", true},
{"[\\p{IsAlphabetic}]*", "\u1f80\u0345", "m", true},
// JDK-4867170
{ "[\u1f80-\u1f82]", "ab\u1f80cd", "f", true },