xref: /aosp_15_r20/external/flac/oss-fuzz/reencoder.cc (revision 600f14f40d737144c998e2ec7a483122d3776fbc)
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