xref: /aosp_15_r20/external/cronet/third_party/icu/fuzzers/icu_appendable_fuzzer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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