1 // Copyright 2019 The Chromium Authors. All rights reserved.
2
3 #include <fuzzer/FuzzedDataProvider.h>
4 #include <stddef.h>
5 #include <stdint.h>
6 #include <vector>
7 #include "third_party/icu/fuzzers/fuzzer_utils.h"
8 #include "third_party/icu/source/common/unicode/appendable.h"
9
10 static IcuEnvironment* env = new IcuEnvironment;
11
12 constexpr size_t kMaxInitialSize = 64;
13 constexpr size_t kMaxReserveSize = 4096;
14 constexpr size_t kMaxAppendLength = 64;
15 constexpr size_t kMaxAdditionalDesiredSize = 4096;
16
17 constexpr size_t kScratchBufSize = 4096;
18 char16_t scratch_buf[kScratchBufSize];
19
20 enum class AppendableApi {
21 AppendCodeUnit,
22 AppendCodePoint,
23 AppendString,
24 ReserveAppendCapacity,
25 GetAppendBuffer,
26 kMaxValue = GetAppendBuffer
27 };
28
29 // Entry point for LibFuzzer.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)30 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
31 FuzzedDataProvider provider(data, size);
32 auto str(icu::UnicodeString::fromUTF8(
33 provider.ConsumeRandomLengthString(kMaxInitialSize)));
34 icu::UnicodeStringAppendable strAppendable(str);
35
36 while (provider.remaining_bytes() > 0) {
37 switch (provider.ConsumeEnum<AppendableApi>()) {
38 case AppendableApi::AppendCodeUnit:
39 strAppendable.appendCodeUnit(provider.ConsumeIntegral<char16_t>());
40 break;
41 case AppendableApi::AppendCodePoint:
42 strAppendable.appendCodePoint(provider.ConsumeIntegral<UChar32>());
43 break;
44 case AppendableApi::AppendString: {
45 std::string appendChrs8(
46 provider.ConsumeRandomLengthString(kMaxAppendLength));
47 if (appendChrs8.size() == 0)
48 break;
49 std::vector<char16_t> appendChrs(RandomChar16Array(
50 2, reinterpret_cast<const uint8_t*>(appendChrs8.data()),
51 appendChrs8.size()));
52 strAppendable.appendString(appendChrs.data(), appendChrs.size());
53 break;
54 }
55 case AppendableApi::ReserveAppendCapacity:
56 strAppendable.reserveAppendCapacity(
57 provider.ConsumeIntegralInRange<int32_t>(0, kMaxReserveSize));
58 break;
59 case AppendableApi::GetAppendBuffer: {
60 int32_t out_capacity;
61 const auto min_capacity =
62 provider.ConsumeIntegralInRange<int32_t>(1, kScratchBufSize);
63 char16_t* out_buffer = strAppendable.getAppendBuffer(
64 min_capacity,
65 min_capacity + provider.ConsumeIntegralInRange<int32_t>(
66 0, kMaxAdditionalDesiredSize),
67 scratch_buf, kScratchBufSize, &out_capacity);
68 // Write arbitrary value at the end of the buffer.
69 if (out_buffer)
70 out_buffer[out_capacity - 1] = 1;
71 break;
72 }
73 }
74 }
75
76 return 0;
77 }
78