• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* fuzzer_encoder_v2
2  * Copyright (C) 2022  Xiph.Org Foundation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the Xiph.org Foundation nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <cstdlib>
33 #include <cstring> /* for memcpy */
34 #include "FLAC/stream_encoder.h"
35 #include "FLAC/metadata.h"
36 extern "C" {
37 #include "share/private.h"
38 }
39 #include "common.h"
40 
41 /* This C++ fuzzer uses the FLAC and not FLAC++ because the latter lacks a few
42  * hidden functions like FLAC__stream_encoder_disable_constant_subframes. It
43  * is still processed by a C++ compiler because that's what oss-fuzz expects */
44 
45 
write_callback(const FLAC__StreamEncoder * encoder,const FLAC__byte buffer[],size_t bytes,uint32_t samples,uint32_t current_frame,void * client_data)46 static FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, uint32_t current_frame, void *client_data)
47 {
48 	(void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
49 	return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
50 }
51 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)52 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
53 {
54 	FLAC__bool encoder_valid = true;
55 	FLAC__StreamEncoder *encoder = 0;
56 	FLAC__StreamEncoderState state;
57 	FLAC__StreamMetadata *metadata[16] = {NULL};
58 	unsigned num_metadata = 0;
59 	FLAC__StreamMetadata_VorbisComment_Entry VorbisCommentField;
60 
61 	unsigned sample_rate, channels, bps;
62 	uint64_t samples_estimate, samples_in_input;
63 	unsigned compression_level, input_data_width, blocksize, max_lpc_order, qlp_coeff_precision, min_residual_partition_order, max_residual_partition_order, metadata_mask, instruction_set_disable_mask;
64 	FLAC__bool ogg, write_to_file, interleaved;
65 
66 	FLAC__bool data_bools[24];
67 
68 	/* Set alloc threshold. This check was added later and no spare config
69 	 * bytes were left, so we're reusing the sample rate as that of little
70 	 * consequence to the encoder and decoder except reading the frame header */
71 
72 	if(size < 3)
73 		return 0;
74 	alloc_check_threshold = data[2];
75 	alloc_check_counter = 0;
76 
77 	/* allocate the encoder */
78 	if((encoder = FLAC__stream_encoder_new()) == NULL) {
79 		fprintf(stderr, "ERROR: allocating encoder\n");
80 		return 1;
81 	}
82 
83 	/* Use first 20 byte for configuration */
84 	if(size < 20){
85 		FLAC__stream_encoder_delete(encoder);
86 		return 0;
87 	}
88 
89 	/* First 3 byte for sample rate, 4th byte for channels, 5th byte for bps */
90 	sample_rate = ((unsigned)data[0] << 16) + ((unsigned)data[1] << 8) + data[2];
91 	channels = data[3];
92 	bps = data[4];
93 
94 	/* Number of samples estimate, format accepts 36-bit max */
95 	samples_estimate = ((uint64_t)data[5] << 32) + ((unsigned)data[6] << 24) + ((unsigned)data[7] << 16) + ((unsigned)data[8] << 8) + data[9];
96 
97 	compression_level = data[10]&0b1111;
98 	input_data_width = 1 + (data[10]>>4)%4;
99 	samples_in_input = (size-20)/input_data_width;
100 	blocksize = ((unsigned)data[11] << 8) + (unsigned)data[12];
101 	max_lpc_order = data[13];
102 	qlp_coeff_precision = data[14];
103 	min_residual_partition_order = data[15] & 0b1111;
104 	max_residual_partition_order = data[15] & 0b11110000;
105 	metadata_mask = data[16];
106 	instruction_set_disable_mask = data[17];
107 
108 	/* Get array of bools from configuration */
109 	for(int i = 0; i < 16; i++)
110 		data_bools[i] = data[18+i/8] & (1 << (i % 8));
111 
112 	ogg = data_bools[0];
113 	interleaved = data_bools[1];
114 	write_to_file = data_bools[13];
115 
116 	/* Set input and process parameters */
117 	encoder_valid &= FLAC__stream_encoder_set_verify(encoder, data_bools[2]);
118 	encoder_valid &= FLAC__stream_encoder_set_channels(encoder, channels);
119 	encoder_valid &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
120 	encoder_valid &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
121 	encoder_valid &= FLAC__stream_encoder_set_total_samples_estimate(encoder, samples_estimate);
122 	encoder_valid &= FLAC__stream_encoder_disable_instruction_set(encoder, instruction_set_disable_mask);
123 	encoder_valid &= FLAC__stream_encoder_set_limit_min_bitrate(encoder, data_bools[15]);
124 
125 	/* Set compression related parameters */
126 	encoder_valid &= FLAC__stream_encoder_set_compression_level(encoder, compression_level);
127 	if(data_bools[3]){
128 		/* Bias towards regular compression levels */
129 		encoder_valid &= FLAC__stream_encoder_set_blocksize(encoder, blocksize);
130 		encoder_valid &= FLAC__stream_encoder_set_max_lpc_order(encoder, max_lpc_order);
131 		encoder_valid &= FLAC__stream_encoder_set_qlp_coeff_precision(encoder, qlp_coeff_precision);
132 		encoder_valid &= FLAC__stream_encoder_set_min_residual_partition_order(encoder, min_residual_partition_order);
133 
134 		/* With large inputs and expensive options enabled, the fuzzer can get *really* slow.
135 		 * Some combinations can make the fuzzer timeout (>60 seconds). However, while combining
136 		 * options makes the fuzzer slower, most options do not expose new code when combined.
137 		 * Therefore, combining slow options is disabled for large inputs. Any input containing
138 		 * more than 65536 * 2 samples (max blocksize, stereo) is considered large
139 		 */
140 		if(samples_in_input < (2*65536)) {
141 			encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, data_bools[4]);
142 			encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, data_bools[5]);
143 			encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, data_bools[6]);
144 			encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, data_bools[7]);
145 			/* Combining model search, precision search and a high residual partition order is especially
146 			 * expensive, so limit that even further. This high partition order can only be set on
147 			 * large blocksize and with streamable subset disabled */
148 			if(samples_in_input < (2 * 4609) || data_bools[4] || !data_bools[7] || !data_bools[5] || max_residual_partition_order < 9 || blocksize < 4609)
149 				encoder_valid &= FLAC__stream_encoder_set_max_residual_partition_order(encoder, max_residual_partition_order);
150 		}
151 		else {
152 			if(!data_bools[4])
153 				encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, false);
154 			else if(data_bools[6])
155 				encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, true);
156 			else if(data_bools[7])
157 				encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, true);
158 			else if(data_bools[5])
159 				encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, true);
160 		}
161 		encoder_valid &= FLAC__stream_encoder_set_do_mid_side_stereo(encoder, data_bools[8]);
162 		encoder_valid &= FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, data_bools[9]);
163 
164 		encoder_valid &= FLAC__stream_encoder_disable_constant_subframes(encoder, data_bools[10]);
165 		encoder_valid &= FLAC__stream_encoder_disable_fixed_subframes(encoder, data_bools[11]);
166 		encoder_valid &= FLAC__stream_encoder_disable_verbatim_subframes(encoder, data_bools[12]);
167 	}
168 
169 	/* Disable alloc check if requested */
170 	if(encoder_valid && data_bools[14])
171 		alloc_check_threshold = INT32_MAX;
172 
173 	/* add metadata */
174 	if(encoder_valid && (metadata_mask & 1)) {
175 		if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO)) == NULL)
176 			encoder_valid = false;
177 		else
178 			num_metadata++;
179 	}
180 	if(encoder_valid && (metadata_mask & 2) && size > 21){
181 		if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL)
182 			encoder_valid = false;
183 		else {
184 			metadata[num_metadata++]->length = (((unsigned)data[20]) << 8) + (unsigned)(data[21]);
185 		}
186 	}
187 	if(encoder_valid && (metadata_mask & 4) && size > 20){
188 		FLAC__byte * application_data = (FLAC__byte *)malloc(size-20);
189 		if(0 != application_data && ((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) == NULL))
190 			encoder_valid = false;
191 		else {
192 			memcpy(application_data,data+20,size-20);
193 			FLAC__metadata_object_application_set_data(metadata[num_metadata++], application_data, size-20, 0);
194 		}
195 	}
196 	if(encoder_valid && (metadata_mask & 8) && size > 25){
197 		if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE)) == NULL)
198 			encoder_valid = false;
199 		else {
200 			unsigned seekpoint_spacing = ((unsigned)data[22] << 8) + data[23];
201 			unsigned total_samples_for_seekpoints = ((unsigned)data[24] << 8) + data[25];
202 			FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(metadata[num_metadata++], seekpoint_spacing, total_samples_for_seekpoints);
203 		}
204 	}
205 	if(encoder_valid && (metadata_mask & 16)){
206 		if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) != NULL) {
207 			bool vorbiscomment_valid = true;
208 			/* Append a vorbis comment */
209 			if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Nothing to �� report"))
210 				vorbiscomment_valid = false;
211 			else {
212 				if(FLAC__metadata_object_vorbiscomment_append_comment(metadata[num_metadata], VorbisCommentField, false)) {
213 
214 					/* Insert a vorbis comment at the first index */
215 					if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Still nothing to report ����"))
216 						vorbiscomment_valid = false;
217 					else
218 						if(!FLAC__metadata_object_vorbiscomment_insert_comment(metadata[num_metadata], 0, VorbisCommentField, false)) {
219 							free(VorbisCommentField.entry);
220 							vorbiscomment_valid = false;
221 						}
222 				}
223 				else {
224 					free(VorbisCommentField.entry);
225 					vorbiscomment_valid = false;
226 				}
227 			}
228 			if(!vorbiscomment_valid) {
229 				FLAC__metadata_object_delete(metadata[num_metadata]);
230 				metadata[num_metadata] = 0;
231 			}
232 			else
233 				num_metadata++;
234 		}
235 	}
236 	if(encoder_valid && (metadata_mask & 32)){
237 		if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)) != NULL) {
238 			if(!FLAC__metadata_object_cuesheet_insert_blank_track(metadata[num_metadata],0)) {
239 				FLAC__metadata_object_delete(metadata[num_metadata]);
240 				metadata[num_metadata] = 0;
241 			}
242 			else {
243 				if(!FLAC__metadata_object_cuesheet_track_insert_blank_index(metadata[num_metadata],0,0)) {
244 					FLAC__metadata_object_delete(metadata[num_metadata]);
245 					metadata[num_metadata] = 0;
246 				}
247 				else {
248 					metadata[num_metadata]->data.cue_sheet.tracks[0].number = 1;
249 					num_metadata++;
250 				}
251 			}
252 		}
253 	}
254 	if(encoder_valid && (metadata_mask & 64)){
255 		if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)) != NULL) {
256 			num_metadata++;
257 		}
258 	}
259 	if(encoder_valid && (metadata_mask & 128)){
260 		if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_UNDEFINED)) != NULL) {
261 			metadata[num_metadata]->length = 24;
262 			metadata[num_metadata]->data.unknown.data = (FLAC__byte *)calloc(24, 1);
263 			num_metadata++;
264 		}
265 	}
266 
267 	if(num_metadata && encoder_valid)
268 			encoder_valid = FLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
269 
270 	/* initialize encoder */
271 	if(encoder_valid) {
272 		FLAC__StreamEncoderInitStatus init_status;
273 		if(ogg)
274 			if(write_to_file)
275 				init_status = FLAC__stream_encoder_init_ogg_file(encoder, "/tmp/tmp.flac", NULL, NULL);
276 			else
277 				init_status = FLAC__stream_encoder_init_ogg_stream(encoder, NULL, write_callback, NULL, NULL, NULL, NULL);
278 		else
279 			if(write_to_file)
280 				init_status = FLAC__stream_encoder_init_file(encoder, "/tmp/tmp.flac", NULL, NULL);
281 			else
282 				init_status = FLAC__stream_encoder_init_stream(encoder, write_callback, NULL, NULL, NULL, NULL);
283 		if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
284 			encoder_valid = false;
285 		}
286 	}
287 
288 
289 	/* send samples to encoder */
290 	if(encoder_valid && size > (input_data_width*channels+26)) {
291 		unsigned samples = (size - 26)/input_data_width/channels;
292 		const uint8_t * pcm_data = data + 26;
293 		int32_t * data_as_int32 = (int32_t *)malloc(4*samples*channels);
294 		if(0 != data_as_int32){
295 			for(unsigned i = 0; i < samples*channels; i++)
296 				if(input_data_width == 1)
297 					data_as_int32[i] = (int32_t)pcm_data[i] - 0x80;
298 				else if(input_data_width == 2)
299 					data_as_int32[i] = (((int32_t)pcm_data[i*2] << 8) + pcm_data[i*2+1]) - 0x8000;
300 				else if(input_data_width == 3)
301 					data_as_int32[i] = (((int32_t)pcm_data[i*3] << 16) + ((int32_t)pcm_data[i*3+1] << 8) + pcm_data[i*3+2]) - 0x800000;
302 				else if(input_data_width == 4)
303 					data_as_int32[i] = (((int64_t)pcm_data[i*4] << 24) + ((int32_t)pcm_data[i*4+1] << 16) + ((int32_t)pcm_data[i*4+2] << 8) + pcm_data[i*4+3]) - 0x80000000;
304 
305 			/* feed samples to encoder */
306 			if(interleaved)
307 				encoder_valid = FLAC__stream_encoder_process_interleaved(encoder, data_as_int32, samples);
308 			else {
309 				encoder_valid = FLAC__stream_encoder_process(encoder, (const int32_t*[]){data_as_int32,
310 				                                                       data_as_int32+samples,
311 				                                                       data_as_int32+samples*2,
312 				                                                       data_as_int32+samples*3,
313 				                                                       data_as_int32+samples*4, data_as_int32+samples*5, data_as_int32+samples*6, data_as_int32+samples*7}, samples);
314 			}
315 			free(data_as_int32);
316 		}
317 		else {
318 			encoder_valid = false;
319 		}
320 	}
321 
322 	state = FLAC__stream_encoder_get_state(encoder);
323 	if(!(state == FLAC__STREAM_ENCODER_OK ||
324 	     state == FLAC__STREAM_ENCODER_UNINITIALIZED ||
325 	     state == FLAC__STREAM_ENCODER_CLIENT_ERROR ||
326 	     ((state == FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR ||
327                state == FLAC__STREAM_ENCODER_FRAMING_ERROR ||
328 	       (state == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR &&
329 	        FLAC__stream_encoder_get_verify_decoder_state(encoder) == FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR)) &&
330 	      alloc_check_threshold < INT32_MAX))) {
331 		fprintf(stderr,"-----\nERROR: stream encoder returned %s\n-----\n",FLAC__stream_encoder_get_resolved_state_string(encoder));
332 		if(state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) {
333 			uint32_t frame_number, channel, sample_number;
334 			FLAC__int32 expected, got;
335 			FLAC__stream_encoder_get_verify_decoder_error_stats(encoder, NULL, &frame_number, &channel, &sample_number, &expected, &got);
336 			fprintf(stderr,"Frame number %d\nChannel %d\n Sample number %d\nExpected value %d\nGot %d\n", frame_number, channel, sample_number, expected, got);
337 		}
338 		abort();
339 	}
340 
341 	FLAC__stream_encoder_finish(encoder);
342 
343 	/* now that encoding is finished, the metadata can be freed */
344 	for(unsigned i = 0; i < 16; i++)
345 		if(0 != metadata[i])
346 			FLAC__metadata_object_delete(metadata[i]);
347 
348 	FLAC__stream_encoder_delete(encoder);
349 
350 	return 0;
351 }
352 
353