From 00e530042f481d1000be27584cf05be939a42bb0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jul 2024 09:07:42 -0400 Subject: [PATCH 1/6] [LANG-1745] RandomStringUtils.random() with a negative character index should throw IllegalArgumentException (#1247) * Add testLang1641() * Rename some test methods * [LANG-1745] RandomStringUtils.random() with a negative character index should throw IllegalArgumentException --- src/changes/changes.xml | 17 ++++++----- .../commons/lang3/RandomStringUtils.java | 2 ++ .../commons/lang3/RandomStringUtilsTest.java | 30 +++++++++++++++---- .../lang3/time/FastDateFormatTest.java | 23 ++++++++++++-- 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e1d190482..02208f3de 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,14 +46,15 @@ The type attribute can be add,update,fix,remove. - - Reimplement StopWatch internals to use java.time. - - Add StopWatch.getSplitDuration() and deprecate getSplitTime(). - Add StopWatch.getStartInstant() and deprecate getStartTime(). - Add StopWatch.getStopInstant() and deprecate getStopTime(). - Add StopWatch.getDuration() and deprecate getTime(). - + + Reimplement StopWatch internals to use java.time. + RandomStringUtils.random() with a negative character index should throw IllegalArgumentException. + + Add StopWatch.getSplitDuration() and deprecate getSplitTime(). + Add StopWatch.getStartInstant() and deprecate getStartTime(). + Add StopWatch.getStopInstant() and deprecate getStopTime(). + Add StopWatch.getDuration() and deprecate getTime(). + diff --git a/src/main/java/org/apache/commons/lang3/RandomStringUtils.java b/src/main/java/org/apache/commons/lang3/RandomStringUtils.java index e30e214eb..eb6615e75 100644 --- a/src/main/java/org/apache/commons/lang3/RandomStringUtils.java +++ b/src/main/java/org/apache/commons/lang3/RandomStringUtils.java @@ -232,6 +232,8 @@ public class RandomStringUtils { } } else if (end <= start) { throw new IllegalArgumentException("Parameter end (" + end + ") must be greater than start (" + start + ")"); + } else if (start < 0 || end < 0) { + throw new IllegalArgumentException("Character positions MUST be >= 0"); } if (end > Character.MAX_CODE_POINT) { diff --git a/src/test/java/org/apache/commons/lang3/RandomStringUtilsTest.java b/src/test/java/org/apache/commons/lang3/RandomStringUtilsTest.java index 876a0d146..2999d8ebc 100644 --- a/src/test/java/org/apache/commons/lang3/RandomStringUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/RandomStringUtilsTest.java @@ -93,23 +93,43 @@ public class RandomStringUtilsTest extends AbstractLangTest { } @Test - public void testExceptions() { - final char[] DUMMY = { 'a' }; // valid char array + public void testExceptionsRandom() { assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1)); assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, true, true)); - assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, DUMMY)); + assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, new char[] { 'a' })); assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(1, new char[0])); assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, "")); assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, (String) null)); assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, 'a', 'z', false, false)); - assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, 'a', 'z', false, false, DUMMY)); - assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, 'a', 'z', false, false, DUMMY, new Random())); + assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, 'a', 'z', false, false, new char[] { 'a' })); + assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(-1, 'a', 'z', false, false, new char[] { 'a' }, new Random())); assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(8, 32, 48, false, true)); assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(8, 32, 65, true, false)); + assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.random(1, Integer.MIN_VALUE, -10, false, false, null)); + } + + @Test + public void testExceptionsRandomAlphabetic() { assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.randomAlphabetic(-1)); + } + + @Test + public void testExceptionsRandomAscii() { assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.randomAscii(-1)); + } + + @Test + public void testExceptionsRandomGraph() { assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.randomGraph(-1)); + } + + @Test + public void testExceptionsRandomNumeric() { assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.randomNumeric(-1)); + } + + @Test + public void testExceptionsRandomPrint() { assertThrows(IllegalArgumentException.class, () -> RandomStringUtils.randomPrint(-1)); } diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java index aa13e2845..698dd1ade 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java @@ -47,6 +47,9 @@ import org.junitpioneer.jupiter.DefaultTimeZone; * Unit tests {@link org.apache.commons.lang3.time.FastDateFormat}. */ public class FastDateFormatTest extends AbstractLangTest { + + private static final String ISO_8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZ"; + private static final int NTHREADS = 10; private static final int NROUNDS = 10000; @@ -245,7 +248,7 @@ public class FastDateFormatTest extends AbstractLangTest { } @Test - public void testLANG_1152() { + public void testLang1152() { final TimeZone utc = FastTimeZone.getGmtTimeZone(); final Date date = new Date(Long.MAX_VALUE); @@ -256,15 +259,29 @@ public class FastDateFormatTest extends AbstractLangTest { assertEquals("17/08/292278994", dateAsString); } @Test - public void testLANG_1267() { + public void testLang1267() { FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); } + @Test + public void testLang1641() { + assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT), FastDateFormat.getInstance(ISO_8601_DATE_FORMAT)); + // commons-lang's GMT TimeZone + assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, FastTimeZone.getGmtTimeZone()), + FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, FastTimeZone.getGmtTimeZone())); + // default TimeZone + assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getDefault()), + FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getDefault())); + // TimeZones that are identical in every way except ID + assertNotSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getTimeZone("Australia/Broken_Hill")), + FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getTimeZone("Australia/Yancowinna"))); + } + /** * According to LANG-954 (https://issues.apache.org/jira/browse/LANG-954) this is broken in Android 2.1. */ @Test - public void testLANG_954() { + public void testLang954() { final String pattern = "yyyy-MM-dd'T'"; FastDateFormat.getInstance(pattern); } From 3ebaac5c02a209dfc28f4a50700153da20a61265 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jul 2024 11:03:42 -0400 Subject: [PATCH 2/6] Format nits --- src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java index c1f7500c3..6205283f5 100644 --- a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java @@ -539,10 +539,8 @@ public class LocaleUtilsTest extends AbstractLangTest { assertValidToLocale("us_EN_SFsafdFDsdfF", "us", "EN", "SFSAFDFDSDFF"); } - assertThrows( - IllegalArgumentException.class, () -> LocaleUtils.toLocale("us_EN-a"), "Should fail as no consistent delimiter"); - assertThrows( - IllegalArgumentException.class, () -> LocaleUtils.toLocale("uu_UU_"), "Must be 3, 5 or 7+ in length"); + assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("us_EN-a"), "Should fail as no consistent delimiter"); + assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("uu_UU_"), "Must be 3, 5 or 7+ in length"); } /** From effb8c7d3c333ddfcbeb8c467d673bff866c9957 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jul 2024 11:07:26 -0400 Subject: [PATCH 3/6] Javadoc --- .../java/org/apache/commons/lang3/LocaleUtils.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/org/apache/commons/lang3/LocaleUtils.java b/src/main/java/org/apache/commons/lang3/LocaleUtils.java index bd6b97447..df2f4885f 100644 --- a/src/main/java/org/apache/commons/lang3/LocaleUtils.java +++ b/src/main/java/org/apache/commons/lang3/LocaleUtils.java @@ -52,9 +52,20 @@ public class LocaleUtils { AVAILABLE_LOCALE_SET = Collections.unmodifiableSet(new HashSet<>(list)); } } + + /** + * The underscore character {@code '}{@value}{@code '}. + */ private static final char UNDERSCORE = '_'; + + /** + * The undetermined language {@value}. + */ private static final String UNDETERMINED = "und"; + /** + * The dash character {@code '}{@value}{@code '}. + */ private static final char DASH = '-'; /** Concurrent map of language locales by country. */ From e79f81f746db910d231733dbdee03728547aed0f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jul 2024 11:08:08 -0400 Subject: [PATCH 4/6] Format nits --- .../java/org/apache/commons/lang3/LocaleUtils.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/LocaleUtils.java b/src/main/java/org/apache/commons/lang3/LocaleUtils.java index df2f4885f..8548ba4ee 100644 --- a/src/main/java/org/apache/commons/lang3/LocaleUtils.java +++ b/src/main/java/org/apache/commons/lang3/LocaleUtils.java @@ -68,13 +68,15 @@ public class LocaleUtils { */ private static final char DASH = '-'; - /** Concurrent map of language locales by country. */ - private static final ConcurrentMap> cLanguagesByCountry = - new ConcurrentHashMap<>(); + /** + * Concurrent map of language locales by country. + */ + private static final ConcurrentMap> cLanguagesByCountry = new ConcurrentHashMap<>(); - /** Concurrent map of country locales by language. */ - private static final ConcurrentMap> cCountriesByLanguage = - new ConcurrentHashMap<>(); + /** + * Concurrent map of country locales by language. + */ + private static final ConcurrentMap> cCountriesByLanguage = new ConcurrentHashMap<>(); /** * Obtains an unmodifiable list of installed locales. From 0f4dee8451df2ec68a1f201a859f3955a7abd504 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jul 2024 11:35:33 -0400 Subject: [PATCH 5/6] LocaleUtils.toLocale(String) cannot parse four segments --- src/changes/changes.xml | 1 + .../org/apache/commons/lang3/LocaleUtils.java | 22 ++++++++++--------- .../apache/commons/lang3/LocaleUtilsTest.java | 3 ++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 02208f3de..9438361e8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,6 +49,7 @@ The type attribute can be add,update,fix,remove. Reimplement StopWatch internals to use java.time. RandomStringUtils.random() with a negative character index should throw IllegalArgumentException. + LocaleUtils.toLocale(String) cannot parse four segments. Add StopWatch.getSplitDuration() and deprecate getSplitTime(). Add StopWatch.getStartInstant() and deprecate getStartTime(). diff --git a/src/main/java/org/apache/commons/lang3/LocaleUtils.java b/src/main/java/org/apache/commons/lang3/LocaleUtils.java index 8548ba4ee..39b81a490 100644 --- a/src/main/java/org/apache/commons/lang3/LocaleUtils.java +++ b/src/main/java/org/apache/commons/lang3/LocaleUtils.java @@ -249,28 +249,30 @@ public class LocaleUtils { } /** - * Tries to parse a locale from the given String. + * Tries to parse a Locale from the given String. + *

+ * See {@Link Locale} for the format. + *

* - * @param str the String to parse a locale from. - * @return a Locale instance parsed from the given String. + * @param str the String to parse as a Locale. + * @return a Locale parsed from the given String. * @throws IllegalArgumentException if the given String can not be parsed. + * @see Locale */ private static Locale parseLocale(final String str) { if (isISO639LanguageCode(str)) { return new Locale(str); } - - final String[] segments = str.indexOf(UNDERSCORE) != -1 - ? str.split(String.valueOf(UNDERSCORE), -1) - : str.split(String.valueOf(DASH), -1); + final int limit = 3; + final char separator = str.indexOf(UNDERSCORE) != -1 ? UNDERSCORE : DASH; + final String[] segments = str.split(String.valueOf(separator), 3); final String language = segments[0]; if (segments.length == 2) { final String country = segments[1]; - if (isISO639LanguageCode(language) && isISO3166CountryCode(country) || - isNumericAreaCode(country)) { + if (isISO639LanguageCode(language) && isISO3166CountryCode(country) || isNumericAreaCode(country)) { return new Locale(language, country); } - } else if (segments.length == 3) { + } else if (segments.length == limit) { final String country = segments[1]; final String variant = segments[2]; if (isISO639LanguageCode(language) && diff --git a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java index 6205283f5..dc9e3969d 100644 --- a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java @@ -538,9 +538,10 @@ public class LocaleUtilsTest extends AbstractLangTest { assertValidToLocale("us_EN_a", "us", "EN", "A"); assertValidToLocale("us_EN_SFsafdFDsdfF", "us", "EN", "SFSAFDFDSDFF"); } - assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("us_EN-a"), "Should fail as no consistent delimiter"); assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("uu_UU_"), "Must be 3, 5 or 7+ in length"); + // LANG-1741 + assertEquals(new Locale("en", "001", "US_POSIX"), LocaleUtils.toLocale("en_001_US_POSIX")); } /** From b7c24e7820a3d2ce7bcb7a0e4a950baaa8fe85e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 12:04:18 -0400 Subject: [PATCH 6/6] Bump github/codeql-action from 3.25.12 to 3.25.13 (#1248) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.12 to 3.25.13. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4fa2a7953630fd2f3fb380f21be14ede0169dd4f...2d790406f505036ef40ecba973cc774a50395aac) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cc793b616..1584ee8c9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # 3.25.12 + uses: github/codeql-action/init@2d790406f505036ef40ecba973cc774a50395aac # 3.25.13 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # 3.25.12 + uses: github/codeql-action/autobuild@2d790406f505036ef40ecba973cc774a50395aac # 3.25.13 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # 3.25.12 + uses: github/codeql-action/analyze@2d790406f505036ef40ecba973cc774a50395aac # 3.25.13 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 3dc1433d6..bec68e97c 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # 3.25.12 + uses: github/codeql-action/upload-sarif@2d790406f505036ef40ecba973cc774a50395aac # 3.25.13 with: sarif_file: results.sarif