From 66d3535c6b17bc06a119a4d1ff6acbb2ae29529c Mon Sep 17 00:00:00 2001 From: Tulgaa Date: Mon, 23 Mar 2026 13:47:59 +0800 Subject: [PATCH 1/2] fix: add MAX_INPUT_STRING_LENGTH check in C++ ParseHelper The Java and JavaScript implementations both enforce a 250-character limit on input strings before regex evaluation to prevent excessive CPU consumption. The C++ implementation was missing this check, allowing unbounded input to reach the ICU backtracking regex engine (the default build configuration). Add the same kMaxInputStringLength=250 guard at the top of ParseHelper, matching the Java implementation at PhoneNumberUtil.java:3279. Bug: CWE-1333 (ReDoS via Inefficient Regular Expression) --- cpp/src/phonenumbers/phonenumberutil.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpp/src/phonenumbers/phonenumberutil.cc b/cpp/src/phonenumbers/phonenumberutil.cc index c0c9d09a04..0bdcd7576f 100644 --- a/cpp/src/phonenumbers/phonenumberutil.cc +++ b/cpp/src/phonenumbers/phonenumberutil.cc @@ -2285,6 +2285,16 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper( PhoneNumber* phone_number) const { DCHECK(phone_number); + // We don't allow input strings for parsing to be longer than 250 chars. + // This prevents malicious input from consuming excessive CPU in the + // regular-expression engine. This matches the check in the Java and + // JavaScript implementations. + static const size_t kMaxInputStringLength = 250; + if (number_to_parse.length() > kMaxInputStringLength) { + VLOG(2) << "Input string is too long for parsing."; + return NOT_A_NUMBER; + } + string national_number; PhoneNumberUtil::ErrorType build_national_number_for_parsing_return = BuildNationalNumberForParsing(number_to_parse, &national_number); From e4da90d90cb22caa24210e781d2f0663bf53d9ee Mon Sep 17 00:00:00 2001 From: Tulgaa Date: Mon, 23 Mar 2026 14:08:14 +0800 Subject: [PATCH 2/2] test: add ParseRejectsInputLongerThanMaxLength test Verify that inputs longer than 250 characters are rejected with NOT_A_NUMBER, matching the Java/JS MAX_INPUT_STRING_LENGTH behavior. Tests boundary at exactly 250 chars and normal parsing still works. --- cpp/test/phonenumbers/phonenumberutil_test.cc | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/cpp/test/phonenumbers/phonenumberutil_test.cc b/cpp/test/phonenumbers/phonenumberutil_test.cc index 97cf1f08a4..85f523eabd 100644 --- a/cpp/test/phonenumbers/phonenumberutil_test.cc +++ b/cpp/test/phonenumbers/phonenumberutil_test.cc @@ -4116,6 +4116,42 @@ TEST_F(PhoneNumberUtilTest, FailedParseOnInvalidNumbers) { EXPECT_EQ(PhoneNumber::default_instance(), test_number); } +TEST_F(PhoneNumberUtilTest, ParseRejectsInputLongerThanMaxLength) { + // The C++ ParseHelper enforces a max input string length of 250 characters, + // matching the check in the Java and JavaScript implementations. Inputs + // exceeding this limit should return NOT_A_NUMBER immediately to prevent + // excessive CPU consumption in the regular-expression engine. + PhoneNumber test_number; + + // A string of exactly 251 characters (over the 250-char limit). + string too_long_input(251, '1'); + EXPECT_EQ(PhoneNumberUtil::NOT_A_NUMBER, + phone_util_.Parse(too_long_input, RegionCode::US(), &test_number)); + EXPECT_EQ(PhoneNumber::default_instance(), test_number); + + // A string with digits and spaces that exceeds 250 characters total. + string too_long_with_spaces = "+1 650 253 "; + too_long_with_spaces.append(245, '0'); + EXPECT_EQ(PhoneNumberUtil::NOT_A_NUMBER, + phone_util_.Parse(too_long_with_spaces, RegionCode::US(), + &test_number)); + EXPECT_EQ(PhoneNumber::default_instance(), test_number); + + // A string of exactly 250 characters should NOT be rejected by the length + // check (it may fail for other reasons, but not due to input length). + string at_limit_input(250, '1'); + EXPECT_NE(PhoneNumberUtil::NOT_A_NUMBER, + phone_util_.Parse(at_limit_input, RegionCode::US(), &test_number)); + + // A normal phone number under 250 characters should parse successfully. + PhoneNumber nz_number; + nz_number.set_country_code(64); + nz_number.set_national_number(uint64{33316005}); + EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR, + phone_util_.Parse("033316005", RegionCode::NZ(), &test_number)); + EXPECT_EQ(nz_number, test_number); +} + TEST_F(PhoneNumberUtilTest, ParseNumbersWithPlusWithNoRegion) { PhoneNumber nz_number; nz_number.set_country_code(64);