• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <fuzzer/FuzzedDataProvider.h>
18 #include <algorithm>
19 /**
20  * A thread-safe interface to the FuzzedDataProvider
21  */
22 class ThreadSafeFuzzedDataProvider : FuzzedDataProvider {
23 private:
24     std::mutex mLock;
25 
26 public:
ThreadSafeFuzzedDataProvider(const uint8_t * data,size_t size)27     ThreadSafeFuzzedDataProvider(const uint8_t* data, size_t size)
28           : FuzzedDataProvider(data, size) {}
29 
30     template <typename T>
ConsumeBytes(size_t num_bytes)31     std::vector<T> ConsumeBytes(size_t num_bytes) {
32         std::scoped_lock _l(mLock);
33         return FuzzedDataProvider::ConsumeBytes<T>(num_bytes);
34     }
35 
36     template <typename T>
ConsumeBytesWithTerminator(size_t num_bytes,T terminator)37     std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator) {
38         std::scoped_lock _l(mLock);
39         return FuzzedDataProvider::ConsumeBytesWithTerminator<T>(num_bytes, terminator);
40     }
41 
42     template <typename T>
ConsumeRemainingBytes()43     std::vector<T> ConsumeRemainingBytes() {
44         std::scoped_lock _l(mLock);
45         return FuzzedDataProvider::ConsumeRemainingBytes<T>();
46     }
47 
ConsumeBytesAsString(size_t num_bytes)48     std::string ConsumeBytesAsString(size_t num_bytes) {
49         std::scoped_lock _l(mLock);
50         return FuzzedDataProvider::ConsumeBytesAsString(num_bytes);
51     }
52 
ConsumeRandomLengthString(size_t max_length)53     std::string ConsumeRandomLengthString(size_t max_length) {
54         std::scoped_lock _l(mLock);
55         return FuzzedDataProvider::ConsumeRandomLengthString(max_length);
56     }
57 
ConsumeRandomLengthString()58     std::string ConsumeRandomLengthString() {
59         std::scoped_lock _l(mLock);
60         return FuzzedDataProvider::ConsumeRandomLengthString();
61     }
62 
63     // Converting the string to a UTF-8 string by setting the prefix bits of each
64     // byte according to UTF-8 encoding rules.
ConsumeRandomLengthUtf8String(size_t max_length)65     std::string ConsumeRandomLengthUtf8String(size_t max_length) {
66         std::scoped_lock _l(mLock);
67         std::string result = FuzzedDataProvider::ConsumeRandomLengthString(max_length);
68         size_t remaining_bytes = result.length(), idx = 0;
69         while (remaining_bytes > 0) {
70             size_t random_byte_size = FuzzedDataProvider::ConsumeIntegralInRange(1, 4);
71             size_t byte_size = std::min(random_byte_size, remaining_bytes);
72             switch (byte_size) {
73                 // Prefix byte: 0xxxxxxx
74                 case 1:
75                     result[idx++] &= 0b01111111;
76                     break;
77                 // Prefix bytes: 110xxxxx 10xxxxxx
78                 case 2:
79                     result[idx++] = (result[idx] & 0b00011111) | 0b11000000;
80                     result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
81                     break;
82                 // Prefix bytes: 1110xxxx 10xxxxxx 10xxxxxx
83                 case 3:
84                     result[idx++] = (result[idx] & 0b00001111) | 0b11100000;
85                     result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
86                     result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
87                     break;
88                 // Prefix bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
89                 case 4:
90                     result[idx++] = (result[idx] & 0b00000111) | 0b11110000;
91                     result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
92                     result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
93                     result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
94                     break;
95             }
96             remaining_bytes -= byte_size;
97         }
98         return result;
99     }
100 
ConsumeRemainingBytesAsString()101     std::string ConsumeRemainingBytesAsString() {
102         std::scoped_lock _l(mLock);
103         return FuzzedDataProvider::ConsumeRemainingBytesAsString();
104     }
105 
106     template <typename T>
ConsumeIntegral()107     T ConsumeIntegral() {
108         std::scoped_lock _l(mLock);
109         return FuzzedDataProvider::ConsumeIntegral<T>();
110     }
111 
112     template <typename T>
ConsumeIntegralInRange(T min,T max)113     T ConsumeIntegralInRange(T min, T max) {
114         std::scoped_lock _l(mLock);
115         return FuzzedDataProvider::ConsumeIntegralInRange<T>(min, max);
116     }
117 
118     template <typename T>
ConsumeFloatingPoint()119     T ConsumeFloatingPoint() {
120         std::scoped_lock _l(mLock);
121         return FuzzedDataProvider::ConsumeFloatingPoint<T>();
122     }
123 
124     template <typename T>
ConsumeFloatingPointInRange(T min,T max)125     T ConsumeFloatingPointInRange(T min, T max) {
126         std::scoped_lock _l(mLock);
127         return FuzzedDataProvider::ConsumeFloatingPointInRange<T>(min, max);
128     }
129 
130     template <typename T>
ConsumeProbability()131     T ConsumeProbability() {
132         std::scoped_lock _l(mLock);
133         return FuzzedDataProvider::ConsumeProbability<T>();
134     }
135 
ConsumeBool()136     bool ConsumeBool() {
137         std::scoped_lock _l(mLock);
138         return FuzzedDataProvider::ConsumeBool();
139     }
140 
141     template <typename T>
ConsumeEnum()142     T ConsumeEnum() {
143         std::scoped_lock _l(mLock);
144         return FuzzedDataProvider::ConsumeEnum<T>();
145     }
146 
147     template <typename T, size_t size>
PickValueInArray(const T (& array)[size])148     T PickValueInArray(const T (&array)[size]) {
149         std::scoped_lock _l(mLock);
150         return FuzzedDataProvider::PickValueInArray(array);
151     }
152 
153     template <typename T, size_t size>
PickValueInArray(const std::array<T,size> & array)154     T PickValueInArray(const std::array<T, size>& array) {
155         std::scoped_lock _l(mLock);
156         return FuzzedDataProvider::PickValueInArray(array);
157     }
158 
159     template <typename T>
PickValueInArray(std::initializer_list<const T> list)160     T PickValueInArray(std::initializer_list<const T> list) {
161         std::scoped_lock _l(mLock);
162         return FuzzedDataProvider::PickValueInArray(list);
163     }
164 
ConsumeData(void * destination,size_t num_bytes)165     size_t ConsumeData(void* destination, size_t num_bytes) {
166         std::scoped_lock _l(mLock);
167         return FuzzedDataProvider::ConsumeData(destination, num_bytes);
168     }
169 
remaining_bytes()170     size_t remaining_bytes() {
171         std::scoped_lock _l(mLock);
172         return FuzzedDataProvider::remaining_bytes();
173     }
174 };
175