From ad29f17efb36a0a0f05481d37fad4f1913f038ae Mon Sep 17 00:00:00 2001 From: bann6578-boop Date: Sat, 20 Jun 2026 19:11:44 +0700 Subject: [PATCH 1/2] Add input length bound to isAlphaNumber() to prevent StackOverflowError --- .../src/com/google/i18n/phonenumbers/PhoneNumberUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java index b6de408449..ababe905dc 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -2564,6 +2564,9 @@ public boolean isNANPACountry(String regionCode) { * @return true if the number is a valid vanity number */ public boolean isAlphaNumber(CharSequence number) { + if (number.length() > MAX_INPUT_STRING_LENGTH) { + return false; + } if (!isViablePhoneNumber(number)) { // Number is too short, or doesn't match the basic phone number pattern. return false; From b4b7247f900f2def5b2d70f56739d68e867a805c Mon Sep 17 00:00:00 2001 From: bann6578-boop Date: Sat, 20 Jun 2026 19:22:28 +0700 Subject: [PATCH 2/2] Add input length bound and replace regex in isAlphaNumber() to prevent StackOverflowError isAlphaNumber() did not limit input length before evaluating VALID_ALPHA_PHONE_PATTERN, allowing a numeric-only input of ~1684 characters to cause an uncaught StackOverflowError via unbounded regex recursion. Unlike parse(), which is guarded by MAX_INPUT_STRING_LENGTH, this method had no such bound. This adds the same MAX_INPUT_STRING_LENGTH guard already used in parseHelper() as defense-in-depth, and additionally replaces the recursive regex VALID_ALPHA_PHONE_PATTERN with an equivalent linear character scan (hasAtLeastThreeAlphaChars), eliminating the recursion-based failure mode at its root rather than only guarding against it. The replacement matches the exact ASCII [A-Za-z] range of the original pattern, so behavior is unchanged for all valid inputs. Verified: - Input up to 50,000 characters no longer throws StackOverflowError - isAlphaNumber("1800MICROSOFT"), "325-CARS", "0800 REPAIR", "1-800-MY-APPLE" all still return true (no behavior change) - isAlphaNumber("+14155552671") still returns false - Full PhoneNumberUtilTest suite passes: 121 tests, 0 failures, 0 errors Related: Google OSS VRP / Buganizer issue 525896790 --- .../google/i18n/phonenumbers/PhoneNumberUtil.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java index ababe905dc..68790cec67 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -2563,6 +2563,19 @@ public boolean isNANPACountry(String regionCode) { * @param number the number that needs to be checked * @return true if the number is a valid vanity number */ + private static boolean hasAtLeastThreeAlphaChars(CharSequence number) { + int alphaCount = 0; + for (int i = 0; i < number.length(); i++) { + char c = number.charAt(i); + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { + if (++alphaCount >= 3) { + return true; + } + } + } + return false; + } + public boolean isAlphaNumber(CharSequence number) { if (number.length() > MAX_INPUT_STRING_LENGTH) { return false; @@ -2573,7 +2586,7 @@ public boolean isAlphaNumber(CharSequence number) { } StringBuilder strippedNumber = new StringBuilder(number); maybeStripExtension(strippedNumber); - return VALID_ALPHA_PHONE_PATTERN.matcher(strippedNumber).matches(); + return hasAtLeastThreeAlphaChars(strippedNumber); } /**