1 /* Copyright 2019 Guido Vranken
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject
9 * to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <cstddef>
25 #include <cstdint>
26 #include <limits>
27
28 #include <fuzzing/datasource/datasource.hpp>
29 #include <fuzzing/memory.hpp>
30
31 #include "FLAC++/encoder.h"
32 #include "FLAC++/decoder.h"
33 #include "FLAC++/metadata.h"
34 #include "common.h"
35
36 #define MAX_NUM_METADATA_BLOCKS 2048
37
38 namespace FLAC {
39 namespace Encoder {
40 class FuzzerStream : public Stream {
41 private:
42 // fuzzing::datasource::Datasource& ds;
43 public:
FuzzerStream(fuzzing::datasource::Datasource &)44 FuzzerStream(fuzzing::datasource::Datasource&) :
45 Stream() { }
46
write_callback(const FLAC__byte buffer[],size_t bytes,uint32_t,uint32_t)47 ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], size_t bytes, uint32_t /* samples */, uint32_t /* current_frame */) override {
48 fuzzing::memory::memory_test(buffer, bytes);
49 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
50 }
51 };
52 }
53 namespace Decoder {
54 class FuzzerDecoder : public Stream {
55 private:
56 fuzzing::datasource::Datasource& ds;
57 FLAC::Encoder::FuzzerStream& encoder;
58 public:
FuzzerDecoder(fuzzing::datasource::Datasource & dsrc,FLAC::Encoder::FuzzerStream & encoder_arg)59 FuzzerDecoder(fuzzing::datasource::Datasource& dsrc, FLAC::Encoder::FuzzerStream& encoder_arg) :
60 Stream(), ds(dsrc), encoder(encoder_arg) { }
61
62 ::FLAC__StreamMetadata * metadata_blocks[MAX_NUM_METADATA_BLOCKS] = {0};
63 int num_metadata_blocks = 0;
64
metadata_callback(const::FLAC__StreamMetadata * metadata)65 void metadata_callback(const ::FLAC__StreamMetadata *metadata) override {
66 if(num_metadata_blocks < MAX_NUM_METADATA_BLOCKS)
67 if((metadata_blocks[num_metadata_blocks] = FLAC__metadata_object_clone(metadata)) != NULL)
68 num_metadata_blocks++;
69 }
70
read_callback(FLAC__byte buffer[],size_t * bytes)71 ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes) override {
72 try {
73 const size_t maxCopySize = *bytes;
74
75 if ( maxCopySize > 0 ) {
76 /* memset just to test if this overwrites anything, and triggers ASAN */
77 memset(buffer, 0, maxCopySize);
78 }
79
80 const auto data = ds.GetData(0);
81 const auto dataSize = data.size();
82 const auto copySize = std::min(maxCopySize, dataSize);
83
84 if ( copySize > 0 ) {
85 memcpy(buffer, data.data(), copySize);
86 }
87
88 *bytes = copySize;
89
90 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
91 } catch ( ... ) {
92 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
93 }
94 }
95
write_callback(const::FLAC__Frame * frame,const FLAC__int32 * const buffer[])96 ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) override {
97 {
98 fuzzing::memory::memory_test(&(frame->header), sizeof(frame->header));
99 fuzzing::memory::memory_test(&(frame->footer), sizeof(frame->footer));
100 }
101
102 {
103 const auto numChannels = get_channels();
104 const size_t bytesPerChannel = frame->header.blocksize * sizeof(FLAC__int32);
105 for (size_t i = 0; i < numChannels; i++) {
106 fuzzing::memory::memory_test(buffer[i], bytesPerChannel);
107 }
108 }
109
110 /* Data is checked, now pass it towards encoder */
111 if(encoder.get_state() == FLAC__STREAM_ENCODER_OK) {
112 if(encoder.get_channels() != get_channels())
113 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
114 if(encoder.get_bits_per_sample() != get_bits_per_sample())
115 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
116 encoder.process(buffer, frame->header.blocksize);
117 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
118 }
119 else
120 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
121 }
error_callback(::FLAC__StreamDecoderErrorStatus status)122 void error_callback(::FLAC__StreamDecoderErrorStatus status) override {
123 fuzzing::memory::memory_test(status);
124 }
125 };
126 }
127 }
128
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)129 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
130 fuzzing::datasource::Datasource ds(data, size);
131 FLAC::Encoder::FuzzerStream encoder(ds);
132 FLAC::Decoder::FuzzerDecoder decoder(ds, encoder);
133
134 try {
135 const int channels = ds.Get<uint8_t>();
136 const int bps = ds.Get<uint8_t>();
137 encoder.set_channels(channels);
138 encoder.set_bits_per_sample(bps);
139
140 {
141 const bool res = encoder.set_streamable_subset(ds.Get<bool>());
142 fuzzing::memory::memory_test(res);
143 }
144 {
145 const bool res = encoder.set_ogg_serial_number(ds.Get<long>());
146 fuzzing::memory::memory_test(res);
147 }
148 {
149 const bool res = encoder.set_verify(ds.Get<bool>());
150 fuzzing::memory::memory_test(res);
151 }
152 {
153 const bool res = encoder.set_compression_level(ds.Get<uint8_t>());
154 fuzzing::memory::memory_test(res);
155 }
156 {
157 const bool res = encoder.set_do_mid_side_stereo(ds.Get<bool>());
158 fuzzing::memory::memory_test(res);
159 }
160 {
161 const bool res = encoder.set_loose_mid_side_stereo(ds.Get<bool>());
162 fuzzing::memory::memory_test(res);
163 }
164 {
165 const bool res = encoder.set_max_lpc_order(ds.Get<uint8_t>());
166 fuzzing::memory::memory_test(res);
167 }
168 {
169 const bool res = encoder.set_qlp_coeff_precision(ds.Get<uint32_t>());
170 fuzzing::memory::memory_test(res);
171 }
172 {
173 const bool res = encoder.set_do_escape_coding(ds.Get<bool>());
174 fuzzing::memory::memory_test(res);
175 }
176 {
177 const bool res = encoder.set_min_residual_partition_order(ds.Get<uint32_t>());
178 fuzzing::memory::memory_test(res);
179 }
180 {
181 const bool res = encoder.set_max_residual_partition_order(ds.Get<uint32_t>());
182 fuzzing::memory::memory_test(res);
183 }
184 {
185 const bool res = encoder.set_total_samples_estimate(ds.Get<uint64_t>());
186 fuzzing::memory::memory_test(res);
187 }
188 {
189 const bool res = encoder.set_blocksize(ds.Get<uint16_t>());
190 fuzzing::memory::memory_test(res);
191 }
192 {
193 const bool res = encoder.set_limit_min_bitrate(ds.Get<bool>());
194 fuzzing::memory::memory_test(res);
195 }
196 {
197 const bool res = encoder.set_sample_rate(ds.Get<uint32_t>());
198 fuzzing::memory::memory_test(res);
199 }
200
201 decoder.set_metadata_respond_all();
202
203 {
204 ::FLAC__StreamDecoderInitStatus ret;
205 if ( ds.Get<bool>() ) {
206 ret = decoder.init();
207 } else {
208 ret = decoder.init_ogg();
209 }
210
211 if ( ret != FLAC__STREAM_DECODER_INIT_STATUS_OK ) {
212 goto end;
213 }
214
215 decoder.process_until_end_of_metadata();
216 if(decoder.num_metadata_blocks > 0)
217 encoder.set_metadata(decoder.metadata_blocks, decoder.num_metadata_blocks);
218 }
219
220 {
221 ::FLAC__StreamEncoderInitStatus ret;
222 if ( ds.Get<bool>() ) {
223 ret = encoder.init();
224 } else {
225 ret = encoder.init_ogg();
226 }
227
228 if ( ret != FLAC__STREAM_ENCODER_INIT_STATUS_OK ) {
229 goto end;
230 }
231 }
232
233 /* These sets must fail, because encoder is already initialized */
234 {
235 bool res = false;
236 res = res || encoder.set_streamable_subset(true);
237 res = res || encoder.set_ogg_serial_number(0);
238 res = res || encoder.set_verify(true);
239 res = res || encoder.set_compression_level(0);
240 res = res || encoder.set_do_exhaustive_model_search(true);
241 res = res || encoder.set_do_mid_side_stereo(true);
242 res = res || encoder.set_loose_mid_side_stereo(true);
243 res = res || encoder.set_apodization("test");
244 res = res || encoder.set_max_lpc_order(0);
245 res = res || encoder.set_qlp_coeff_precision(0);
246 res = res || encoder.set_do_qlp_coeff_prec_search(true);
247 res = res || encoder.set_do_escape_coding(true);
248 res = res || encoder.set_min_residual_partition_order(0);
249 res = res || encoder.set_max_residual_partition_order(0);
250 res = res || encoder.set_rice_parameter_search_dist(0);
251 res = res || encoder.set_total_samples_estimate(0);
252 res = res || encoder.set_channels(channels);
253 res = res || encoder.set_bits_per_sample(16);
254 res = res || encoder.set_limit_min_bitrate(true);
255 res = res || encoder.set_blocksize(3021);
256 res = res || encoder.set_sample_rate(44100);
257 fuzzing::memory::memory_test(res);
258 if(res)
259 abort();
260 }
261
262
263 {
264 /* XORing values as otherwise compiler will optimize, apparently */
265 bool res = false;
266 res = res != encoder.get_streamable_subset();
267 res = res != encoder.get_verify();
268 res = res != encoder.get_do_exhaustive_model_search();
269 res = res != encoder.get_do_mid_side_stereo();
270 res = res != encoder.get_loose_mid_side_stereo();
271 res = res != encoder.get_max_lpc_order();
272 res = res != encoder.get_qlp_coeff_precision();
273 res = res != encoder.get_do_qlp_coeff_prec_search();
274 res = res != encoder.get_do_escape_coding();
275 res = res != encoder.get_min_residual_partition_order();
276 res = res != encoder.get_max_residual_partition_order();
277 res = res != encoder.get_rice_parameter_search_dist();
278 res = res != encoder.get_total_samples_estimate();
279 res = res != encoder.get_channels();
280 res = res != encoder.get_bits_per_sample();
281 res = res != encoder.get_limit_min_bitrate();
282 res = res != encoder.get_blocksize();
283 res = res != encoder.get_sample_rate();
284 fuzzing::memory::memory_test(res);
285 }
286
287 decoder.process_until_end_of_stream();
288
289 } catch ( ... ) { }
290
291 end:
292 {
293 const bool res = encoder.finish();
294 fuzzing::memory::memory_test(res);
295 }
296 {
297 const bool res = decoder.finish();
298 fuzzing::memory::memory_test(res);
299 }
300 for(int i = 0; i < decoder.num_metadata_blocks; i++)
301 FLAC__metadata_object_delete(decoder.metadata_blocks[i]);
302
303 return 0;
304 }
305