From 8a30c2a9b2ef3f069e82061e6db113e259a75bcd Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 5 Oct 2023 23:06:20 +0000 Subject: [PATCH] 8317443: StackOverflowError on calling ListFormat::getInstance() for Norwegian locales Reviewed-by: joehw --- .../util/locale/provider/LocaleResources.java | 21 ++++++++++--------- .../Format/ListFormat/TestListFormat.java | 7 ++++--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java index dd7064416bd..e83f2896304 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java @@ -849,19 +849,20 @@ public class LocaleResources { ResourceReference data = cache.get(cacheKey); if (data == null || ((lpArray = (String[]) data.get()) == null)) { - ResourceBundle rb = localeData.getDateFormatData(locale); - lpArray = rb.getStringArray("ListPatterns_" + typeStr + (style == ListFormat.Style.FULL ? "" : "-" + styleStr)); + var rbKey = "ListPatterns_" + typeStr + (style == ListFormat.Style.FULL ? "" : "-" + styleStr); + lpArray = localeData.getDateFormatData(locale).getStringArray(rbKey); if (lpArray[0].isEmpty() || lpArray[1].isEmpty() || lpArray[2].isEmpty()) { - var adapter = LocaleProviderAdapter.forType(LocaleProviderAdapter.Type.CLDR); - if (adapter instanceof ResourceBundleBasedAdapter rbba) { + if (LocaleProviderAdapter.forType(LocaleProviderAdapter.Type.CLDR) + instanceof ResourceBundleBasedAdapter rbba) { var candList = rbba.getCandidateLocales("", locale); - // make sure there is at least one parent locale - if (candList.size() >= 2) { - var parentPatterns = adapter.getLocaleResources(candList.get(1)).getListPatterns(type, style); - for (int i = 0; i < 3; i++) { // exclude optional ones, ie, "two"/"three" - if (lpArray[i].isEmpty()) { - lpArray[i] = parentPatterns[i]; + if (!candList.isEmpty()) { + for (var p : candList.subList(1, candList.size())) { + var parentPatterns = localeData.getDateFormatData(p).getStringArray(rbKey); + for (int i = 0; i < 3; i++) { // exclude optional ones, ie, "two"/"three" + if (lpArray[i].isEmpty()) { + lpArray[i] = parentPatterns[i]; + } } } } diff --git a/test/jdk/java/text/Format/ListFormat/TestListFormat.java b/test/jdk/java/text/Format/ListFormat/TestListFormat.java index 7f8258dbed0..2d260c9a94c 100644 --- a/test/jdk/java/text/Format/ListFormat/TestListFormat.java +++ b/test/jdk/java/text/Format/ListFormat/TestListFormat.java @@ -316,10 +316,11 @@ public class TestListFormat { // English ("en") has Oxford-comma "end" pattern. Thus missing "standard"/"middle" // should be inherited from "en", but "end" should stay non-Oxford for "en-001" // Note that this test depends on a particular version of CLDR data. + var world = Locale.forLanguageTag("en-001"); assertEquals(""" - ListFormat [locale: "English (world)", start: "{0}, {1}", middle: "{0}, {1}", end: "{0} and {1}", two: "{0} and {1}", three: "{0}, {1} and {2}"] - """, - ListFormat.getInstance(Locale.forLanguageTag("en-001"), ListFormat.Type.STANDARD, ListFormat.Style.FULL).toString()); + ListFormat [locale: "%s", start: "{0}, {1}", middle: "{0}, {1}", end: "{0} and {1}", two: "{0} and {1}", three: "{0}, {1} and {2}"] + """.formatted(world.getDisplayName()), + ListFormat.getInstance(world, ListFormat.Type.STANDARD, ListFormat.Style.FULL).toString()); } private static void compareResult(ListFormat f, List input, String expected, boolean roundTrip) throws ParseException {