/src/icu/icu4c/source/test/fuzzer/plurrule_fuzzer.cpp
Line | Count | Source |
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 | | |
14 | 33.0k | void TestPluralRules(icu::PluralRules* pp, int32_t number, double dbl, UErrorCode& status) { |
15 | 33.0k | if (U_FAILURE(status)) { |
16 | 10.8k | return; |
17 | 10.8k | } |
18 | 22.2k | pp->select(number); |
19 | 22.2k | pp->select(dbl); |
20 | 22.2k | } |
21 | | |
22 | | void TestPluralRulesWithLocale( |
23 | 9.43k | const icu::Locale& locale, int32_t number, double dbl, UPluralType type, UErrorCode& status) { |
24 | 9.43k | if (U_FAILURE(status)) { |
25 | 0 | return; |
26 | 0 | } |
27 | 9.43k | std::unique_ptr<icu::PluralRules> pp(icu::PluralRules::forLocale(locale, status)); |
28 | 9.43k | TestPluralRules(pp.get(), number, dbl, status); |
29 | | |
30 | 9.43k | status = U_ZERO_ERROR; |
31 | 9.43k | pp.reset(icu::PluralRules::forLocale(locale, type, status)); |
32 | 9.43k | TestPluralRules(pp.get(), number, dbl, status); |
33 | | |
34 | 9.43k | type = static_cast<UPluralType>( |
35 | 9.43k | static_cast<int>(type) % (static_cast<int>(UPLURAL_TYPE_COUNT))); |
36 | | |
37 | 9.43k | status = U_ZERO_ERROR; |
38 | 9.43k | pp.reset(icu::PluralRules::forLocale(locale, type, status)); |
39 | 9.43k | TestPluralRules(pp.get(), number, dbl, status); |
40 | 9.43k | } |
41 | | |
42 | 4.72k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
43 | 4.72k | uint16_t rnd; |
44 | 4.72k | int32_t number; |
45 | 4.72k | double dbl; |
46 | 4.72k | UPluralType type; |
47 | 4.72k | if (size > 5000) { |
48 | 6 | size = 5000; |
49 | 6 | } |
50 | 4.72k | if (size < sizeof(rnd) + sizeof(number) + sizeof(dbl) + sizeof(type)) return 0; |
51 | 4.71k | icu::StringPiece fuzzData(reinterpret_cast<const char *>(data), size); |
52 | | |
53 | 4.71k | std::memcpy(&rnd, fuzzData.data(), sizeof(rnd)); |
54 | 4.71k | icu::Locale locale = GetRandomLocale(rnd); |
55 | 4.71k | fuzzData.remove_prefix(sizeof(rnd)); |
56 | | |
57 | 4.71k | std::memcpy(&number, fuzzData.data(), sizeof(number)); |
58 | 4.71k | fuzzData.remove_prefix(sizeof(number)); |
59 | | |
60 | 4.71k | std::memcpy(&dbl, fuzzData.data(), sizeof(dbl)); |
61 | 4.71k | fuzzData.remove_prefix(sizeof(dbl)); |
62 | | |
63 | 4.71k | std::memcpy(&type, fuzzData.data(), sizeof(type)); |
64 | 4.71k | fuzzData.remove_prefix(sizeof(type)); |
65 | | |
66 | 4.71k | size_t len = fuzzData.size() / sizeof(char16_t); |
67 | 4.71k | icu::UnicodeString text(false, reinterpret_cast<const char16_t*>(fuzzData.data()), len); |
68 | | |
69 | 4.71k | UErrorCode status = U_ZERO_ERROR; |
70 | 4.71k | std::unique_ptr<icu::PluralRules> pp( |
71 | 4.71k | icu::PluralRules::createRules(text, status)); |
72 | 4.71k | TestPluralRules(pp.get(), number, dbl, status); |
73 | | |
74 | 4.71k | status = U_ZERO_ERROR; |
75 | 4.71k | TestPluralRulesWithLocale(locale, number, dbl, type, status); |
76 | | |
77 | 4.71k | std::string str(fuzzData.data(), fuzzData.size()); // ensure null-terminate |
78 | | // by std::string c_str |
79 | 4.71k | icu::Locale locale2(str.c_str()); |
80 | | |
81 | 4.71k | status = U_ZERO_ERROR; |
82 | 4.71k | TestPluralRulesWithLocale(locale2, number, dbl, type, status); |
83 | | return EXIT_SUCCESS; |
84 | 4.72k | } |