/****************************************************************************** * * Copyright (C) 2022 The Android Open Source Project * * 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 #include #include #include #include "HyphenatorMap.h" #include "Locale.h" #include "LocaleListCache.h" #include "MinikinInternal.h" #include "UnicodeUtils.h" #include "minikin/LocaleList.h" #include "minikin/U16StringPiece.h" using namespace minikin; const EndHyphenEdit EndHyphenEdits[] = { EndHyphenEdit::NO_EDIT, EndHyphenEdit::REPLACE_WITH_HYPHEN, EndHyphenEdit::INSERT_HYPHEN, EndHyphenEdit::INSERT_ARMENIAN_HYPHEN, EndHyphenEdit::INSERT_MAQAF, EndHyphenEdit::INSERT_UCAS_HYPHEN, EndHyphenEdit::INSERT_ZWJ_AND_HYPHEN, }; const StartHyphenEdit StartHyphenEdits[] = { StartHyphenEdit::NO_EDIT, StartHyphenEdit::INSERT_HYPHEN, StartHyphenEdit::INSERT_ZWJ, }; const HyphenationType HyphenationTypes[] = { HyphenationType::DONT_BREAK, HyphenationType::BREAK_AND_INSERT_HYPHEN, HyphenationType::BREAK_AND_INSERT_ARMENIAN_HYPHEN, HyphenationType::BREAK_AND_INSERT_MAQAF, HyphenationType::BREAK_AND_INSERT_UCAS_HYPHEN, HyphenationType::BREAK_AND_DONT_INSERT_HYPHEN, HyphenationType::BREAK_AND_REPLACE_WITH_HYPHEN, HyphenationType::BREAK_AND_INSERT_HYPHEN_AT_NEXT_LINE, HyphenationType::BREAK_AND_INSERT_HYPHEN_AND_ZWJ, }; uint16_t specialChars[] = { 0x000A, 0x000D, 0x0009, 0x002D, 0x00A0, 0x00AD, 0x00B7, 0x058A, 0x05BE, 0x1400, 0x200D, 0x2010, }; const uint16_t MAX_STR_LEN = 256; // Function to generate StringPiece from a vector by pushing random valued elements using fdp U16StringPiece generateStringPiece(FuzzedDataProvider* fdp) { uint16_t size = fdp->ConsumeIntegralInRange(0, (fdp->remaining_bytes() / 3)); std::vector v; for (uint16_t i = 0; i < size; ++i) { // To randomize the insertion of special characters if (fdp->ConsumeBool()) { v.push_back(fdp->PickValueInArray(specialChars)); } else { v.push_back(fdp->ConsumeIntegral()); } } return U16StringPiece(v); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); uint8_t minPrefix = fdp.ConsumeIntegral(); uint8_t minSuffix = fdp.ConsumeIntegral(); std::string locale = fdp.ConsumeRandomLengthString(MAX_STR_LEN); std::vector patternData(fdp.ConsumeIntegralInRange(0, 256)); Hyphenator* hyphenator = Hyphenator::loadBinary(&patternData[0], patternData.size(), minPrefix, minSuffix, locale); // To randomize the API calls while (fdp.remaining_bytes() > 0) { auto func = fdp.PickValueInArray>({ [&]() { addHyphenator(locale, hyphenator); }, [&]() { auto fromLocaleString = fdp.ConsumeRandomLengthString(MAX_STR_LEN); auto toLocaleString = fdp.ConsumeRandomLengthString(MAX_STR_LEN); addHyphenatorAlias(fromLocaleString, toLocaleString); }, [&]() { packHyphenEdit(fdp.PickValueInArray(StartHyphenEdits), fdp.PickValueInArray(EndHyphenEdits)); }, [&]() { auto textBuf = generateStringPiece(&fdp); std::vector result; result.push_back(fdp.PickValueInArray(HyphenationTypes)); hyphenator->hyphenate(textBuf, &result); }, // Get the list of locales and invoke the API for each one of them [&]() { uint32_t id = registerLocaleList(fdp.ConsumeRandomLengthString(MAX_STR_LEN)); const LocaleList& locales = LocaleListCache::getById(id); for (size_t i = 0; i < locales.size(); ++i) { HyphenatorMap::lookup(locales[i]); } }, [&]() { getHyphenString(endHyphenEdit(fdp.ConsumeIntegral())); }, [&]() { getHyphenString(startHyphenEdit(fdp.ConsumeIntegral())); }, [&]() { isInsertion(endHyphenEdit(fdp.ConsumeIntegral())); }, [&]() { isInsertion(startHyphenEdit(fdp.ConsumeIntegral())); }, [&]() { editForThisLine(fdp.PickValueInArray(HyphenationTypes)); }, [&]() { editForNextLine(fdp.PickValueInArray(HyphenationTypes)); }, [&]() { isReplacement(endHyphenEdit(fdp.ConsumeIntegral())); }, }); func(); } return 0; }