blob: 1fa4d95e574a2fa0f4d2f10baaa6cfcfa7fac994 [file] [log] [blame]
/******************************************************************************
*
* 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 <fuzzer/FuzzedDataProvider.h>
#include <minikin/Hyphenator.h>
#include <iostream>
#include <string>
#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<uint16_t>(0, (fdp->remaining_bytes() / 3));
std::vector<uint16_t> 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<uint16_t>());
}
}
return U16StringPiece(v);
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);
uint8_t minPrefix = fdp.ConsumeIntegral<size_t>();
uint8_t minSuffix = fdp.ConsumeIntegral<size_t>();
std::string locale = fdp.ConsumeRandomLengthString(MAX_STR_LEN);
std::vector<uint8_t> patternData(fdp.ConsumeIntegralInRange<uint32_t>(0, 256));
Hyphenator* hyphenator = Hyphenator::loadBinary(&patternData[0], minPrefix, minSuffix, locale);
// To randomize the API calls
while (fdp.remaining_bytes() > 0) {
auto func = fdp.PickValueInArray<const std::function<void()>>({
[&]() { 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<HyphenationType> 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<uint8_t>())); },
[&]() { getHyphenString(startHyphenEdit(fdp.ConsumeIntegral<uint8_t>())); },
[&]() { isInsertion(endHyphenEdit(fdp.ConsumeIntegral<uint8_t>())); },
[&]() { isInsertion(startHyphenEdit(fdp.ConsumeIntegral<uint8_t>())); },
[&]() { editForThisLine(fdp.PickValueInArray(HyphenationTypes)); },
[&]() { editForNextLine(fdp.PickValueInArray(HyphenationTypes)); },
[&]() { isReplacement(endHyphenEdit(fdp.ConsumeIntegral<uint8_t>())); },
});
func();
}
return 0;
}