Coverage Report

Created: 2025-07-11 06:54

/src/flac/oss-fuzz/encoder_v2.cc
Line
Count
Source (jump to first uncovered line)
1
/* fuzzer_encoder_v2
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_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
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
80.8k
{
48
80.8k
  (void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
49
80.8k
  return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
50
80.8k
}
51
52
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
53
12.2k
{
54
12.2k
  FLAC__bool encoder_valid = true;
55
12.2k
  FLAC__StreamEncoder *encoder = 0;
56
12.2k
  FLAC__StreamEncoderState state;
57
12.2k
  const char* state_string = "";
58
12.2k
  FLAC__StreamMetadata *metadata[16] = {NULL};
59
12.2k
  unsigned num_metadata = 0;
60
12.2k
  FLAC__StreamMetadata_VorbisComment_Entry VorbisCommentField;
61
62
12.2k
  unsigned sample_rate, channels, bps;
63
12.2k
  uint64_t samples_estimate, samples_in_input;
64
12.2k
  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;
65
12.2k
  FLAC__bool ogg, write_to_file, interleaved;
66
67
12.2k
  FLAC__bool data_bools[24];
68
69
  /* Set alloc threshold. This check was added later and no spare config
70
   * bytes were left, so we're reusing the sample rate as that of little
71
   * consequence to the encoder and decoder except reading the frame header */
72
73
12.2k
  if(size < 3)
74
2
    return 0;
75
12.2k
  alloc_check_threshold = data[2];
76
12.2k
  alloc_check_counter = 0;
77
78
  /* allocate the encoder */
79
12.2k
  if((encoder = FLAC__stream_encoder_new()) == NULL) {
80
12
    return 0;
81
12
  }
82
83
  /* Use first 20 byte for configuration */
84
12.2k
  if(size < 20){
85
21
    FLAC__stream_encoder_delete(encoder);
86
21
    return 0;
87
21
  }
88
89
  /* First 3 byte for sample rate, 4th byte for channels, 5th byte for bps */
90
12.2k
  sample_rate = ((unsigned)data[0] << 16) + ((unsigned)data[1] << 8) + data[2];
91
12.2k
  channels = data[3];
92
12.2k
  bps = data[4];
93
94
  /* Number of samples estimate, format accepts 36-bit max */
95
12.2k
  samples_estimate = ((uint64_t)data[5] << 32) + ((unsigned)data[6] << 24) + ((unsigned)data[7] << 16) + ((unsigned)data[8] << 8) + data[9];
96
97
12.2k
  compression_level = data[10]&0b1111;
98
12.2k
  input_data_width = 1 + (data[10]>>4)%4;
99
12.2k
  samples_in_input = (size-20)/input_data_width;
100
12.2k
  blocksize = ((unsigned)data[11] << 8) + (unsigned)data[12];
101
12.2k
  max_lpc_order = data[13];
102
12.2k
  qlp_coeff_precision = data[14];
103
12.2k
  min_residual_partition_order = data[15] & 0b1111;
104
12.2k
  max_residual_partition_order = data[15] & 0b11110000;
105
12.2k
  metadata_mask = data[16];
106
12.2k
  instruction_set_disable_mask = data[17];
107
108
  /* Get array of bools from configuration */
109
208k
  for(int i = 0; i < 16; i++)
110
196k
    data_bools[i] = data[18+i/8] & (1 << (i % 8));
111
112
12.2k
  ogg = data_bools[0];
113
12.2k
  interleaved = data_bools[1];
114
12.2k
  write_to_file = data_bools[13];
115
116
  /* Set input and process parameters */
117
12.2k
  encoder_valid &= FLAC__stream_encoder_set_verify(encoder, data_bools[2]);
118
12.2k
  encoder_valid &= FLAC__stream_encoder_set_channels(encoder, channels);
119
12.2k
  encoder_valid &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
120
12.2k
  encoder_valid &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
121
12.2k
  encoder_valid &= FLAC__stream_encoder_set_total_samples_estimate(encoder, samples_estimate);
122
12.2k
  encoder_valid &= FLAC__stream_encoder_disable_instruction_set(encoder, instruction_set_disable_mask);
123
12.2k
  encoder_valid &= FLAC__stream_encoder_set_limit_min_bitrate(encoder, data_bools[15]);
124
12.2k
  encoder_valid &= (FLAC__stream_encoder_set_num_threads(encoder,data[9]) == FLAC__STREAM_ENCODER_SET_NUM_THREADS_OK); /* reuse data[9] */
