Coverage Report

Created: 2026-09-04 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/flac/oss-fuzz/seek.cc
Line
Count
Source
1
/* fuzzer_seek
2
 * Copyright (C) 2022-2025  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
#if MSAN == 1
38
extern "C" void __msan_check_mem_is_initialized(const volatile void *x, size_t size);
39
#endif
40
41
int write_abort_check_counter = -1;
42
int written_uncompressed_bytes = 0;
43
int errors_received_counter = 0;
44
45
#if 0 /* set to 1 to debug */
46
#define FPRINTF_DEBUG_ONLY(...) fprintf(__VA_ARGS__)
47
#else
48
#define FPRINTF_DEBUG_ONLY(...)
49
#endif
50
51
108k
#define CONFIG_LENGTH 3
52
53
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
54
31.5k
{
55
31.5k
  (void)decoder, (void)buffer, (void)client_data;
56
31.5k
  if(write_abort_check_counter > 0) {
57
250
    write_abort_check_counter--;
58
250
    if(write_abort_check_counter == 0)
59
25
      return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
60
31.3k
  } else if(write_abort_check_counter == 0)
61
    /* This must not happen: write callback called after abort is returned */
62
0
    abort();
63
64
31.5k
  written_uncompressed_bytes += frame->header.blocksize * frame->header.channels * frame->header.bits_per_sample / 8;
65
31.5k
  if(written_uncompressed_bytes > (1 << 24))
66
1
    return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
67
68
69
31.5k
  if(errors_received_counter > 10000)
70
3
    return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
71
72
31.5k
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
73
31.5k
}
74
75
static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus error, void *client_data)
76
427k
{
77
427k
  (void)decoder, (void)error, (void)client_data;
78
427k
  errors_received_counter++;
79
427k
}
80
81
82
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
83
11.2k
{
84
11.2k
  FLAC__bool decoder_valid = true;
85
11.2k
  FLAC__StreamDecoder *decoder;
86
11.2k
  uint8_t command_length;
87
11.2k
  FLAC__bool init_bools[16], ogg;
88
89
11.2k
  if(size < 1)
90
0
    return 1;
91
92
11.2k
  if(data[0] < 128) /* Use MSB as on/off */
93
5.76k
    alloc_check_threshold = data[0];
94
5.43k
  else
95
5.43k
    alloc_check_threshold = INT32_MAX;
96
11.2k
  alloc_check_counter = 0;
97
98
11.2k
  write_abort_check_counter = -1;
99
11.2k
  written_uncompressed_bytes = 0;
100
11.2k
  errors_received_counter = 0;
101
102
  /* allocate the decoder */
103
11.2k
  if((decoder = FLAC__stream_decoder_new()) == NULL) {
104
3
    return 1;
105
3
  }
106
107
  /* Use first CONFIG_LENGTH bytes for configuration, leave at least one byte of input */
108
11.1k
  if(size < 1 + CONFIG_LENGTH){
109
21
    FLAC__stream_decoder_delete(decoder);
110
21
    return 0;
111
21
  }
112
113
  /* bit 8 to 19 bits for configuration bools, bit 20 to 23 for length of command section */
114
145k
  for(int i = 0; i < 12; i++)
115
134k
    init_bools[i] = data[1+i/8] & (1 << (i % 8));
116
117
11.1k
  command_length = data[CONFIG_LENGTH-1] >> 4;
118
119
  /* Leave at least one byte as input */
120
11.1k
  if(command_length >= size - 1 - CONFIG_LENGTH)
121
354
    command_length = size - 1 - CONFIG_LENGTH;
122
123
  /* Dump decoder input to file */
124
11.1k
  {
125
11.1k
    FILE * file_to_decode = fopen("/tmp/tmp.flac","w");
126
11.1k
    fwrite(data+CONFIG_LENGTH+command_length,1,size-CONFIG_LENGTH-command_length,file_to_decode);
127
11.1k
    fclose(file_to_decode);
128
11.1k
  }
129
130
11.1k
  ogg = init_bools[0];
131
132
11.1k
  FLAC__stream_decoder_set_md5_checking(decoder,init_bools[1]);
133
11.1k
  if(init_bools[2])
134
7.02k
    FLAC__stream_decoder_set_metadata_respond_all(decoder);
135
11.1k
  if(init_bools[3])
136
4.99k
    FLAC__stream_decoder_set_metadata_ignore_all(decoder);
137
11.1k
  if(init_bools[4])
138
5.24k
    FLAC__stream_decoder_set_decode_chained_stream(decoder, true);
139
140
  /* initialize decoder */
141
11.1k
  if(decoder_valid) {
142
11.1k
    FLAC__StreamDecoderInitStatus init_status;
143
11.1k
    if(ogg)
144
2.60k
      init_status = FLAC__stream_decoder_init_ogg_file(decoder, "/tmp/tmp.flac", write_callback, NULL, error_callback, NULL);
145
8.56k
    else
146
8.56k
      init_status = FLAC__stream_decoder_init_file(decoder, "/tmp/tmp.flac", write_callback, NULL, error_callback, NULL);
147
11.1k
    if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
148
1
      decoder_valid = false;
149
1
    }
150
11.1k
  }
