Coverage Report

Created: 2026-06-07 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}