1 /* fuzzer_seek
2 * Copyright (C) 2022-2023 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_decoder.h"
35 #include "common.h"
36
37 int write_abort_check_counter = -1;
38
39 #if 0 /* set to 1 to debug */
40 #define FPRINTF_DEBUG_ONLY(...) fprintf(__VA_ARGS__)
41 #else
42 #define FPRINTF_DEBUG_ONLY(...)
43 #endif
44
45 #define CONFIG_LENGTH 2
46
write_callback(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)47 static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
48 {
49 (void)decoder, (void)frame, (void)buffer, (void)client_data;
50 if(write_abort_check_counter > 0) {
51 write_abort_check_counter--;
52 if(write_abort_check_counter == 0)
53 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
54 } else if(write_abort_check_counter == 0)
55 /* This must not happen: write callback called after abort is returned */
56 abort();
57 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
58 }
59
error_callback(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus error,void * client_data)60 static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus error, void *client_data)
61 {
62 (void)decoder, (void)error, (void)client_data;
63 }
64
65
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)66 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
67 {
68 FLAC__bool decoder_valid = true;
69 FLAC__StreamDecoder *decoder;
70 uint8_t command_length;
71 FLAC__bool init_bools[16], ogg;
72
73 if(size > 2 && data[1] < 128) /* Use MSB as on/off */
74 alloc_check_threshold = data[1];
75 else
76 alloc_check_threshold = INT32_MAX;
77 alloc_check_counter = 0;
78
79 write_abort_check_counter = -1;
80
81 /* allocate the decoder */
82 if((decoder = FLAC__stream_decoder_new()) == NULL) {
83 fprintf(stderr, "ERROR: allocating decoder\n");
84 return 1;
85 }
86
87 /* Use first byte for configuration, leave at least one byte of input */
88 if(size < 1 + CONFIG_LENGTH){
89 FLAC__stream_decoder_delete(decoder);
90 return 0;
91 }
92
93 /* First 4 bits for configuration bools, next 4 for length of command section */
94 for(int i = 0; i < 4; i++)
95 init_bools[i] = data[i/8] & (1 << (i % 8));
96
97 command_length = data[0] >> 4;
98
99 /* Leave at least one byte as input */
100 if(command_length >= size - 1 - CONFIG_LENGTH)
101 command_length = size - 1 - CONFIG_LENGTH;
102
103 /* Dump decoder input to file */
104 {
105 FILE * file_to_decode = fopen("/tmp/tmp.flac","w");
106 fwrite(data+CONFIG_LENGTH+command_length,1,size-CONFIG_LENGTH-command_length,file_to_decode);
107 fclose(file_to_decode);
108 }
109
110 ogg = init_bools[0];
111
112 FLAC__stream_decoder_set_md5_checking(decoder,init_bools[1]);
113 if(init_bools[2])
114 FLAC__stream_decoder_set_metadata_respond_all(decoder);
115 if(init_bools[3])
116 FLAC__stream_decoder_set_metadata_ignore_all(decoder);
117
118 /* initialize decoder */
119 if(decoder_valid) {
120 FLAC__StreamDecoderInitStatus init_status;
121 if(ogg)
122 init_status = FLAC__stream_decoder_init_ogg_file(decoder, "/tmp/tmp.flac", write_callback, NULL, error_callback, NULL);
123 else
124 init_status = FLAC__stream_decoder_init_file(decoder, "/tmp/tmp.flac", write_callback, NULL, error_callback, NULL);
125 if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
126 decoder_valid = false;
127 }
128 }
129
130 /* Run commands */
131 for(uint8_t i = 0; decoder_valid && (i < command_length); i++){
132 const uint8_t * command = data+CONFIG_LENGTH+i;
133 uint8_t shift = 1u << (command[0] >> 3);
134 FLAC__uint64 seekpos;
135
136 switch(command[0] & 15){
137 case 0:
138 FPRINTF_DEBUG_ONLY(stderr,"end_of_stream\n");
139 decoder_valid = FLAC__stream_decoder_process_until_end_of_stream(decoder);
140 break;
141 case 1:
142 FPRINTF_DEBUG_ONLY(stderr,"end_of_metadata\n");
143 decoder_valid = FLAC__stream_decoder_process_until_end_of_metadata(decoder);
144 break;
145 case 2:
146 FPRINTF_DEBUG_ONLY(stderr,"single\n");
147 decoder_valid = FLAC__stream_decoder_process_single(decoder);
148 break;
149 case 3:
150 FPRINTF_DEBUG_ONLY(stderr,"skip_single\n");
151 decoder_valid = FLAC__stream_decoder_skip_single_frame(decoder);
152 break;
153 case 4:
154 FPRINTF_DEBUG_ONLY(stderr,"reset\n");
155 decoder_valid = FLAC__stream_decoder_reset(decoder);
156 break;
157 case 5:
158 FPRINTF_DEBUG_ONLY(stderr,"flush\n");
159 decoder_valid = FLAC__stream_decoder_flush(decoder);
160 break;
161 case 6:
162 case 14:
163 shift = 1u << (command[0] >> 3);
164 FPRINTF_DEBUG_ONLY(stderr,"seek short %hhu\n",shift);
165 decoder_valid = FLAC__stream_decoder_seek_absolute(decoder,shift);
166 break;
167 case 7:
168 if(i+8 >= command_length) /* Not enough data available to do this */
169 break;
170 seekpos = ((FLAC__uint64)command[1] << 56) +
171 ((FLAC__uint64)command[2] << 48) +
172 ((FLAC__uint64)command[3] << 40) +
173 ((FLAC__uint64)command[4] << 32) +
174 ((FLAC__uint64)command[5] << 24) +
175 ((FLAC__uint64)command[6] << 16) +
176 ((FLAC__uint64)command[7] << 8) +
177 command[8];
178 i+=8;
179 FPRINTF_DEBUG_ONLY(stderr,"seek long %lu\n",seekpos);
180 decoder_valid = FLAC__stream_decoder_seek_absolute(decoder,seekpos);
181 break;
182 case 8:
183 /* Set abort on write callback */
184 write_abort_check_counter = (command[0] >> 4) + 1;
185 break;
186 }
187 }
188
189 FLAC__stream_decoder_finish(decoder);
190
191 FLAC__stream_decoder_delete(decoder);
192
193 return 0;
194 }
195
196