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:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
|
|
@ -0,0 +1,462 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 5102289 6278334 8261179
|
||||
* @summary Test the default Control implementation. The expiration
|
||||
* functionality of newBundle, getTimeToLive, and needsReload is
|
||||
* tested by ExpirationTest.sh. The factory methods are tested
|
||||
* separately.
|
||||
* @build TestResourceRB
|
||||
* @build NonResourceBundle
|
||||
* @run main DefaultControlTest
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import static java.util.ResourceBundle.Control.*;
|
||||
|
||||
public class DefaultControlTest {
|
||||
// The ResourceBundle.Control instance
|
||||
static final ResourceBundle.Control CONTROL
|
||||
= ResourceBundle.Control.getControl(FORMAT_DEFAULT);
|
||||
|
||||
static final ResourceBundle BUNDLE = new ResourceBundle() {
|
||||
public Enumeration<String> getKeys() { return null; }
|
||||
protected Object handleGetObject(String key) { return null; }
|
||||
};
|
||||
|
||||
static final String CLAZZ = FORMAT_CLASS.get(0);
|
||||
|
||||
static final String PROPERTIES = FORMAT_PROPERTIES.get(0);
|
||||
|
||||
static final ClassLoader LOADER = DefaultControlTest.class.getClassLoader();
|
||||
|
||||
// Full arguments for NPE testing
|
||||
static final Object[] FULLARGS = { "any",
|
||||
Locale.US,
|
||||
FORMAT_PROPERTIES.get(0),
|
||||
LOADER,
|
||||
BUNDLE };
|
||||
|
||||
static int errors;
|
||||
|
||||
public static void main(String[] args) {
|
||||
checkConstants();
|
||||
|
||||
// Test getFormats(String)
|
||||
testGetFormats();
|
||||
|
||||
// Test getCandidateLocales(String, Locale)
|
||||
testGetCandidateLocales();
|
||||
|
||||
// Test getFallbackLocale(String, Locale)
|
||||
testGetFallbackLocale();
|
||||
|
||||
// Test newBundle(String, Locale, String, ClassLoader, boolean)
|
||||
testNewBundle();
|
||||
|
||||
// Test toBundleName(String, Locale)
|
||||
testToBundleName();
|
||||
|
||||
// Test getTimeToLive(String, Locale)
|
||||
testGetTimeToLive();
|
||||
|
||||
// Test needsReload(String, Locale, String, ClassLoader,
|
||||
// ResourceBundle, long)
|
||||
testNeedsReload();
|
||||
|
||||
// Test toResourceName(String, String)
|
||||
testToResourceName();
|
||||
|
||||
if (errors > 0) {
|
||||
throw new RuntimeException("FAILED: " + errors + " error(s)");
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkConstants() {
|
||||
// Check FORMAT_*
|
||||
if (!CONTROL.FORMAT_DEFAULT.equals(Arrays.asList("java.class",
|
||||
"java.properties"))) {
|
||||
error("Wrong Control.FORMAT_DEFAULT");
|
||||
}
|
||||
checkImmutableList(CONTROL.FORMAT_DEFAULT);
|
||||
if (!CONTROL.FORMAT_CLASS.equals(Arrays.asList("java.class"))) {
|
||||
error("Wrong Control.FORMAT_CLASS");
|
||||
}
|
||||
checkImmutableList(CONTROL.FORMAT_CLASS);
|
||||
if (!CONTROL.FORMAT_PROPERTIES.equals(Arrays.asList("java.properties"))) {
|
||||
error("Wrong Control.FORMAT_PROPERTIES");
|
||||
}
|
||||
checkImmutableList(CONTROL.FORMAT_PROPERTIES);
|
||||
|
||||
// Check TTL_*
|
||||
if (CONTROL.TTL_DONT_CACHE != -1) {
|
||||
error("Wrong Control.TTL_DONT_CACHE: %d%n", CONTROL.TTL_DONT_CACHE);
|
||||
}
|
||||
if (CONTROL.TTL_NO_EXPIRATION_CONTROL != -2) {
|
||||
error("Wrong Control.TTL_NO_EXPIRATION_CONTROL: %d%n",
|
||||
CONTROL.TTL_NO_EXPIRATION_CONTROL);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkImmutableList(List<String> list) {
|
||||
try {
|
||||
list.add("hello");
|
||||
error("%s is mutable%n", list);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private static void testGetFormats() {
|
||||
List<String> list = CONTROL.getFormats("foo");
|
||||
if (list != CONTROL.FORMAT_DEFAULT) {
|
||||
error("getFormats returned " + list);
|
||||
}
|
||||
try {
|
||||
list = CONTROL.getFormats(null);
|
||||
error("getFormats doesn't throw NPE.");
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private static void testGetCandidateLocales() {
|
||||
Map<Locale, Locale[]> candidateData = new HashMap<Locale, Locale[]>();
|
||||
candidateData.put(Locale.of("ja", "JP", "YOK"), new Locale[] {
|
||||
Locale.of("ja", "JP", "YOK"),
|
||||
Locale.of("ja", "JP"),
|
||||
Locale.of("ja"),
|
||||
Locale.ROOT });
|
||||
candidateData.put(Locale.of("ja", "JP"), new Locale[] {
|
||||
Locale.of("ja", "JP"),
|
||||
Locale.of("ja"),
|
||||
Locale.ROOT });
|
||||
candidateData.put(Locale.of("ja"), new Locale[] {
|
||||
Locale.of("ja"),
|
||||
Locale.ROOT });
|
||||
|
||||
candidateData.put(Locale.of("ja", "", "YOK"), new Locale[] {
|
||||
Locale.of("ja", "", "YOK"),
|
||||
Locale.of("ja"),
|
||||
Locale.ROOT });
|
||||
candidateData.put(Locale.of("", "JP", "YOK"), new Locale[] {
|
||||
Locale.of("", "JP", "YOK"),
|
||||
Locale.of("", "JP"),
|
||||
Locale.ROOT });
|
||||
candidateData.put(Locale.of("", "", "YOK"), new Locale[] {
|
||||
Locale.of("", "", "YOK"),
|
||||
Locale.ROOT });
|
||||
candidateData.put(Locale.of("", "JP"), new Locale[] {
|
||||
Locale.of("", "JP"),
|
||||
Locale.ROOT });
|
||||
candidateData.put(Locale.ROOT, new Locale[] {
|
||||
Locale.ROOT });
|
||||
|
||||
// Norwegian Bokmal
|
||||
candidateData.put(Locale.forLanguageTag("nb-NO-POSIX"), new Locale[] {
|
||||
Locale.forLanguageTag("nb-NO-POSIX"),
|
||||
Locale.forLanguageTag("no-NO-POSIX"),
|
||||
Locale.forLanguageTag("nb-NO"),
|
||||
Locale.forLanguageTag("no-NO"),
|
||||
Locale.forLanguageTag("nb"),
|
||||
Locale.forLanguageTag("no"),
|
||||
Locale.ROOT});
|
||||
candidateData.put(Locale.forLanguageTag("no-NO-POSIX"), new Locale[] {
|
||||
Locale.forLanguageTag("no-NO-POSIX"),
|
||||
Locale.forLanguageTag("nb-NO-POSIX"),
|
||||
Locale.forLanguageTag("no-NO"),
|
||||
Locale.forLanguageTag("nb-NO"),
|
||||
Locale.forLanguageTag("no"),
|
||||
Locale.forLanguageTag("nb"),
|
||||
Locale.ROOT});
|
||||
|
||||
|
||||
for (Locale locale : candidateData.keySet()) {
|
||||
List<Locale> candidates = CONTROL.getCandidateLocales("any", locale);
|
||||
List<Locale> expected = Arrays.asList(candidateData.get(locale));
|
||||
if (!candidates.equals(expected)) {
|
||||
error("Wrong candidates for %s: got %s, expected %s%n",
|
||||
toString(locale), candidates, expected);
|
||||
}
|
||||
}
|
||||
final int NARGS = 2;
|
||||
for (int mask = 0; mask < (1 << NARGS)-1; mask++) {
|
||||
Object[] data = getNpeArgs(NARGS, mask);
|
||||
try {
|
||||
List<Locale> candidates = CONTROL.getCandidateLocales((String) data[0],
|
||||
(Locale) data[1]);
|
||||
error("getCandidateLocales(%s, %s) doesn't throw NPE.%n",
|
||||
data[0], toString((Locale)data[1]));
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testGetFallbackLocale() {
|
||||
Locale current = Locale.getDefault();
|
||||
Locale.setDefault(Locale.ITALY);
|
||||
try {
|
||||
Locale loc = CONTROL.getFallbackLocale("any", Locale.FRANCE);
|
||||
if (loc != Locale.ITALY) {
|
||||
error("getFallbackLocale: got %s, expected %s%n",
|
||||
toString(loc), toString(Locale.ITALY));
|
||||
}
|
||||
loc = CONTROL.getFallbackLocale("any", Locale.ITALY);
|
||||
if (loc != null) {
|
||||
error("getFallbackLocale: got %s, expected null%n", toString(loc));
|
||||
}
|
||||
} finally {
|
||||
Locale.setDefault(current);
|
||||
}
|
||||
|
||||
final int NARGS = 2;
|
||||
for (int mask = 0; mask < (1 << NARGS)-1; mask++) {
|
||||
Object[] data = getNpeArgs(NARGS, mask);
|
||||
try {
|
||||
Locale loc = CONTROL.getFallbackLocale((String) data[0], (Locale) data[1]);
|
||||
error("getFallbackLocale(%s, %s) doesn't throw NPE.%n", data[0], data[1]);
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testNewBundle() {
|
||||
int testNo = 0;
|
||||
ResourceBundle rb = null;
|
||||
try {
|
||||
testNo = 1;
|
||||
rb = CONTROL.newBundle("StressOut", Locale.JAPANESE,
|
||||
PROPERTIES, LOADER, false);
|
||||
String s = rb.getString("data");
|
||||
if (!s.equals("Japan")) {
|
||||
error("newBundle: #%d got %s, expected Japan%n", testNo, s);
|
||||
}
|
||||
|
||||
testNo = 2;
|
||||
rb = CONTROL.newBundle("TestResourceRB", Locale.ROOT,
|
||||
CLAZZ, LOADER, false);
|
||||
s = rb.getString("type");
|
||||
if (!s.equals(CLAZZ)) {
|
||||
error("newBundle: #%d got %s, expected %s%n", testNo, s, CLAZZ);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
error("newBundle: #%d threw %s%n", testNo, e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Test exceptions
|
||||
|
||||
try {
|
||||
// MalformedDataRB contains an invalid Unicode notation which
|
||||
// causes to throw an IllegalArgumentException.
|
||||
rb = CONTROL.newBundle("MalformedDataRB", Locale.ENGLISH,
|
||||
PROPERTIES, LOADER, false);
|
||||
error("newBundle: doesn't throw IllegalArgumentException with malformed data.");
|
||||
} catch (IllegalArgumentException iae) {
|
||||
} catch (Exception e) {
|
||||
error("newBundle: threw %s%n", e);
|
||||
}
|
||||
|
||||
try {
|
||||
rb = CONTROL.newBundle("StressOut", Locale.JAPANESE,
|
||||
"foo.bar", LOADER, false);
|
||||
error("newBundle: doesn't throw IllegalArgumentException with invalid format.");
|
||||
} catch (IllegalArgumentException iae) {
|
||||
} catch (Exception e) {
|
||||
error("newBundle: threw %s%n", e);
|
||||
}
|
||||
|
||||
try {
|
||||
rb = CONTROL.newBundle("NonResourceBundle", Locale.ROOT,
|
||||
"java.class", LOADER, false);
|
||||
error("newBundle: doesn't throw ClassCastException with a non-ResourceBundle subclass.");
|
||||
} catch (ClassCastException cce) {
|
||||
} catch (Exception e) {
|
||||
error("newBundle: threw %s%n", e);
|
||||
}
|
||||
|
||||
// NPE test
|
||||
final int NARGS = 4;
|
||||
for (int mask = 0; mask < (1 << NARGS)-1; mask++) {
|
||||
Object[] data = getNpeArgs(NARGS, mask);
|
||||
Locale loc = (Locale) data[1];
|
||||
try {
|
||||
rb = CONTROL.newBundle((String) data[0], loc,
|
||||
(String) data[2], (ClassLoader) data[3],
|
||||
false);
|
||||
error("newBundle(%s, %s, %s, %s, false) doesn't throw NPE.%n",
|
||||
data[0], toString(loc), data[2], data[3]);
|
||||
} catch (NullPointerException npe) {
|
||||
} catch (Exception e) {
|
||||
error("newBundle(%s, %s, %s, %s, false) threw %s.%n",
|
||||
data[0], toString(loc), data[2], data[3], e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testGetTimeToLive() {
|
||||
long ttl = CONTROL.getTimeToLive("any", Locale.US);
|
||||
if (ttl != CONTROL.TTL_NO_EXPIRATION_CONTROL) {
|
||||
error("getTimeToLive: got %d, expected %d%n", ttl,
|
||||
CONTROL.TTL_NO_EXPIRATION_CONTROL);
|
||||
}
|
||||
final int NARGS = 2;
|
||||
for (int mask = 0; mask < (1 << NARGS)-1; mask++) {
|
||||
Object[] data = getNpeArgs(NARGS, mask);
|
||||
try {
|
||||
ttl = CONTROL.getTimeToLive((String) data[0], (Locale) data[1]);
|
||||
error("getTimeToLive(%s, %s) doesn't throw NPE.%n", data[0], data[1]);
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The functionality of needsReload is tested by
|
||||
// ExpirationTest.sh. Only parameter checking is tested here.
|
||||
private static void testNeedsReload() {
|
||||
long loadTime = System.currentTimeMillis();
|
||||
|
||||
// NPE test
|
||||
final int NARGS = 5;
|
||||
for (int mask = 0; mask < (1 << NARGS)-1; mask++) {
|
||||
Object[] data = getNpeArgs(NARGS, mask);
|
||||
Locale loc = (Locale) data[1];
|
||||
try {
|
||||
boolean b = CONTROL.needsReload((String) data[0], loc,
|
||||
(String) data[2], (ClassLoader) data[3],
|
||||
(ResourceBundle) data[4], loadTime);
|
||||
error("needsReload(%s, %s, %s, %s, %s, loadTime) doesn't throw NPE.%n",
|
||||
data[0], toString(loc), data[2], data[3], data[4]);
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testToBundleName() {
|
||||
final String name = "J2SE";
|
||||
Map<Locale, String> bundleNames = new HashMap<Locale, String>();
|
||||
bundleNames.put(Locale.of("ja", "JP", "YOK"),
|
||||
name + "_" + "ja" + "_" + "JP" + "_" + "YOK");
|
||||
bundleNames.put(Locale.of("ja", "JP"),
|
||||
name + "_" + "ja" + "_" + "JP");
|
||||
bundleNames.put(Locale.of("ja"),
|
||||
name + "_" + "ja");
|
||||
bundleNames.put(Locale.of("ja", "", "YOK"),
|
||||
name + "_" + "ja" + "_" + "" + "_" + "YOK");
|
||||
bundleNames.put(Locale.of("", "JP", "YOK"),
|
||||
name + "_" + "" + "_" + "JP" + "_" + "YOK");
|
||||
bundleNames.put(Locale.of("", "", "YOK"),
|
||||
name + "_" + "" + "_" + "" + "_" + "YOK");
|
||||
bundleNames.put(Locale.of("", "JP"),
|
||||
name + "_" + "" + "_" + "JP");
|
||||
bundleNames.put(Locale.ROOT,
|
||||
name);
|
||||
|
||||
for (Locale locale : bundleNames.keySet()) {
|
||||
String bn = CONTROL.toBundleName(name, locale);
|
||||
String expected = bundleNames.get(locale);
|
||||
if (!bn.equals(expected)) {
|
||||
error("toBundleName: got %s, expected %s%n", bn, expected);
|
||||
}
|
||||
}
|
||||
|
||||
final int NARGS = 2;
|
||||
for (int mask = 0; mask < (1 << NARGS)-1; mask++) {
|
||||
Object[] data = getNpeArgs(NARGS, mask);
|
||||
try {
|
||||
String s = CONTROL.toBundleName((String) data[0], (Locale) data[1]);
|
||||
error("toBundleName(%s, %s) doesn't throw NPE.%n", data[0], data[1]);
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testToResourceName() {
|
||||
String[][] names = {
|
||||
// bundleName, suffix, expected result
|
||||
{ "com.sun.J2SE", "xml", "com/sun/J2SE.xml" },
|
||||
{ ".J2SE", "xml", "/J2SE.xml" },
|
||||
{ "J2SE", "xml", "J2SE.xml" },
|
||||
{ "com/sun/J2SE", "xml", "com/sun/J2SE.xml" },
|
||||
{ "com.sun.J2SE", "", "com/sun/J2SE." },
|
||||
{ ".", "", "/." },
|
||||
{ "", "", "." },
|
||||
|
||||
// data for NPE tests
|
||||
{ null, "any", null },
|
||||
{ "any", null, null },
|
||||
{ null, null, null },
|
||||
};
|
||||
|
||||
for (String[] data : names) {
|
||||
String result = null;
|
||||
boolean npeThrown = false;
|
||||
try {
|
||||
result = CONTROL.toResourceName(data[0], data[1]);
|
||||
} catch (NullPointerException npe) {
|
||||
npeThrown = true;
|
||||
}
|
||||
String expected = data[2];
|
||||
if (expected != null) {
|
||||
if (!result.equals(expected)) {
|
||||
error("toResourceName: got %s, expected %s%n", result, data[2]);
|
||||
}
|
||||
} else {
|
||||
if (!npeThrown) {
|
||||
error("toResourceName(%s, %s) doesn't throw NPE.%n", data[0], data[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces permutations argument data that contains at least one
|
||||
* null.
|
||||
*/
|
||||
private static Object[] getNpeArgs(int length, int mask) {
|
||||
Object[] data = new Object[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
if ((mask & (1 << i)) == 0) {
|
||||
data[i] = null;
|
||||
} else {
|
||||
data[i] = FULLARGS[i];
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private static String toString(Locale loc) {
|
||||
if (loc == null)
|
||||
return "null";
|
||||
return "\"" + loc.getLanguage() + "_" + loc.getCountry() + "_" + loc.getVariant() + "\"";
|
||||
}
|
||||
|
||||
private static void error(String msg) {
|
||||
System.out.println(msg);
|
||||
errors++;
|
||||
}
|
||||
|
||||
private static void error(String fmt, Object... args) {
|
||||
System.out.printf(fmt, args);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue