1 // © 2023 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3
4 // Fuzzer for ICU PluralRules.
5
6 #include <cstring>
7
8 #include "fuzzer_utils.h"
9
10 #include "unicode/plurrule.h"
11 #include "unicode/locid.h"
12
13
TestPluralRules(icu::PluralRules * pp,int32_t number,double dbl,UErrorCode & status)14 void TestPluralRules(icu::PluralRules* pp, int32_t number, double dbl, UErrorCode& status) {
15 if (U_FAILURE(status)) {
16 return;
17 }
18 pp->select(number);
19 pp->select(dbl);
20 }
21
TestPluralRulesWithLocale(const icu::Locale & locale,int32_t number,double dbl,UPluralType type,UErrorCode & status)22 void TestPluralRulesWithLocale(
23 const icu::Locale& locale, int32_t number, double dbl, UPluralType type, UErrorCode& status) {
24 if (U_FAILURE(status)) {
25 return;
26 }
27 std::unique_ptr<icu::PluralRules> pp(icu::PluralRules::forLocale(locale, status));
28 TestPluralRules(pp.get(), number, dbl, status);
29
30 status = U_ZERO_ERROR;
31 pp.reset(icu::PluralRules::forLocale(locale, type, status));
32 TestPluralRules(pp.get(), number, dbl, status);
33
34 type = static_cast<UPluralType>(
35 static_cast<int>(type) % (static_cast<int>(UPLURAL_TYPE_COUNT)));
36
37 status = U_ZERO_ERROR;
38 pp.reset(icu::PluralRules::forLocale(locale, type, status));
39 TestPluralRules(pp.get(), number, dbl, status);
40 }
41
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)42 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
43 uint16_t rnd;
44 int32_t number;
45 double dbl;
46 UPluralType type;
47 if (size > 5000) {
48 size = 5000;
49 }
50 if (size < sizeof(rnd) + sizeof(number) + sizeof(dbl) + sizeof(type)) return 0;
51 icu::StringPiece fuzzData(reinterpret_cast<const char *>(data), size);
52
53 std::memcpy(&rnd, fuzzData.data(), sizeof(rnd));
54 icu::Locale locale = GetRandomLocale(rnd);
55 fuzzData.remove_prefix(sizeof(rnd));
56
57 std::memcpy(&number, fuzzData.data(), sizeof(number));
58 fuzzData.remove_prefix(sizeof(number));
59
60 std::memcpy(&dbl, fuzzData.data(), sizeof(dbl));
61 fuzzData.remove_prefix(sizeof(dbl));
62
63 std::memcpy(&type, fuzzData.data(), sizeof(type));
64 fuzzData.remove_prefix(sizeof(type));
65
66 size_t len = fuzzData.size() / sizeof(char16_t);
67 icu::UnicodeString text(false, reinterpret_cast<const char16_t*>(fuzzData.data()), len);
68
69 UErrorCode status = U_ZERO_ERROR;
70 std::unique_ptr<icu::PluralRules> pp(
71 icu::PluralRules::createRules(text, status));
72 TestPluralRules(pp.get(), number, dbl, status);
73
74 status = U_ZERO_ERROR;
75 TestPluralRulesWithLocale(locale, number, dbl, type, status);
76
77 std::string str(fuzzData.data(), fuzzData.size()); // ensure null-terminate
78 // by std::string c_str
79 icu::Locale locale2(str.c_str());
80
81 status = U_ZERO_ERROR;
82 TestPluralRulesWithLocale(locale2, number, dbl, type, status);
83 return EXIT_SUCCESS;
84 }
85