151
152
  /* Run commands */
153
63.8k
  for(uint8_t i = 0; decoder_valid && (i < command_length); i++){
154
52.7k
    const uint8_t * command = data+CONFIG_LENGTH+i;
155
52.7k
    uint8_t shift = 1u << (command[0] >> 3);
156
52.7k
    FLAC__uint64 seekpos;
157
158
52.7k
    switch(command[0] & 15){
159
12.9k
      case 0:
160
12.9k
        FPRINTF_DEBUG_ONLY(stderr,"end_of_stream\n");
161
12.9k
        decoder_valid = FLAC__stream_decoder_process_until_end_of_stream(decoder);
162
12.9k
        break;
163
1.95k
      case 1:
164
1.95k
        FPRINTF_DEBUG_ONLY(stderr,"end_of_metadata\n");
165
1.95k
        decoder_valid = FLAC__stream_decoder_process_until_end_of_metadata(decoder);
166
1.95k
        break;
167
1.64k
      case 2:
168
1.64k
        FPRINTF_DEBUG_ONLY(stderr,"single\n");
169
1.64k
        decoder_valid = FLAC__stream_decoder_process_single(decoder);
170
1.64k
        break;
171
937
      case 3:
172
937
        FPRINTF_DEBUG_ONLY(stderr,"skip_single\n");
173
937
        decoder_valid = FLAC__stream_decoder_skip_single_frame(decoder);
174
937
        break;
175
760
      case 4:
176
760
        FPRINTF_DEBUG_ONLY(stderr,"reset\n");
177
760
        decoder_valid = FLAC__stream_decoder_reset(decoder);
178
760
        break;
179
1.25k
      case 5:
180
1.25k
        FPRINTF_DEBUG_ONLY(stderr,"flush\n");
181
1.25k
        decoder_valid = FLAC__stream_decoder_flush(decoder);
182
1.25k
        break;
183
7.11k
      case 6:
184
19.5k
      case 14:
185
19.5k
        shift = 1u << (command[0] >> 3);
186
19.5k
        FPRINTF_DEBUG_ONLY(stderr,"seek short %hhu\n",shift);
187
19.5k
        decoder_valid = FLAC__stream_decoder_seek_absolute(decoder,shift);
188
19.5k
        break;
189
1.42k
      case 7:
190
1.42k
        if(i+8 >= command_length) /* Not enough data available to do this */
191
558
          break;
192
866
        seekpos = ((FLAC__uint64)command[1] << 56) +
193
866
                  ((FLAC__uint64)command[2] << 48) +
194
866
                  ((FLAC__uint64)command[3] << 40) +
195
866
                  ((FLAC__uint64)command[4] << 32) +
196
866
                  ((FLAC__uint64)command[5] << 24) +
197
866
                  ((FLAC__uint64)command[6] << 16) +
198
866
                  ((FLAC__uint64)command[7] << 8) +
199
866
                  command[8];
200
866
        i+=8;
201
866
        FPRINTF_DEBUG_ONLY(stderr,"seek long %lu\n",seekpos);
202
866
        decoder_valid = FLAC__stream_decoder_seek_absolute(decoder,seekpos);
203
866
        break;
204
631
      case 8:
205
        /* Set abort on write callback */
206
631
        write_abort_check_counter = (command[0] >> 4) + 1;
207
631
        break;
208
2.22k
      case 9:
209
2.22k
        FPRINTF_DEBUG_ONLY(stderr,"end_of_link\n");
210
2.22k
        decoder_valid = FLAC__stream_decoder_process_until_end_of_link(decoder);
211
2.22k
        break;
212
549
      case 10:
213
549
        FPRINTF_DEBUG_ONLY(stderr,"finish_link\n");
214
549
        if(FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_LINK)
215
15
          FLAC__stream_decoder_finish_link(decoder);
216
549
        break;
217
2.81k
      case 11:
218
2.81k
        FPRINTF_DEBUG_ONLY(stderr,"skip_single_link\n");
219
2.81k
        decoder_valid = FLAC__stream_decoder_skip_single_link(decoder);
220
2.81k
        break;
221
3.40k
      case 12:
222
3.40k
        FPRINTF_DEBUG_ONLY(stderr,"find_total_samples\n");
223
3.40k
        if(FLAC__stream_decoder_find_total_samples(decoder) == 0) {
224
2.74k
          FLAC__StreamDecoderState state = FLAC__stream_decoder_get_state(decoder);
225
2.74k
          if(state == FLAC__STREAM_DECODER_OGG_ERROR ||
226
2.74k
          state == FLAC__STREAM_DECODER_SEEK_ERROR ||
227
1.75k
          state == FLAC__STREAM_DECODER_ABORTED ||
228
1.74k
          state == FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR ||
229
1.74k
          state == FLAC__STREAM_DECODER_UNINITIALIZED)
230
1.00k
            decoder_valid = false;
231
2.74k
        }
232
3.40k
        break;
233
876
      case 13:
234
876
        int32_t retval;
235
876
        FLAC__uint64 *link_lengths;
236
876
        FPRINTF_DEBUG_ONLY(stderr,"get_link_lengths\n");
237
876
        retval = FLAC__stream_decoder_get_link_lengths(decoder, &link_lengths);
238
876
        if(retval == FLAC__STREAM_DECODER_GET_LINK_LENGTHS_MEMORY_ALLOCATION_ERROR) {
239
0
          decoder_valid = false;
240
0
        }
241
876
        if(retval > 0) {
242
36.0k
          for(int32_t j = 0; j < retval; j++) {
243
#if MSAN == 1
244
             __msan_check_mem_is_initialized(&link_lengths[j],sizeof(link_lengths[j]));
245
#else
246
35.8k
            ;
247
35.8k
#endif
248
35.8k
          }
249
181
          free(link_lengths);
250
181
        }
251
876
        break;
252
      /* case 14 is already used above */
253
52.7k
    }
254
52.7k
    if(!decoder_valid) {
255
      /* Try again if possible */
256
34.9k
      FLAC__StreamDecoderState state = FLAC__stream_decoder_get_state(decoder);
257
34.9k
      if(state != FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR && state != FLAC__STREAM_DECODER_ABORTED) {
258
34.7k
        FPRINTF_DEBUG_ONLY(stderr,"reset invalid\n");
259
34.7k
        decoder_valid = FLAC__stream_decoder_reset(decoder);
260
34.7k
      }
261
34.9k
    }
262
52.7k
  }
263
264
11.1k
  FLAC__stream_decoder_finish(decoder);
265
266
11.1k
  FLAC__stream_decoder_delete(decoder);
267
268
11.1k
  return 0;
269
11.1k
}
270