1 // © 2019 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3
4 #include <array>
5 #include <cstring>
6
7 #include "fuzzer_utils.h"
8 #include "unicode/coll.h"
9 #include "unicode/localpointer.h"
10 #include "unicode/locid.h"
11
12 IcuEnvironment* env = new IcuEnvironment();
13
14 static const std::array<icu::Collator::ECollationStrength, 5> kStrength = {
15 icu::Collator::PRIMARY,
16 icu::Collator::SECONDARY,
17 icu::Collator::TERTIARY,
18 icu::Collator::QUATERNARY,
19 icu::Collator::IDENTICAL
20 };
21
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)22 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
23 UErrorCode status = U_ZERO_ERROR;
24
25 uint16_t rnd16;
26
27 if (size < 2 + sizeof(rnd16))
28 return 0;
29
30 std::memcpy(&rnd16, data, sizeof(rnd16));
31 size -= sizeof(rnd16);
32 data += sizeof(rnd16);
33 icu::Collator::ECollationStrength strength = kStrength[rnd16 % kStrength.size()];
34 const icu::Locale& locale = GetRandomLocale(rnd16 / kStrength.size());
35
36 // Limit the comparison size to 4096 to avoid unnecessary timeout
37 if (size > 4096) {
38 size = 4096;
39 }
40 std::unique_ptr<char16_t[]> compbuff1(new char16_t[size/4]);
41 std::memcpy(compbuff1.get(), data, (size/4)*2);
42 std::unique_ptr<char16_t[]> compbuff2(new char16_t[size/4]);
43 std::memcpy(compbuff2.get(), data + size/2, (size/4)*2);
44
45
46 icu::LocalPointer<icu::Collator> fuzzCollator(
47 icu::Collator::createInstance(locale, status), status);
48 if (U_SUCCESS(status)) {
49
50 fuzzCollator->setStrength(strength);
51
52 fuzzCollator->compare(compbuff1.get(), size/4,
53 compbuff2.get(), size/4);
54 }
55 status = U_ZERO_ERROR;
56
57 std::string str(reinterpret_cast<const char*>(data), size);
58 fuzzCollator.adoptInstead(
59 icu::Collator::createInstance(icu::Locale(str.c_str()), status));
60 return 0;
61 }
62