| /* 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 <memory> |
| #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; |
| std::unique_ptr<i18n::phonenumbers::RegExp> regexp( |
| factory.CreateRegExp(regexp_string)); |
| regexp->Match(text, full_match, &matched_string); |
| |
| return 0; |
| } |