| @ -0,0 +1,64 @@ | |||
| /* Copyright 2025 Google Inc. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| */ | |||
| #include "phonenumbers/phonenumbermatcher.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #include <limits> | |||
| #include <unicode/unistr.h> | |||
| #include "phonenumbers/base/basictypes.h" | |||
| #include "phonenumbers/base/memory/scoped_ptr.h" | |||
| #include "phonenumbers/base/memory/singleton.h" | |||
| #include "phonenumbers/default_logger.h" | |||
| #include "phonenumbers/phonenumber.h" | |||
| #include "phonenumbers/phonenumbermatch.h" | |||
| #include "phonenumbers/phonenumberutil.h" | |||
| #include "phonenumbers/stringutil.h" | |||
| #include "phonenumbers/asyoutypeformatter.h" | |||
| #include "phonenumbers/shortnumberinfo.h" | |||
| #include <fuzzer/FuzzedDataProvider.h> | |||
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { | |||
| // initial setup of all the structs we need | |||
| FuzzedDataProvider fuzzed_data(data, size); | |||
| i18n::phonenumbers::PhoneNumberUtil* phone_util = | |||
| i18n::phonenumbers::PhoneNumberUtil::GetInstance(); | |||
| bool region_is_2_bytes = fuzzed_data.ConsumeBool(); | |||
| std::string region = fuzzed_data.ConsumeBytesAsString(region_is_2_bytes ? 2 : 3); | |||
| std::unique_ptr<i18n::phonenumbers::AsYouTypeFormatter> formatter( | |||
| phone_util->GetAsYouTypeFormatter(region)); | |||
| // setup the data passed to the target methods | |||
| const int iterations = fuzzed_data.ConsumeIntegralInRange(0, 32); | |||
| std::string result; | |||
| // Random amount of iterations | |||
| for (int i = 0; i < iterations; ++i) { | |||
| const char32_t next_char = fuzzed_data.ConsumeIntegral<char32_t>(); | |||
| const bool remember = fuzzed_data.ConsumeBool(); | |||
| // Randomly trigger the remember method | |||
| if (remember) { | |||
| formatter->InputDigitAndRememberPosition(next_char, &result); | |||
| } else { | |||
| formatter->InputDigit(next_char, &result); | |||
| } | |||
| // get the remembered position whether we remembered it or not | |||
| formatter->GetRememberedPosition(); | |||
| } | |||
| return 0; | |||
| } | |||
| @ -0,0 +1,85 @@ | |||
| /* Copyright 2025 Google Inc. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| */ | |||
| #include "phonenumbers/phonenumbermatcher.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #include <limits> | |||
| #include <unicode/unistr.h> | |||
| #include "phonenumbers/base/basictypes.h" | |||
| #include "phonenumbers/base/memory/scoped_ptr.h" | |||
| #include "phonenumbers/base/memory/singleton.h" | |||
| #include "phonenumbers/default_logger.h" | |||
| #include "phonenumbers/phonenumber.h" | |||
| #include "phonenumbers/phonenumbermatch.h" | |||
| #include "phonenumbers/regexp_adapter_icu.h" | |||
| #include "phonenumbers/phonenumberutil.h" | |||
| #include "phonenumbers/stringutil.h" | |||
| #include "phonenumbers/asyoutypeformatter.h" | |||
| #include "phonenumbers/shortnumberinfo.h" | |||
| #include <fuzzer/FuzzedDataProvider.h> | |||
| // returns a leniency level based on the data we got from libfuzzer | |||
| i18n::phonenumbers::PhoneNumberMatcher::Leniency ConsumeLeniency( | |||
| FuzzedDataProvider& fuzzed_data) { | |||
| switch (fuzzed_data.ConsumeIntegralInRange(0, 3)) { | |||
| case 0: | |||
| return i18n::phonenumbers::PhoneNumberMatcher::Leniency::POSSIBLE; | |||
| case 1: | |||
| return i18n::phonenumbers::PhoneNumberMatcher::Leniency::VALID; | |||
| case 2: | |||
| return i18n::phonenumbers::PhoneNumberMatcher::Leniency::STRICT_GROUPING; | |||
| default: | |||
| return i18n::phonenumbers::PhoneNumberMatcher::Leniency::EXACT_GROUPING; | |||
| } | |||
| } | |||
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { | |||
| // Setup the data provider and util | |||
| FuzzedDataProvider fuzzed_data(data, size); | |||
| i18n::phonenumbers::PhoneNumberUtil* phone_util = | |||
| i18n::phonenumbers::PhoneNumberUtil::GetInstance(); | |||
| // this should be enought to get at least 2 matches | |||
| std::string text = fuzzed_data.ConsumeBytesAsString(128); | |||
| // the region is either 2 or 3 characters long | |||
| bool region_is_2_bytes = fuzzed_data.ConsumeBool(); | |||
| std::string region = fuzzed_data.ConsumeBytesAsString(region_is_2_bytes ? 2 : 3); | |||
| // setup fuzzed data for matchers | |||
| i18n::phonenumbers::PhoneNumberMatcher::Leniency leniency = | |||
| ConsumeLeniency(fuzzed_data); | |||
| int max_tries = fuzzed_data.ConsumeIntegralInRange(0, 500); | |||
| bool full_match = fuzzed_data.ConsumeBool(); | |||
| std::string regexp_string = fuzzed_data.ConsumeRandomLengthString(32); | |||
| // initialize and fuzz the built-in matcher | |||
| i18n::phonenumbers::PhoneNumberMatcher matcher(*phone_util, text, region, | |||
| leniency, max_tries); | |||
| while (matcher.HasNext()) { | |||
| i18n::phonenumbers::PhoneNumberMatch match; | |||
| matcher.Next(&match); | |||
| } | |||
| // fuzz the matching with the icu adapter | |||
| std::string matched_string; | |||
| i18n::phonenumbers::ICURegExpFactory factory; | |||
| i18n::phonenumbers::RegExp* regexp = factory.CreateRegExp(regexp_string); | |||
| regexp->Match(text, full_match, &matched_string); | |||
| return 0; | |||
| } | |||
| @ -1,48 +0,0 @@ | |||
| /* Copyright 2020 Google Inc. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| */ | |||
| #include "phonenumbers/phonenumbermatcher.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #include <unicode/unistr.h> | |||
| #include "phonenumbers/base/basictypes.h" | |||
| #include "phonenumbers/base/memory/scoped_ptr.h" | |||
| #include "phonenumbers/base/memory/singleton.h" | |||
| #include "phonenumbers/default_logger.h" | |||
| #include "phonenumbers/phonenumber.h" | |||
| #include "phonenumbers/phonenumber.pb.h" | |||
| #include "phonenumbers/phonenumbermatch.h" | |||
| #include "phonenumbers/phonenumberutil.h" | |||
| #include "phonenumbers/stringutil.h" | |||
| #include <fuzzer/FuzzedDataProvider.h> | |||
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | |||
| { | |||
| FuzzedDataProvider fuzzed_data(data, size); | |||
| std::string input = fuzzed_data.ConsumeRandomLengthString(); | |||
| std::string input2 = fuzzed_data.ConsumeRandomLengthString(); | |||
| i18n::phonenumbers::PhoneNumberUtil *phone_util = i18n::phonenumbers::PhoneNumberUtil::GetInstance(); | |||
| i18n::phonenumbers::PhoneNumber parsed; | |||
| phone_util->Parse(input, input2, &parsed); | |||
| phone_util->IsValidNumber(parsed); | |||
| phone_util->GetCountryCodeForRegion(input); | |||
| return 0; | |||
| } | |||
| @ -0,0 +1,79 @@ | |||
| /* Copyright 2025 Google Inc. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| */ | |||
| #include "phonenumbers/phonenumbermatcher.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #include <limits> | |||
| #include <unicode/unistr.h> | |||
| #include "phonenumbers/base/basictypes.h" | |||
| #include "phonenumbers/base/memory/scoped_ptr.h" | |||
| #include "phonenumbers/base/memory/singleton.h" | |||
| #include "phonenumbers/default_logger.h" | |||
| #include "phonenumbers/phonenumber.h" | |||
| #include "phonenumbers/phonenumbermatch.h" | |||
| #include "phonenumbers/phonenumberutil.h" | |||
| #include "phonenumbers/stringutil.h" | |||
| #include "phonenumbers/asyoutypeformatter.h" | |||
| #include "phonenumbers/shortnumberinfo.h" | |||
| #include <fuzzer/FuzzedDataProvider.h> | |||
| // returns a short number cost based on the data we got from libfuzzer | |||
| i18n::phonenumbers::ShortNumberInfo::ShortNumberCost ConsumeShortNumberCost( | |||
| FuzzedDataProvider& fuzzed_data) { | |||
| switch (fuzzed_data.ConsumeIntegralInRange(0, 4)) { | |||
| case 0: return i18n::phonenumbers::ShortNumberInfo::TOLL_FREE; | |||
| case 1: return i18n::phonenumbers::ShortNumberInfo::STANDARD_RATE; | |||
| case 2: return i18n::phonenumbers::ShortNumberInfo::PREMIUM_RATE; | |||
| default: return i18n::phonenumbers::ShortNumberInfo::UNKNOWN_COST; | |||
| } | |||
| } | |||
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { | |||
| // setup the data provider and util | |||
| FuzzedDataProvider fuzzed_data(data, size); | |||
| i18n::phonenumbers::PhoneNumberUtil* phone_util = | |||
| i18n::phonenumbers::PhoneNumberUtil::GetInstance(); | |||
| // setup all the data we need to pass to the target methods | |||
| i18n::phonenumbers::PhoneNumber phone_number; | |||
| std::string number = fuzzed_data.ConsumeRandomLengthString(32); | |||
| bool region_is_2_bytes = fuzzed_data.ConsumeBool(); | |||
| std::string region = fuzzed_data.ConsumeBytesAsString(region_is_2_bytes ? 2 : 3); | |||
| if (fuzzed_data.ConsumeBool()) { | |||
| phone_util->ParseAndKeepRawInput(number, region, &phone_number); | |||
| } else { | |||
| phone_util->Parse(number, region, &phone_number); | |||
| } | |||
| // fuzz the public methods | |||
| i18n::phonenumbers::ShortNumberInfo short_info; | |||
| short_info.IsPossibleShortNumberForRegion(phone_number, region); | |||
| short_info.IsPossibleShortNumber(phone_number); | |||
| short_info.IsValidShortNumber(phone_number); | |||
| short_info.GetExpectedCostForRegion(phone_number, region); | |||
| short_info.GetExpectedCost(phone_number); | |||
| short_info.GetExampleShortNumber(region); | |||
| i18n::phonenumbers::ShortNumberInfo::ShortNumberCost cost = | |||
| ConsumeShortNumberCost(fuzzed_data); | |||
| short_info.GetExampleShortNumberForCost(region, cost); | |||
| short_info.ConnectsToEmergencyNumber(number, region); | |||
| short_info.IsEmergencyNumber(number, region); | |||
| short_info.IsCarrierSpecific(phone_number); | |||
| short_info.IsCarrierSpecificForRegion(phone_number, region); | |||
| short_info.IsSmsServiceForRegion(phone_number, region); | |||
| return 0; | |||
| } | |||
| @ -0,0 +1,210 @@ | |||
| /* Copyright 2020 Google Inc. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| */ | |||
| #include "phonenumbers/phonenumbermatcher.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #include <limits> | |||
| #include <unicode/unistr.h> | |||
| #include "phonenumbers/base/basictypes.h" | |||
| #include "phonenumbers/base/memory/scoped_ptr.h" | |||
| #include "phonenumbers/base/memory/singleton.h" | |||
| #include "phonenumbers/default_logger.h" | |||
| #include "phonenumbers/phonenumber.h" | |||
| #include "phonenumbers/phonenumbermatch.h" | |||
| #include "phonenumbers/phonenumberutil.h" | |||
| #include "phonenumbers/stringutil.h" | |||
| #include "phonenumbers/asyoutypeformatter.h" | |||
| #include "phonenumbers/shortnumberinfo.h" | |||
| #include <fuzzer/FuzzedDataProvider.h> | |||
| using google::protobuf::RepeatedPtrField; | |||
| // consume PhoneNumberUtil::PhoneNumberType from libfuzzer data | |||
| i18n::phonenumbers::PhoneNumberUtil::PhoneNumberType ConsumePhoneNumberType( | |||
| FuzzedDataProvider& fuzzed_data) { | |||
| switch (fuzzed_data.ConsumeIntegralInRange(0, 11)) { | |||
| case 0: | |||
| return i18n::phonenumbers::PhoneNumberUtil::FIXED_LINE; | |||
| case 1: | |||
| return i18n::phonenumbers::PhoneNumberUtil::MOBILE; | |||
| case 2: | |||
| return i18n::phonenumbers::PhoneNumberUtil::FIXED_LINE_OR_MOBILE; | |||
| case 3: | |||
| return i18n::phonenumbers::PhoneNumberUtil::TOLL_FREE; | |||
| case 4: | |||
| return i18n::phonenumbers::PhoneNumberUtil::PREMIUM_RATE; | |||
| case 5: | |||
| return i18n::phonenumbers::PhoneNumberUtil::SHARED_COST; | |||
| case 6: | |||
| return i18n::phonenumbers::PhoneNumberUtil::VOIP; | |||
| case 7: | |||
| return i18n::phonenumbers::PhoneNumberUtil::PERSONAL_NUMBER; | |||
| case 8: | |||
| return i18n::phonenumbers::PhoneNumberUtil::PAGER; | |||
| case 9: | |||
| return i18n::phonenumbers::PhoneNumberUtil::UAN; | |||
| case 10: | |||
| return i18n::phonenumbers::PhoneNumberUtil::VOICEMAIL; | |||
| default: | |||
| return i18n::phonenumbers::PhoneNumberUtil::UNKNOWN; | |||
| } | |||
| } | |||
| // consume PhoneNumberUtil::PhoneNumberFormat from libfuzzer data | |||
| i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat ConsumePhoneNumberFormat( | |||
| FuzzedDataProvider& fuzzed_data) { | |||
| switch (fuzzed_data.ConsumeIntegralInRange(0, 3)) { | |||
| case 0: | |||
| return i18n::phonenumbers::PhoneNumberUtil::E164; | |||
| case 1: | |||
| return i18n::phonenumbers::PhoneNumberUtil::INTERNATIONAL; | |||
| case 2: | |||
| return i18n::phonenumbers::PhoneNumberUtil::NATIONAL; | |||
| default: | |||
| return i18n::phonenumbers::PhoneNumberUtil::RFC3966; | |||
| } | |||
| } | |||
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { | |||
| // initialize the phone util | |||
| i18n::phonenumbers::PhoneNumberUtil* phone_util = | |||
| i18n::phonenumbers::PhoneNumberUtil::GetInstance(); | |||
| FuzzedDataProvider fuzzed_data(data, size); | |||
| // initialize the first phone number, region and country calling code | |||
| i18n::phonenumbers::PhoneNumber phone_number; | |||
| bool region_is_2_bytes = fuzzed_data.ConsumeBool(); | |||
| std::string region = fuzzed_data.ConsumeBytesAsString(region_is_2_bytes ? 2 : 3); | |||
| std::string number = fuzzed_data.ConsumeRandomLengthString(32); | |||
| int country_calling_code = fuzzed_data.ConsumeIntegral<int>(); | |||
| // trigger either one of the public parse methods | |||
| if (fuzzed_data.ConsumeBool()) { | |||
| phone_util->ParseAndKeepRawInput(number, region, &phone_number); | |||
| } else { | |||
| phone_util->Parse(number, region, &phone_number); | |||
| } | |||
| // initialize the second phone number, this is used only for the | |||
| // isNumberMatch* methods | |||
| i18n::phonenumbers::PhoneNumber phone_number2; | |||
| std::string number2 = fuzzed_data.ConsumeRandomLengthString(32); | |||
| if (fuzzed_data.ConsumeBool()) { | |||
| phone_util->ParseAndKeepRawInput(number2, region, &phone_number2); | |||
| } else { | |||
| phone_util->Parse(number2, region, &phone_number2); | |||
| } | |||
| // randomly trigger the truncate method, this may affect state of the input | |||
| // for the method calls that follow it | |||
| if (fuzzed_data.ConsumeIntegralInRange(0, 10) == 5) { | |||
| phone_util->TruncateTooLongNumber(&phone_number); | |||
| } | |||
| // fuzz public methods | |||
| phone_util->IsAlphaNumber(number); | |||
| phone_util->IsPossibleNumber(phone_number); | |||
| phone_util->IsNumberMatch(phone_number, phone_number2); | |||
| phone_util->IsNumberMatchWithOneString(phone_number, number2); | |||
| phone_util->IsNumberMatchWithTwoStrings(number, number2); | |||
| phone_util->CanBeInternationallyDialled(phone_number); | |||
| phone_util->GetNumberType(phone_number); | |||
| phone_util->GetLengthOfGeographicalAreaCode(phone_number); | |||
| phone_util->GetLengthOfNationalDestinationCode(phone_number); | |||
| phone_util->IsNANPACountry(region); | |||
| phone_util->GetCountryCodeForRegion(region); | |||
| phone_util->IsPossibleNumberForString(number, region); | |||
| phone_util->IsNumberGeographical(phone_number); | |||
| phone_util->IsNumberGeographical(number_type, country_calling_code); | |||
| i18n::phonenumbers::PhoneNumberUtil::PhoneNumberType number_type = | |||
| ConsumePhoneNumberType(fuzzed_data); | |||
| phone_util->IsPossibleNumberForType(phone_number, number_type); | |||
| i18n::phonenumbers::PhoneNumber example_number; | |||
| phone_util->GetExampleNumberForType(region, number_type, &example_number); | |||
| i18n::phonenumbers::PhoneNumber example_number_2; | |||
| phone_util->GetExampleNumberForType(number_type, &example_number_2); | |||
| i18n::phonenumbers::PhoneNumber invalid_number; | |||
| phone_util->GetInvalidExampleNumber(region, &invalid_number); | |||
| i18n::phonenumbers::PhoneNumber non_geo_number; | |||
| phone_util->GetExampleNumberForNonGeoEntity(country_calling_code, &non_geo_number); | |||
| std::string output; | |||
| phone_util->GetCountryMobileToken(country_calling_code, &output); | |||
| output.clear(); | |||
| phone_util->GetRegionCodeForNumber(phone_number, &output); | |||
| output.clear(); | |||
| phone_util->GetNddPrefixForRegion(region, fuzzed_data.ConsumeBool(), &output); | |||
| output.clear(); | |||
| // Fuzz the methods which affect the input string, but not the PhoneNumber object | |||
| std::string input = fuzzed_data.ConsumeRandomLengthString(32); | |||
| phone_util->ConvertAlphaCharactersInNumber(&input); | |||
| input.clear(); | |||
| input = fuzzed_data.ConsumeRandomLengthString(32); | |||
| phone_util->NormalizeDigitsOnly(&input); | |||
| input.clear(); | |||
| input = fuzzed_data.ConsumeRandomLengthString(32); | |||
| phone_util->NormalizeDiallableCharsOnly(&input); | |||
| input.clear(); | |||
| // Fuzz the formatting methods | |||
| i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat format = ConsumePhoneNumberFormat(fuzzed_data); | |||
| std::string formatted; | |||
| phone_util->Format(phone_number, format, &formatted); | |||
| formatted.clear(); | |||
| phone_util->FormatInOriginalFormat(phone_number, region, &formatted); | |||
| formatted.clear(); | |||
| phone_util->FormatNumberForMobileDialing(phone_number, region, | |||
| fuzzed_data.ConsumeBool(), &formatted); | |||
| formatted.clear(); | |||
| phone_util->FormatNationalNumberWithPreferredCarrierCode(phone_number, region, &formatted); | |||
| formatted.clear(); | |||
| phone_util->FormatOutOfCountryKeepingAlphaChars(phone_number, region, &formatted); | |||
| formatted.clear(); | |||
| std::string carrier = fuzzed_data.ConsumeRandomLengthString(8); | |||
| phone_util->FormatNationalNumberWithCarrierCode(phone_number, carrier, &formatted); | |||
| formatted.clear(); | |||
| // setup the parameters for FormatByPattern | |||
| i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat number_format = ConsumePhoneNumberFormat(fuzzed_data); | |||
| RepeatedPtrField<i18n::phonenumbers::NumberFormat> number_formats; | |||
| i18n::phonenumbers::NumberFormat* temp_number_format = number_formats.Add(); | |||
| std::string pattern = fuzzed_data.ConsumeRandomLengthString(16); | |||
| std::string format_string = fuzzed_data.ConsumeRandomLengthString(16); | |||
| temp_number_format->set_pattern(pattern); | |||
| temp_number_format->set_format(format_string); | |||
| // fuzz FormatByPattern | |||
| phone_util->FormatByPattern(phone_number, number_format, number_formats, &formatted); | |||
| formatted.clear(); | |||
| return 0; | |||
| } | |||