125
126
  /* Set compression related parameters */
127
12.2k
  encoder_valid &= FLAC__stream_encoder_set_compression_level(encoder, compression_level);
128
12.2k
  if(data_bools[3]){
129
    /* Bias towards regular compression levels */
130
9.70k
    encoder_valid &= FLAC__stream_encoder_set_blocksize(encoder, blocksize);
131
9.70k
    encoder_valid &= FLAC__stream_encoder_set_max_lpc_order(encoder, max_lpc_order);
132
9.70k
    encoder_valid &= FLAC__stream_encoder_set_qlp_coeff_precision(encoder, qlp_coeff_precision);
133
9.70k
    encoder_valid &= FLAC__stream_encoder_set_min_residual_partition_order(encoder, min_residual_partition_order);
134
135
    /* With large inputs and expensive options enabled, the fuzzer can get *really* slow.
136
     * Some combinations can make the fuzzer timeout (>60 seconds). However, while combining
137
     * options makes the fuzzer slower, most options do not expose new code when combined.
138
     * Therefore, combining slow options is disabled for large inputs. Any input containing
139
     * more than 65536 * 2 samples (max blocksize, stereo) is considered large
140
     */
141
9.70k
    if(samples_in_input < (2*65536)) {
142
9.53k
      encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, data_bools[4]);
143
9.53k
      encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, data_bools[5]);
144
9.53k
      encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, data_bools[6]);
145
9.53k
      encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, data_bools[7]);
146
      /* Combining model search, precision search and a high residual partition order is especially
147
       * expensive, so limit that even further. This high partition order can only be set on
148
       * large blocksize and with streamable subset disabled */
149
9.53k
      if(samples_in_input < (2 * 4609) || data_bools[4] || !data_bools[7] || !data_bools[5] || max_residual_partition_order < 9 || blocksize < 4609)
150
9.46k
        encoder_valid &= FLAC__stream_encoder_set_max_residual_partition_order(encoder, max_residual_partition_order);
151
9.53k
    }
152
173
    else {
153
173
      if(!data_bools[4])
154
129
        encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, false);
155
44
      else if(data_bools[6])
156
23
        encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, true);
157
21
      else if(data_bools[7])
158
10
        encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, true);
159
11
      else if(data_bools[5])
160
1
        encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, true);
161
173
    }
162
9.70k
    encoder_valid &= FLAC__stream_encoder_set_do_mid_side_stereo(encoder, data_bools[8]);
163
9.70k
    encoder_valid &= FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, data_bools[9]);
164
165
9.70k
    encoder_valid &= FLAC__stream_encoder_disable_constant_subframes(encoder, data_bools[10]);
166
9.70k
    encoder_valid &= FLAC__stream_encoder_disable_fixed_subframes(encoder, data_bools[11]);
167
9.70k
    encoder_valid &= FLAC__stream_encoder_disable_verbatim_subframes(encoder, data_bools[12]);
168
9.70k
  }
169
170
  /* Disable alloc check if requested */
171
12.2k
  if(encoder_valid && data_bools[14])
172
7.23k
    alloc_check_threshold = INT32_MAX;
173
174
  /* add metadata */
175
12.2k
  if(encoder_valid && (metadata_mask & 1)) {
176
79
    if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO)) == NULL)
177
0
      encoder_valid = false;
178
79
    else
179
79
      num_metadata++;
180
79
  }
181
12.2k
  if(encoder_valid && (metadata_mask & 2) && size > 21){
182
4.85k
    if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL)
183
0
      encoder_valid = false;
184
4.85k
    else {
185
4.85k
      metadata[num_metadata++]->length = (((unsigned)data[20]) << 8) + (unsigned)(data[21]);
186
4.85k
    }
187
4.85k
  }
188
12.2k
  if(encoder_valid && (metadata_mask & 4) && size > 20){
189
4.95k
    FLAC__byte * application_data = (FLAC__byte *)malloc(size-20);
190
4.95k
    if(0 != application_data && ((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) == NULL))
191
0
      encoder_valid = false;
192
4.95k
    else {
193
4.95k
      memcpy(application_data,data+20,size-20);
194
4.95k
      FLAC__metadata_object_application_set_data(metadata[num_metadata++], application_data, size-20, 0);
195
4.95k
    }
196
4.95k
  }
197
12.2k
  if(encoder_valid && (metadata_mask & 8) && size > 25){
198
5.84k
    if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE)) == NULL)
199
0
      encoder_valid = false;
