undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,267 @@
/*
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 4533872 4640853
* @summary Unit tests for supplementary character support (JSR-204) and Unicode 4.0 support
* @run junit Bug4533872
*/
import java.text.BreakIterator;
import java.util.Locale;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.fail;
public class Bug4533872 {
static final String[] given = {
/* Lu Nd Lu Ll */
"XYZ12345 ABCDE abcde",
/* Nd Lo Nd Lu Po Lu Ll */
"123\uD800\uDC00345 ABC\uFF61XYZ abc",
/* Nd Lo Nd Lu Po Lu Ll */
"123\uD800\uDC00345 ABC\uD800\uDD00XYZ abc",
/* Lu Ll Cs Ll Cs Lu Lo Lu */
"ABCabc\uDC00xyz\uD800ABC\uD800\uDC00XYZ",
};
// Golden data for TestNext(), TestBoundar() and TestPrintEach*ward()
static final String[][] expected = {
{"XYZ12345", " ", "ABCDE", " ", "abcde"},
{"123\uD800\uDC00345", " ", "ABC", "\uFF61", "XYZ", " ", "abc"},
{"123\uD800\uDC00345", " ", "ABC", "\uD800\uDD00", "XYZ", " ", "abc"},
{"ABCabc", "\uDC00", "xyz", "\uD800", "ABC\uD800\uDC00XYZ"},
};
BreakIterator iter;
int start, end, current;
/*
* Test for next(int n)
*/
@Test
void TestNext() {
iter = BreakIterator.getWordInstance(Locale.US);
for (int i = 0; i < given.length; i++) {
iter.setText(given[i]);
start = iter.first();
int j = expected[i].length - 1;
start = iter.next(j);
end = iter.next();
if (!expected[i][j].equals(given[i].substring(start, end))) {
fail("Word break failure: printEachForward() expected:<" +
expected[i][j] + ">, got:<" +
given[i].substring(start, end) +
"> start=" + start + " end=" + end);
}
}
}
/*
* Test for isBoundary(int n)
*/
@Test
void TestIsBoundary() {
iter = BreakIterator.getWordInstance(Locale.US);
for (int i = 0; i < given.length; i++) {
iter.setText(given[i]);
start = iter.first();
end = iter.next();
while (end < given[i].length()) {
if (!iter.isBoundary(end)) {
fail("Word break failure: isBoundary() This should be a boundary. Index=" +
end + " for " + given[i]);
}
end = iter.next();
}
}
}
/*
* The followig test cases were made based on examples in BreakIterator's
* API Doc.
*/
/*
* Test mainly for next() and current()
*/
@Test
void TestPrintEachForward() {
iter = BreakIterator.getWordInstance(Locale.US);
for (int i = 0; i < given.length; i++) {
iter.setText(given[i]);
start = iter.first();
// Check current()'s return value - should be same as first()'s.
current = iter.current();
if (start != current) {
fail("Word break failure: printEachForward() Unexpected current value: current()=" +
current + ", expected(=first())=" + start);
}
int j = 0;
for (end = iter.next();
end != BreakIterator.DONE;
start = end, end = iter.next(), j++) {
// Check current()'s return value - should be same as next()'s.
current = iter.current();
if (end != current) {
fail("Word break failure: printEachForward() Unexpected current value: current()=" +
current + ", expected(=next())=" + end);
}
if (!expected[i][j].equals(given[i].substring(start, end))) {
fail("Word break failure: printEachForward() expected:<" +
expected[i][j] + ">, got:<" +
given[i].substring(start, end) +
"> start=" + start + " end=" + end);
}
}
}
}
/*
* Test mainly for previous() and current()
*/
@Test
void TestPrintEachBackward() {
iter = BreakIterator.getWordInstance(Locale.US);
for (int i = 0; i < given.length; i++) {
iter.setText(given[i]);
end = iter.last();
// Check current()'s return value - should be same as last()'s.
current = iter.current();
if (end != current) {
fail("Word break failure: printEachBackward() Unexpected current value: current()=" +
current + ", expected(=last())=" + end);
}
int j;
for (start = iter.previous(), j = expected[i].length-1;
start != BreakIterator.DONE;
end = start, start = iter.previous(), j--) {
// Check current()'s return value - should be same as previous()'s.
current = iter.current();
if (start != current) {
fail("Word break failure: printEachBackward() Unexpected current value: current()=" +
current + ", expected(=previous())=" + start);
}
if (!expected[i][j].equals(given[i].substring(start, end))) {
fail("Word break failure: printEachBackward() expected:<" +
expected[i][j] + ">, got:<" +
given[i].substring(start, end) +
"> start=" + start + " end=" + end);
}
}
}
}
/*
* Test mainly for following() and previous()
*/
@Test
void TestPrintAt_1() {
iter = BreakIterator.getWordInstance(Locale.US);
int[][] index = {
{2, 8, 10, 15, 17},
{1, 8, 10, 12, 15, 17, 20},
{3, 8, 10, 13, 16, 18, 20},
{4, 6, 9, 10, 16},
};
for (int i = 0; i < given.length; i++) {
iter.setText(given[i]);
for (int j = index[i].length-1; j >= 0; j--) {
end = iter.following(index[i][j]);
start = iter.previous();
if (!expected[i][j].equals(given[i].substring(start, end))) {
fail("Word break failure: printAt_1() expected:<" +
expected[i][j] + ">, got:<" +
given[i].substring(start, end) +
"> start=" + start + " end=" + end);
}
}
}
}
/*
* Test mainly for preceding() and next()
*/
@Test
void TestPrintAt_2() {
iter = BreakIterator.getWordInstance(Locale.US);
int[][] index = {
{2, 9, 10, 15, 17},
{1, 9, 10, 13, 16, 18, 20},
{4, 9, 10, 13, 16, 18, 20},
{6, 7, 10, 11, 15},
};
for (int i = 0; i < given.length; i++) {
iter.setText(given[i]);
// Check preceding(0)'s return value - should equals BreakIterator.DONE.
if (iter.preceding(0) != BreakIterator.DONE) {
fail("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" +
iter.preceding(0));
}
for (int j = 0; j < index[i].length; j++) {
start = iter.preceding(index[i][j]);
end = iter.next();
if (!expected[i][j].equals(given[i].substring(start, end))) {
fail("Word break failure: printAt_2() expected:<" +
expected[i][j] + ">, got:<" +
given[i].substring(start, end) +
"> start=" + start + " end=" + end);
}
}
// Check next()'s return value - should equals BreakIterator.DONE.
end = iter.last();
start = iter.next();
if (start != BreakIterator.DONE) {
fail("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" + start);
}
}
}
}