200
5.84k
    else {
201
5.84k
      unsigned seekpoint_spacing = ((unsigned)data[22] << 8) + data[23];
202
5.84k
      unsigned total_samples_for_seekpoints = ((unsigned)data[24] << 8) + data[25];
203
5.84k
      FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(metadata[num_metadata++], seekpoint_spacing, total_samples_for_seekpoints);
204
5.84k
    }
205
5.84k
  }
206
12.2k
  if(encoder_valid && (metadata_mask & 16)){
207
3.50k
    if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) != NULL) {
208
3.50k
      bool vorbiscomment_valid = true;
209
      /* Append a vorbis comment */
210
3.50k
      if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Nothing to 🤔 report"))
211
1
        vorbiscomment_valid = false;
212
3.50k
      else {
213
3.50k
        if(FLAC__metadata_object_vorbiscomment_append_comment(metadata[num_metadata], VorbisCommentField, false)) {
214
215
          /* Insert a vorbis comment at the first index */
216
3.50k
          if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Still nothing to report 🤔🤣"))
217
1
            vorbiscomment_valid = false;
218
3.49k
          else
219
3.49k
            if(!FLAC__metadata_object_vorbiscomment_insert_comment(metadata[num_metadata], 0, VorbisCommentField, false)) {
220
2
              free(VorbisCommentField.entry);
221
2
              vorbiscomment_valid = false;
222
2
            }
223
3.50k
        }
224
5
        else {
225
5
          free(VorbisCommentField.entry);
226
5
          vorbiscomment_valid = false;
227
5
        }
228
3.50k
      }
229
3.50k
      if(!vorbiscomment_valid) {
230
9
        FLAC__metadata_object_delete(metadata[num_metadata]);
231
9
        metadata[num_metadata] = 0;
232
9
        encoder_valid = false;
233
9
      }
234
3.49k
      else
235
3.49k
        num_metadata++;
236
3.50k
    }
237
2
    else {
238
2
      encoder_valid = false;
239
2
    }
240
3.50k
  }
241
12.2k
  if(encoder_valid && (metadata_mask & 32)){
242
3.99k
    if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)) != NULL) {
243
3.99k
      if(!FLAC__metadata_object_cuesheet_insert_blank_track(metadata[num_metadata],0)) {
244
2
        FLAC__metadata_object_delete(metadata[num_metadata]);
245
2
        metadata[num_metadata] = 0;
246
2
        encoder_valid = false;
247
2
      }
248
3.98k
      else {
249
3.98k
        if(!FLAC__metadata_object_cuesheet_track_insert_blank_index(metadata[num_metadata],0,0)) {
250
1
          FLAC__metadata_object_delete(metadata[num_metadata]);
251
1
          metadata[num_metadata] = 0;
252
1
          encoder_valid = false;
253
1
        }
254
3.98k
        else {
255
3.98k
          metadata[num_metadata]->data.cue_sheet.tracks[0].number = 1;
256
3.98k
          num_metadata++;
257
3.98k
        }
258
3.98k
      }
259
3.99k
    }
260
0
    else {
261
0
      encoder_valid = false;
262
0
    }
263
3.99k
  }
264
12.2k
  if(encoder_valid && (metadata_mask & 64)){
265
4.31k
    if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)) != NULL) {
266
4.31k
      num_metadata++;
267
4.31k
    }
268
0
    else {
269
0
      encoder_valid = false;
270
0
    }
271
4.31k
  }
272
12.2k
  if(encoder_valid && (metadata_mask & 128)){
273
3.32k
    if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_UNDEFINED)) != NULL) {
274
3.32k
      metadata[num_metadata]->length = 24;
275
3.32k
      metadata[num_metadata]->data.unknown.data = (FLAC__byte *)calloc(24, 1);
276
3.32k
      num_metadata++;
277
3.32k
    }
278
0
    else {
279
0
      encoder_valid = false;
280
0
    }
281
3.32k
  }
282
283
12.2k
  if(num_metadata && encoder_valid)
284
8.16k
    encoder_valid = FLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
285
286
  /* initialize encoder */
287
12.2k
  if(encoder_valid) {
288
12.2k
    FLAC__StreamEncoderInitStatus init_status;
289
12.2k
    if(ogg)
290
4.85k
      if(write_to_file)
291
2.67k
        init_status = FLAC__stream_encoder_init_ogg_file(encoder, "/tmp/tmp.flac", NULL, NULL);
292
2.18k
      else
293
2.18k
        init_status = FLAC__stream_encoder_init_ogg_stream(encoder, NULL, write_callback, NULL, NULL, NULL, NULL);
294
7.36k
    else
295
7.36k
      if(write_to_file)
296
3.47k
        init_status = FLAC__stream_encoder_init_file(encoder, "/tmp/tmp.flac", NULL, NULL);
297
3.89k
      else
298
3.89k
        init_status = FLAC__stream_encoder_init_stream(encoder, write_callback, NULL, NULL, NULL, NULL);
299
12.2k
    if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
300
277
      encoder_valid = false;
301
277
    }
302
12.2k
  }
303
304
305
  /* send samples to encoder */
306
12.2k
  if(encoder_valid && size > (input_data_width*channels+26)) {
307
11.6k
    unsigned samples = (size - 26)/input_data_width/channels;
308
11.6k
    const uint8_t * pcm_data = data + 26;
309
11.6k
    int32_t * data_as_int32 = (int32_t *)malloc(4*samples*channels);
310
11.6k
    if(0 != data_as_int32){
311
97.9M
      for(unsigned i = 0; i < samples*channels; i++)
312
97.9M
        if(input_data_width == 1)
313
82.6M
          data_as_int32[i] = (int32_t)pcm_data[i] - 0x80;
314
15.2M
        else if(input_data_width == 2)
315
324k
          data_as_int32[i] = (((int32_t)pcm_data[i*2] << 8) + pcm_data[i*2+1]) - 0x8000;
316
14.9M
        else if(input_data_width == 3)
317
2.91M
          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;
318
12.0M
        else if(input_data_width == 4)
319
12.0M
          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;
320
321
      /* feed samples to encoder */
322
11.6k
      if(interleaved)
323
5.12k
        encoder_valid = FLAC__stream_encoder_process_interleaved(encoder, data_as_int32, samples);
324
6.54k
      else {
325
6.54k
        encoder_valid = FLAC__stream_encoder_process(encoder, (const int32_t*[]){data_as_int32,
326
6.54k
                                                               data_as_int32+samples,
327
6.54k
                                                               data_as_int32+samples*2,
328
6.54k
                                                               data_as_int32+samples*3,
329
6.54k
                                                               data_as_int32+samples*4, data_as_int32+samples*5, data_as_int32+samples*6, data_as_int32+samples*7}, samples);
330
6.54k
      }
331
11.6k
      free(data_as_int32);
332
11.6k
    }
333
0
    else {
334
0
      encoder_valid = false;
335
0
    }
336
11.6k
  }
337
338
12.2k
  state = FLAC__stream_encoder_get_state(encoder);
339
12.2k
  state_string = FLAC__stream_encoder_get_resolved_state_string(encoder);
340
12.2k
  if(!(state == FLAC__STREAM_ENCODER_OK ||
341
12.2k
       state == FLAC__STREAM_ENCODER_UNINITIALIZED ||
342
12.2k
       state == FLAC__STREAM_ENCODER_CLIENT_ERROR ||
343
12.2k
       ((state == FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR ||
344
110
               state == FLAC__STREAM_ENCODER_FRAMING_ERROR ||
345
110
         (state == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR &&
346
12
          FLAC__stream_encoder_get_verify_decoder_state(encoder) == FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR)) &&
347
110
        alloc_check_threshold < INT32_MAX))) {
348
0
    fprintf(stderr,"-----\nERROR: stream encoder returned %s\n-----\n",FLAC__stream_encoder_get_resolved_state_string(encoder));
349
0
    if(state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) {
350
0
      uint32_t frame_number, channel, sample_number;
351
0
      FLAC__int32 expected, got;
352
0
      FLAC__stream_encoder_get_verify_decoder_error_stats(encoder, NULL, &frame_number, &channel, &sample_number, &expected, &got);
353
0
      fprintf(stderr,"Frame number %d\nChannel %d\n Sample number %d\nExpected value %d\nGot %d\n", frame_number, channel, sample_number, expected, got);
354
0
    }
355
0
    abort();
356
0
  }
357
358
12.2k
  FLAC__stream_encoder_finish(encoder);
359
360
  /* now that encoding is finished, the metadata can be freed */
361
208k
  for(unsigned i = 0; i < 16; i++)
362
196k
    if(0 != metadata[i])
363
30.8k
      FLAC__metadata_object_delete(metadata[i]);
364
365
12.2k
  FLAC__stream_encoder_delete(encoder);
366
367
12.2k
  return 0;
368
12.2k
}
369