View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 4740757
* @summary Confirm line-breaking behavior of Hangul
*/
import java.text.*;
import java.util.*;
public class Bug4740757 {
private static boolean err = false;
public static void main(String[] args) {
Locale defaultLocale = Locale.getDefault();
if (defaultLocale.getLanguage().equals("th")) {
Locale.setDefault(Locale.KOREA);
test4740757();
Locale.setDefault(defaultLocale);
} else {
test4740757();
}
if (err) {
throw new RuntimeException("Incorrect Line-breaking");
}
}
private static void test4740757() {
String source = "\uc548\ub155\ud558\uc138\uc694? \uc88b\uc740 \uc544\uce68, \uc5ec\ubcf4\uc138\uc694! \uc548\ub155. End.";
String expected = "\uc548/\ub155/\ud558/\uc138/\uc694? /\uc88b/\uc740 /\uc544/\uce68, /\uc5ec/\ubcf4/\uc138/\uc694! /\uc548/\ub155. /End./";
BreakIterator bi = BreakIterator.getLineInstance(Locale.KOREAN);
bi.setText(source);
int start = bi.first();
int end = bi.next();
StringBuilder sb = new StringBuilder();
for (; end != BreakIterator.DONE; start = end, end = bi.next()) {
sb.append(source.substring(start,end));
sb.append('/');
}
if (!expected.equals(sb.toString())) {
System.err.println("Failed: Hangul line-breaking failed." +
"\n\tExpected: " + expected +
"\n\tGot: " + sb +
"\nin " + Locale.getDefault() + " locale.");
err = true;
}
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 4912404
* @summary Confirm that BreakIterator.equals(null) return false.
*/
import java.text.BreakIterator;
public class Bug4912404 {
public static void main(String[] args) {
BreakIterator b = BreakIterator.getWordInstance();
b.setText("abc");
if (b.equals(null)) {
throw new RuntimeException("BreakIterator.equals(null) should return false.");
}
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @run main/timeout=60 Bug4932583
* @bug 4932583
* @summary Confirm that BreakIterator doesn't get caught in an infinite loop.
*/
import java.text.*;
import java.util.*;
import java.io.*;
public class Bug4932583 {
public static void main(String[] args) {
BreakIterator iterator = BreakIterator.getCharacterInstance();
iterator.setText("\uDB40\uDFFF");
int boundary = iterator.next();
}
}

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6513074
* @summary Confirm that JIS X 0213 characters are processed in line-breaking properly.
*/
import java.text.*;
import java.util.*;
public class Bug6513074 {
private static final String[][] source = {
{"\ufa30\ufa31 \ufa69\ufa6a",
"JIS X 0213 compatibility additions (\\uFA30-\\uFA6A)"},
};
private static final String[] expected_line = {
"\ufa30/\ufa31 /\ufa69/\ufa6a/",
};
private static final String[] expected_word = {
"\ufa30\ufa31/ /\ufa69\ufa6a/",
};
private static final String[] expected_char = {
"\ufa30/\ufa31/ /\ufa69/\ufa6a/",
};
private static boolean err = false;
public static void main(String[] args) {
Locale defaultLocale = Locale.getDefault();
if (defaultLocale.getLanguage().equals("th")) {
Locale.setDefault(Locale.JAPAN);
test6513074();
Locale.setDefault(defaultLocale);
} else {
test6513074();
}
if (err) {
throw new RuntimeException("Failed: Incorrect Text-breaking.");
}
}
private static void test6513074() {
BreakIterator bi = BreakIterator.getLineInstance(Locale.JAPAN);
for (int i = 0; i < source.length; i++) {
testBreakIterator(bi, "Line", source[i][0], expected_line[i], source[i][1]);
}
bi = BreakIterator.getWordInstance(Locale.JAPAN);
for (int i = 0; i < source.length; i++) {
testBreakIterator(bi, "Word", source[i][0], expected_word[i], source[i][1]);
}
bi = BreakIterator.getCharacterInstance(Locale.JAPAN);
for (int i = 0; i < source.length; i++) {
testBreakIterator(bi, "Character", source[i][0], expected_char[i], source[i][1]);
}
}
private static void testBreakIterator(BreakIterator bi,
String type,
String source,
String expected,
String description) {
bi.setText(source);
int start = bi.first();
int end = bi.next();
StringBuilder sb = new StringBuilder();
for (; end != BreakIterator.DONE; start = end, end = bi.next()) {
sb.append(source.substring(start,end));
sb.append('/');
}
if (!expected.equals(sb.toString())) {
System.err.println("Failed: Incorrect " + type + "-breaking for " +
description +
"\n\tExpected: " + toString(expected) +
"\n\tGot: " + toString(sb.toString()));
err = true;
}
}
private static String toString(String s) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
sb.append(" 0x" + Integer.toHexString(s.charAt(i)));
}
return sb.toString();
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7104012
* @summary Confirm that AIOBE is not thrown.
*/
import java.text.*;
import java.util.*;
public class Bug7104012 {
public static void main(String[] args) {
boolean err = false;
List<String> data = new ArrayList<>();
data.add("\udb40");
data.add(" \udb40");
data.add("\udc53");
data.add(" \udc53");
data.add(" \udb40\udc53");
data.add("\udb40\udc53");
data.add("ABC \udb40\udc53 123");
data.add("\udb40\udc53 ABC \udb40\udc53");
for (Locale locale : Locale.getAvailableLocales()) {
List<BreakIterator> breakIterators = new ArrayList<>();
breakIterators.add(BreakIterator.getCharacterInstance(locale));
breakIterators.add(BreakIterator.getLineInstance(locale));
breakIterators.add(BreakIterator.getSentenceInstance(locale));
breakIterators.add(BreakIterator.getWordInstance(locale));
for (BreakIterator bi : breakIterators) {
for (String str : data) {
try {
bi.setText(str);
bi.first();
while (bi.next() != BreakIterator.DONE) { }
bi.last();
while (bi.previous() != BreakIterator.DONE) { }
}
catch (ArrayIndexOutOfBoundsException ex) {
System.out.println(" " + data.indexOf(str)
+ ": BreakIterator(" + locale
+ ") threw AIOBE.");
err = true;
}
}
}
}
if (err) {
throw new RuntimeException("Unexpected exception.");
}
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8032446
* @summary Confirm that BreakIterator works as expected with new characters in Unicode 7.
*/
import java.text.*;
import java.util.*;
public class Bug8032446 {
public static void main(String[] args) {
boolean err = false;
StringBuilder sb = new StringBuilder();
for (int i = 0x10860; i <= 0x10876; i++) { // Palmyrene Letters
sb.append(Character.toChars(i));
}
sb.append(" ");
for (int i = 0x10879; i <= 0x1087D; i++) { // Palmyrene Numbers
sb.append(Character.toChars(i));
}
String s = sb.toString();
BreakIterator bi = BreakIterator.getWordInstance(Locale.ROOT);
bi.setText(s);
bi.first();
if (bi.next() != s.indexOf(' ')) {
throw new RuntimeException("Unexpected word breaking.");
}
}
}

View file

@ -0,0 +1,154 @@
/*
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6521742
* @summary test exceptions
*/
import java.text.*;
import java.util.*;
import static java.text.BreakIterator.DONE;
public class ExceptionTest {
private static final String text =
"An ordered collection (also known as a sequence). "
+ "The user of this interface has precise control over "
+ "where in the list each element is inserted. "
+ "The user can access elements by their integer index (position in the list), "
+ "and search for elements in the list.";
public static void main(String[] args) {
BreakIterator bi = BreakIterator.getWordInstance();
bi.setText(text);
MirroredBreakIterator mirror = new MirroredBreakIterator(bi);
final int first = bi.first();
if (first != 0) {
throw new RuntimeException("first != 0: " + first);
}
final int last = bi.last();
bi = BreakIterator.getWordInstance();
bi.setText(text);
int length = text.length();
/*
* following(int)
*/
for (int i = 0; i <= length; i++) {
if (i == length) {
check(bi.following(i), DONE);
}
check(bi.following(i), mirror.following(i));
check(bi.current(), mirror.current());
}
for (int i = -length; i < 0; i++) {
checkFollowingException(bi, i);
checkFollowingException(mirror, i);
check(bi.current(), mirror.current());
}
for (int i = 1; i < length; i++) {
checkFollowingException(bi, length + i);
checkFollowingException(mirror, length + i);
check(bi.current(), mirror.current());
}
/*
* preceding(int)
*/
for (int i = length; i >= 0; i--) {
if (i == 0) {
check(bi.preceding(i), DONE);
}
check(bi.preceding(i), mirror.preceding(i));
check(bi.current(), mirror.current());
}
for (int i = -length; i < 0; i++) {
checkPrecedingException(bi, i);
checkPrecedingException(mirror, i);
check(bi.current(), mirror.current());
}
for (int i = 1; i < length; i++) {
checkPrecedingException(bi, length + i);
checkPrecedingException(mirror, length + i);
check(bi.current(), mirror.current());
}
/*
* isBoundary(int)
*/
for (int i = 0; i <= length; i++) {
check(bi.isBoundary(i), mirror.isBoundary(i));
check(bi.current(), mirror.current());
}
for (int i = -length; i < 0; i++) {
checkIsBoundaryException(bi, i);
checkIsBoundaryException(mirror, i);
}
for (int i = 1; i < length; i++) {
checkIsBoundaryException(bi, length + i);
checkIsBoundaryException(mirror, length + i);
}
}
private static void check(int i1, int i2) {
if (i1 != i2) {
throw new RuntimeException(i1 + " != " + i2);
}
}
private static void check(boolean b1, boolean b2) {
if (b1 != b2) {
throw new RuntimeException(b1 + " != " + b2);
}
}
private static void checkFollowingException(BreakIterator bi, int offset) {
try {
bi.following(offset);
} catch (IllegalArgumentException e) {
return; // OK
}
throw new RuntimeException(bi + ": following() doesn't throw an IAE with offset "
+ offset);
}
private static void checkPrecedingException(BreakIterator bi, int offset) {
try {
bi.preceding(offset);
} catch (IllegalArgumentException e) {
return; // OK
}
throw new RuntimeException(bi + ": preceding() doesn't throw an IAE with offset "
+ offset);
}
private static void checkIsBoundaryException(BreakIterator bi, int offset) {
try {
bi.isBoundary(offset);
} catch (IllegalArgumentException e) {
return; // OK
}
throw new RuntimeException(bi + ": isBoundary() doesn't throw an IAE with offset "
+ offset);
}
}

View file

@ -0,0 +1,166 @@
/*
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.text.BreakIterator;
import java.text.CharacterIterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public class MirroredBreakIterator extends BreakIterator {
private final List<Integer> boundaries;
private int charIndex;
private int boundaryIndex;
MirroredBreakIterator(BreakIterator bi) {
List<Integer> b = new ArrayList<Integer>();
int i = bi.first();
charIndex = i;
for (; i != DONE; i = bi.next()) {
b.add(i);
}
boundaries = Collections.unmodifiableList(b);
}
@Override
public Object clone() {
try {
return super.clone();
} catch (Exception e) {
throw new RuntimeException("clone failed", e);
}
}
@Override
public int first() {
return changeIndices(0);
}
@Override
public int last() {
return changeIndices(boundaries.size() - 1);
}
@Override
public int next(int n) {
if (n == 0) {
return current();
}
int newBoundary = boundaryIndex + n;
if (newBoundary < 0) {
first();
return DONE;
}
if (newBoundary > lastBoundary()) {
last();
return DONE;
}
return changeIndices(newBoundary);
}
@Override
public int next() {
if (boundaryIndex == lastBoundary()) {
return DONE;
}
return changeIndices(boundaryIndex + 1);
}
@Override
public int previous() {
if (boundaryIndex == 0) {
return DONE;
}
return changeIndices(boundaryIndex - 1);
}
@Override
public int following(int offset) {
validateOffset(offset);
for (int b = 0; b <= lastBoundary(); b++) {
int i = boundaries.get(b);
if (i > offset) {
return changeIndices(i, b);
}
}
return DONE;
}
@Override
public int preceding(int offset) {
validateOffset(offset);
for (int b = lastBoundary(); b >= 0; b--) {
int i = boundaries.get(b);
if (i < offset) {
return changeIndices(i, b);
}
}
return DONE;
}
@Override
public boolean isBoundary(int offset) {
// Call the default implementation in BreakIterator
return super.isBoundary(offset);
}
@Override
public int current() {
return charIndex;
}
@Override
public CharacterIterator getText() {
throw new UnsupportedOperationException();
}
@Override
public void setText(CharacterIterator newText) {
throw new UnsupportedOperationException();
}
private int lastBoundary() {
return boundaries.size() - 1;
}
private int changeIndices(int newCharIndex, int newBoundary) {
boundaryIndex = newBoundary;
return charIndex = newCharIndex;
}
private int changeIndices(int newBoundary) {
try {
return changeIndices(boundaries.get(newBoundary), newBoundary);
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException(e);
}
}
private void validateOffset(int offset) {
if (offset < boundaries.get(0) || offset > boundaries.get(lastBoundary())) {
throw new IllegalArgumentException();
}
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @summary test Comparison of New Collators against Old Collators in the en_US locale
* @modules jdk.localedata
*/
import java.io.*;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Locale;
import java.text.BreakIterator;
import java.lang.Math;
public class NewVSOld_th_TH {
public static void main(String args[]) throws FileNotFoundException,
UnsupportedEncodingException,
IOException {
final String ENCODING = "UTF-8";
final Locale THAI_LOCALE = Locale.of("th", "TH");
String rawFileName = "test_th_TH.txt";
String oldFileName = "broken_th_TH.txt";
StringBuilder rawText = new StringBuilder();
StringBuilder oldText = new StringBuilder();
StringBuilder cookedText = new StringBuilder();
File f;
f = new File(System.getProperty("test.src", "."), rawFileName);
try (InputStreamReader rawReader =
new InputStreamReader(new FileInputStream(f), ENCODING)) {
int c;
while ((c = rawReader.read()) != -1) {
rawText.append((char) c);
}
}
f = new File(System.getProperty("test.src", "."), oldFileName);
try (InputStreamReader oldReader =
new InputStreamReader(new FileInputStream(f), ENCODING)) {
int c;
while ((c = oldReader.read()) != -1) {
oldText.append((char) c);
}
}
BreakIterator breakIterator = BreakIterator.getWordInstance(THAI_LOCALE);
breakIterator.setText(rawText.toString());
int start = breakIterator.first();
for (int end = breakIterator.next();
end != BreakIterator.DONE;
start = end, end = breakIterator.next()) {
cookedText.append(rawText.substring(start, end));
cookedText.append("\n");
}
String cooked = cookedText.toString();
String old = oldText.toString();
if (cooked.compareTo(old) != 0) {
throw new RuntimeException("Text not broken the same as with the old BreakIterators");
}
}
}

View file

@ -0,0 +1,13 @@
การ
เก็บ
ภาษีประเทศ
ไทยและ
ประเทศ
เดนมาร์ค
อนุสัญญา
ระหว่าง
รัฐบาล
แห่ง
ประเทศ
ไทย
กับ

View file

@ -0,0 +1 @@
การเก็บภาษีประเทศไทยและประเทศเดนมาร์คอนุสัญญาระหว่างรัฐบาลแห่งประเทศไทยกับ