Coverage Report

Created: 2025-12-05 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/flac/oss-fuzz/metadata.cc
Line
Count
Source
1
/* fuzzer_metadata
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 <cstdio>
34
#include <cstring> /* for memcpy */
35
#include <unistd.h>
36
#include "FLAC++/metadata.h"
37
#include "common.h"
38
39
51.6k
#define CONFIG_LENGTH 2
40
41
4.42k
#define min(x,y) (x<y?x:y)
42
43
static void run_tests_with_level_0_interface(char filename[]);
44
static void run_tests_with_level_1_interface(char filename[], bool readonly, bool preservestats, const uint8_t *data, size_t size);
45
static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use_padding, const uint8_t *data, size_t size);
46
47
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
48
7.19k
{
49
7.19k
  uint8_t command_length;
50
7.19k
  char filename[] = "/tmp/tmpXXXXXX.flac";
51
7.19k
  FLAC__bool init_bools[4];
52
53
  /* Use first byte for configuration, leave at least one byte of input */
54
7.19k
  if(size < 1 + CONFIG_LENGTH){
55
2
    return 0;
56
2
  }
57
58
  /* First 4 bits for configuration bools, next 4 for length of command section */
59
35.9k
  for(int i = 0; i < 4; i++)
60
28.7k
    init_bools[i] = data[i/8] & (1 << (i % 8));
61
62
7.19k
  command_length = data[0] >> 4;
63
64
7.19k
  if(0)//data[1] < 128) /* Use MSB as on/off */
65
0
    alloc_check_threshold = data[1];
66
7.19k
  else
67
7.19k
    alloc_check_threshold = INT32_MAX;
68
7.19k
  alloc_check_counter = 0;
69
70
71
  /* Leave at least one byte as input */
72
7.19k
  if(command_length >= size - 1 - CONFIG_LENGTH)
73
29
    command_length = size - 1 - CONFIG_LENGTH;
74
75
  /* Dump input to file */
76
7.19k
  {
77
7.19k
    int file_to_fuzz = mkstemps(filename, 5);
78
79
7.19k
    if (file_to_fuzz < 0)
80
0
      abort();
81
7.19k
    write(file_to_fuzz,data+CONFIG_LENGTH+command_length,size-CONFIG_LENGTH-command_length);
82
7.19k
    close(file_to_fuzz);
83
7.19k
  }
84
85
0
  run_tests_with_level_0_interface(filename);
86
7.19k
  run_tests_with_level_1_interface(filename, init_bools[1], init_bools[2], data+CONFIG_LENGTH, command_length/2);
87
88
  /* Dump input to file, to start fresh for level 2 */
89
7.19k
  if(!init_bools[1]){
90
4.20k
    FILE * file_to_fuzz = fopen(filename,"w");
91
4.20k
    fwrite(data+CONFIG_LENGTH+command_length,1,size-CONFIG_LENGTH-command_length,file_to_fuzz);
92
4.20k
    fclose(file_to_fuzz);
93
4.20k
  }
94
95
7.19k
  run_tests_with_level_2_interface(filename, init_bools[0], init_bools[3], data+command_length/2+CONFIG_LENGTH, command_length/2);
96
97
7.19k
  remove(filename);
98
99
7.19k
  return 0;
100
7.19k
}
101
102
7.19k
static void run_tests_with_level_0_interface(char filename[]) {
103
7.19k
  FLAC::Metadata::StreamInfo streaminfo;
104
7.19k
  FLAC::Metadata::VorbisComment vorbis_comment;
105
7.19k
  FLAC::Metadata::CueSheet cue_sheet;
106
7.19k
  FLAC::Metadata::Picture picture;
107
108
7.19k
  FLAC::Metadata::get_streaminfo(filename,streaminfo);
109
7.19k
  FLAC::Metadata::get_tags(filename,vorbis_comment);
110
7.19k
  FLAC::Metadata::get_cuesheet(filename,cue_sheet);
111
7.19k
  FLAC::Metadata::get_picture(filename,picture, (FLAC__StreamMetadata_Picture_Type)(1), NULL, NULL, -1, -1, -1, -1);
112
7.19k
}
113
114
7.19k
static void run_tests_with_level_1_interface(char filename[], bool readonly, bool preservestats, const uint8_t *data, size_t size) {
115
7.19k
  FLAC::Metadata::SimpleIterator iterator;
116
7.19k
  FLAC::Metadata::Prototype *metadata_block = nullptr;
117
7.19k
  uint8_t id[4] = {0};
118
119
7.19k
  if(!iterator.is_valid())
120
0
    return;
121
122
7.19k
  if(!iterator.init(filename,readonly,preservestats))
123
3.04k
    return;
124
125
14.4k
  for(size_t i = 0; i < size && iterator.status() == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; i++) {
126
10.2k
    switch(data[i] & 7) {
127
688
      case 0:
128
688
        iterator.get_block_type();
129
688
        iterator.get_block_offset();
130
688
        iterator.get_block_length();
131
688
        iterator.get_application_id(id);
132
688
        break;
133
2.29k
      case 1:
134
2.29k
        iterator.next();
135
2.29k
        break;
136
579
      case 2:
137
579
        iterator.prev();
138
579
        break;
139
624
      case 3:
140
624
        iterator.delete_block(data[i] & 8);
141
624
        break;
142
2.82k
      case 4:
143
2.82k
        if(metadata_block != 0) {
144
1.10k
          delete metadata_block;
145
1.10k
          metadata_block = nullptr;
146
1.10k
        }
147
2.82k
        metadata_block = iterator.get_block();
148
2.82k
        break;
149
1.01k
      case 5:
150
1.01k
        if(metadata_block != 0)
151
521
          iterator.set_block(metadata_block,data[i] & 8);
152
1.01k
        break;
153
1.24k
      case 6:
154
1.24k
        if(metadata_block != 0)
155
521
          iterator.insert_block_after(metadata_block, data[i] & 8);
156
1.24k
        break;
157
1.01k
      case 7:
158
1.01k
        iterator.status();
159
1.01k
        iterator.is_last();
160
1.01k
        iterator.is_writable();
161
1.01k
        break;
162
10.2k
    }
163
10.2k
  }
164
4.15k
  if(metadata_block != 0) {
165
1.24k
    delete metadata_block;
166
1.24k
    metadata_block = nullptr;
167
1.24k
  }
168
169
170
4.15k
}
171
172
173
7.19k
static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use_padding, const uint8_t *data, size_t size) {
174
7.19k
  FLAC::Metadata::Chain chain;
175
7.19k
  FLAC::Metadata::Iterator iterator;
176
7.19k
  FLAC::Metadata::Prototype *metadata_block_get = nullptr;
177
7.19k
  FLAC::Metadata::Prototype *metadata_block_transfer = nullptr;
178
7.19k
  FLAC::Metadata::Prototype *metadata_block_put = nullptr;
179
180
7.19k
  if(!chain.is_valid())
181
0
    return;
182
183
7.19k
  if(!chain.read(filename, ogg))
184
4.69k
    return;
185
186
2.49k
  iterator.init(chain);
187
188
13.8k
  for(size_t i = 0; i < size; i++) {
189
11.3k
    switch(data[i] & 15) {
190
180
      case 0:
191
180
        iterator.get_block_type();
192
180
        break;
193
2.39k
      case 1:
194
2.39k
        iterator.next();
195
2.39k
        break;
196
54
      case 2:
197
54
        iterator.prev();
198
54
        break;
199
313
      case 3:
200
313
        iterator.delete_block(data[i] & 16);
201
313
        break;
202
2.50k
      case 4:
203
2.50k
        metadata_block_get = iterator.get_block();
204
2.50k
        if(metadata_block_get != 0 && metadata_block_get->is_valid()) {
205
2.50k
          if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
206
327
            if(metadata_block_transfer != metadata_block_get) {
207
327
              delete metadata_block_transfer;
208
327
              metadata_block_transfer = nullptr;
209
327
              metadata_block_transfer = FLAC::Metadata::clone(metadata_block_get);
210
327
            }
211
327
          }
212
2.17k
          else {
213
2.17k
            metadata_block_transfer = FLAC::Metadata::clone(metadata_block_get);
214
2.17k
          }
215
2.50k
        }
216
2.50k
        delete metadata_block_get;
217
2.50k
        break;
218
545
      case 5:
219
545
        if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
220
483
          metadata_block_put = FLAC::Metadata::clone(metadata_block_transfer);
221
483
          if(metadata_block_put != 0 && metadata_block_put->is_valid()) {
222
483
            if(!iterator.insert_block_before(metadata_block_put))
223
31
              delete metadata_block_put;
224
483
          }
225
0
          else
226
0
            if(metadata_block_put != 0)
227
0
              delete metadata_block_put;
228
483
        }
229
545
        break;
230
633
      case 6:
231
633
        if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
232
575
          metadata_block_put = FLAC::Metadata::clone(metadata_block_transfer);
233
575
          if(metadata_block_put != 0 && metadata_block_put->is_valid()) {
234
575
            if(!iterator.insert_block_after(metadata_block_put))
235
14
              delete metadata_block_put;
236
575
          }
237
0
          else
238
0
            if(metadata_block_put != 0)
239
0
              delete metadata_block_put;
240
575
        }
241
633
        break;
242
241
      case 7:
243
241
        if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
244
204
          metadata_block_put = FLAC::Metadata::clone(metadata_block_transfer);
245
204
          if(metadata_block_put != 0 && metadata_block_put->is_valid()) {
246
204
            if(!iterator.set_block(metadata_block_put))
247
31
              delete metadata_block_put;
248
204
          }
249
0
          else
250
0
            if(metadata_block_put != 0)
251
0
              delete metadata_block_put;
252
204
        }
253
241
        break;
254
1.02k
      case 8: /* Examine block */
255
1.02k
        if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
256
1.00k
          switch(metadata_block_transfer->get_type()) {
257
386
            case FLAC__METADATA_TYPE_VORBIS_COMMENT:
258
386
            {
259
386
              uint32_t num_comments;
260
386
              ::FLAC__StreamMetadata_VorbisComment_Entry entry;
261
386
              FLAC::Metadata::VorbisComment::Entry entry_cpp;
262
386
              FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast<FLAC::Metadata::VorbisComment *>(metadata_block_transfer);
263
386
              const ::FLAC__StreamMetadata * metadata_c = *metadata_block_transfer;
264
386
              if(vorbiscomment == 0)
265
0
                abort();
266
386
              vorbiscomment->get_vendor_string();
267
386
              num_comments = vorbiscomment->get_num_comments();
268
386
              if(num_comments > 0) {
269
372
                entry = metadata_c->data.vorbis_comment.comments[min(data[i]>>4,num_comments-1)];
270
372
                if(entry.entry == 0)
271
0
                  abort();
272
372
                if(vorbiscomment->get_comment(min(data[i]>>4,num_comments-1)).is_valid()) {
273
147
                  entry_cpp = vorbiscomment->get_comment(min(data[i]>>4,num_comments-1));
274
147
                  if(entry_cpp.is_valid() && entry_cpp.get_field() == 0)
275
0
                    abort();
276
147
                  vorbiscomment->find_entry_from(0,"TEST");
277
147
                }
278
372
              }
279
280
386
            }
281
386
            break;
282
498
            case FLAC__METADATA_TYPE_CUESHEET:
283
498
            {
284
498
              uint32_t num_tracks, num_indices;
285
498
              FLAC::Metadata::CueSheet * cuesheet = dynamic_cast<FLAC::Metadata::CueSheet *>(metadata_block_transfer);
286
498
              if(cuesheet == 0 || !cuesheet->is_legal())
287
55
                break;
288
443
              cuesheet->is_legal(true); /* check CDDA subset */
289
443
              cuesheet->calculate_cddb_id();
290
443
              cuesheet->get_media_catalog_number();
291
443
              cuesheet->get_lead_in();
292
443
              cuesheet->get_is_cd();
293
443
              num_tracks = cuesheet->get_num_tracks();
294
443
              if(num_tracks > 0) {
295
443
                FLAC::Metadata::CueSheet::Track track = cuesheet->get_track(min(data[i]>>4,num_tracks-1));
296
443
                track.get_offset();
297
443
                track.get_number();
298
443
                track.get_isrc();
299
443
                track.get_pre_emphasis();
300
443
                num_indices = track.get_num_indices();
301
443
                if(num_indices > 0) {
302
156
                  FLAC__StreamMetadata_CueSheet_Index index = track.get_index(min(data[i]>>4,num_indices-1));
303
156
                  (void)index;
304
156
                }
305
443
              }
306
443
            }
307
0
            break;
308
96
            case FLAC__METADATA_TYPE_PICTURE:
309
96
            {
310
96
              char * violation = nullptr;
311
96
              FLAC::Metadata::Picture * picture = dynamic_cast<FLAC::Metadata::Picture *>(metadata_block_transfer);
312
96
              if(picture == 0 || !picture->is_legal((const char **)&violation))
313
48
                break;
314
48
              picture->get_data();
315
48
            }
316
0
            break;
317
23
            default:
318
23
            break;
319
1.00k
          }
320
321
1.00k
        }
322
1.02k
        break;
323
1.63k
      case 9: /* Replace or add in block */
324
1.63k
        if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
325
1.61k
          switch(metadata_block_transfer->get_type()) {
326
553
            case FLAC__METADATA_TYPE_SEEKTABLE:
327
553
            {
328
553
              uint32_t num_seekpoints;
329
553
              FLAC__StreamMetadata_SeekPoint seekpoint;
330
553
              FLAC::Metadata::SeekTable * seektable = dynamic_cast<FLAC::Metadata::SeekTable *>(metadata_block_transfer);
331
553
              if(seektable == 0)
332
0
                break;
333
553
              if(seektable->is_valid() && seektable->is_legal()) {
334
537
                num_seekpoints = seektable->get_num_points();
335
537
                if(num_seekpoints > 0) {
336
412
                  seekpoint = seektable->get_point(min(data[i]>>5,num_seekpoints-1));
337
412
                  seektable->set_point(0,seekpoint);
338
412
                  seektable->insert_point(min(data[i]>>5,num_seekpoints-1),seekpoint);
339
412
                }
340
537
                seektable->template_append_placeholders(4);
341
537
                seektable->template_append_point(111111);
342
537
                seektable->template_append_points((FLAC__uint64[]){222222, 333333, 444444}, 3);
343
537
                seektable->template_append_spaced_points(data[i]>>5, 1234567);
344
537
                seektable->template_append_spaced_points_by_samples(data[i]>>5, 2468000);
345
537
                seektable->template_sort(data[i] & 16);
346
537
              }
347
553
            }
348
1.27k
            case FLAC__METADATA_TYPE_VORBIS_COMMENT:
349
1.27k
            {
350
1.27k
              uint32_t num_comments;
351
1.27k
              FLAC::Metadata::VorbisComment::Entry entry;
352
1.27k
              FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast<FLAC::Metadata::VorbisComment *>(metadata_block_transfer);
353
1.27k
              if(vorbiscomment == 0)
354
553
                break;
355
725
              num_comments = vorbiscomment->get_num_comments();
356
725
              if(num_comments > 0 && entry.is_valid()) {
357
714
                if(vorbiscomment->get_comment(min(data[i]>>5,num_comments-1)).is_valid()) {
358
451
                  entry = vorbiscomment->get_comment(min(data[i]>>5,num_comments-1));
359
451
                  if(entry.is_valid()) {
360
451
                    vorbiscomment->replace_comment(entry,data[i] & 16);
361
451
                    vorbiscomment->set_comment(0,entry);
362
451
                    vorbiscomment->append_comment(entry);
363
451
                    vorbiscomment->insert_comment(0,entry);
364
451
                  }
365
451
                }
366
714
              }
367
725
            }
368
0
            break;
369
166
            case FLAC__METADATA_TYPE_CUESHEET:
370
166
            {
371
166
              uint32_t num_tracks, num_indices;
372
166
              FLAC::Metadata::CueSheet * cuesheet = dynamic_cast<FLAC::Metadata::CueSheet *>(metadata_block_transfer);
373
166
              if(cuesheet == 0 || !cuesheet->is_legal())
374
55
                break;
375
111
              num_tracks = cuesheet->get_num_tracks();
376
111
              if(num_tracks > 0) {
377
111
                FLAC::Metadata::CueSheet::Track track = cuesheet->get_track(min(data[i]>>4,num_tracks-1));
378
111
                num_indices = track.get_num_indices();
379
111
                if(num_indices > 0) {
380
60
                  FLAC__StreamMetadata_CueSheet_Index index = track.get_index(min(data[i]>>4,num_indices-1));
381
60
                  track.set_index(0,index);
382
60
                  cuesheet->insert_index(0,0,index);
383
60
                  cuesheet->insert_blank_index(0,0);
384
60
                }
385
111
                cuesheet->insert_blank_track(0);
386
111
                cuesheet->insert_track(0,track);
387
111
                cuesheet->resize_indices(min(data[i]>>4,num_tracks-1),data[i]>>4);
388
111
              }
389
111
            }
390
0
            break;
391
128
            case FLAC__METADATA_TYPE_PICTURE:
392
128
            {
393
128
              FLAC::Metadata::Picture * picture = dynamic_cast<FLAC::Metadata::Picture *>(metadata_block_transfer);
394
128
              const char testtext[] = "TEST";
395
128
              if(picture == 0 || !picture->is_legal(NULL))
396
31
                break;
397
97
              picture->set_description((FLAC__byte *)&testtext);
398
97
              picture->set_mime_type((const char *)&testtext);
399
97
              picture->set_data((FLAC__byte *)&testtext,4);
400
97
            }
401
0
            break;
402
39
            default:
403
39
            break;
404
1.61k
          }
405
406
1.61k
        }
407
1.63k
        break;
408
1.63k
      case 10: /* Delete from block */
409
650
        if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
410
621
          switch(metadata_block_transfer->get_type()) {
411
146
            case FLAC__METADATA_TYPE_SEEKTABLE:
412
146
            {
413
146
              uint32_t num_seekpoints;
414
146
              FLAC::Metadata::SeekTable * seektable = dynamic_cast<FLAC::Metadata::SeekTable *>(metadata_block_transfer);
415
146
              if(seektable == 0)
416
0
                break;
417
146
              if(seektable->is_valid() && seektable->is_legal()) {
418
135
                num_seekpoints = seektable->get_num_points();
419
135
                if(num_seekpoints > 0)
420
124
                  seektable->delete_point(min(data[i]>>4,num_seekpoints-1));
421
135
              }
422
146
            }
423
425
            case FLAC__METADATA_TYPE_VORBIS_COMMENT:
424
425
            {
425
425
              uint32_t num_comments;
426
425
              FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast<FLAC::Metadata::VorbisComment *>(metadata_block_transfer);
427
425
              if(vorbiscomment == 0)
428
146
                break;
429
279
              num_comments = vorbiscomment->get_num_comments();
430
279
              if(num_comments > 0)
431
269
                vorbiscomment->delete_comment(min(data[i]>>4,num_comments-1));
432
279
              vorbiscomment->remove_entry_matching("TEST");
433
279
              vorbiscomment->remove_entries_matching("TEST");
434
279
            }
435
0
            break;
436
164
            case FLAC__METADATA_TYPE_CUESHEET:
437
164
            {
438
164
              uint32_t num_tracks;
439
164
              FLAC::Metadata::CueSheet * cuesheet = dynamic_cast<FLAC::Metadata::CueSheet *>(metadata_block_transfer);
440
164
              if(cuesheet == 0 || !cuesheet->is_legal())
441
63
                break;
442
101
              num_tracks = cuesheet->get_num_tracks();
443
101
              if(num_tracks > 0) {
444
101
                FLAC::Metadata::CueSheet::Track track = cuesheet->get_track(min(data[i]>>4,num_tracks-1));
445
101
                if(track.get_num_indices() > 0)
446
66
                  cuesheet->delete_index(min(data[i]>>4,num_tracks-1),0);
447
101
                cuesheet->delete_track(0);
448
101
              }
449
101
            }
450
0
            break;
451
32
            default:
452
32
            break;
453
621
          }
454
455
621
        }
456
650
        break;
457
650
      case 11: /* Resize block */
458
528
        if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
459
505
          switch(metadata_block_transfer->get_type()) {
460
16
            case FLAC__METADATA_TYPE_PADDING:
461
16
            {
462
16
              FLAC::Metadata::Padding * padding = dynamic_cast<FLAC::Metadata::Padding *>(metadata_block_transfer);
463
16
              if(padding == 0)
464
0
                break;
465
16
              padding->set_length(data[i]>>4);
466
16
            }
467
0
            break;
468
110
            case FLAC__METADATA_TYPE_SEEKTABLE:
469
110
            {
470
110
              FLAC::Metadata::SeekTable * seektable = dynamic_cast<FLAC::Metadata::SeekTable *>(metadata_block_transfer);
471
110
              if(seektable == 0)
472
0
                break;
473
110
              seektable->resize_points(data[i]>>4);
474
110
            }
475
0
            break;
476
214
            case FLAC__METADATA_TYPE_VORBIS_COMMENT:
477
214
            {
478
214
              FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast<FLAC::Metadata::VorbisComment *>(metadata_block_transfer);
479
214
              if(vorbiscomment == 0)
480
0
                break;
481
214
              vorbiscomment->resize_comments(data[i]>>4);
482
214
            }
483
0
            break;
484
145
            case FLAC__METADATA_TYPE_CUESHEET:
485
145
            {
486
145
              uint32_t num_tracks;
487
145
              FLAC::Metadata::CueSheet * cuesheet = dynamic_cast<FLAC::Metadata::CueSheet *>(metadata_block_transfer);
488
145
              if(cuesheet == 0 || !cuesheet->is_legal())
489
42
                break;
490
103
              num_tracks = cuesheet->get_num_tracks();
491
103
              if(num_tracks > 0) {
492
103
                cuesheet->resize_indices(min(data[i]>>4,num_tracks-1),data[i]>>4);
493
103
              }
494
103
              cuesheet->resize_tracks(data[i]<<4);
495
103
            }
496
0
            break;
497
20
            default:
498
20
            break;
499
505
          }
500
501
505
        }
502
528
        break;
503
528
      case 12: /* Prototype functions */
504
395
        if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
505
362
          const ::FLAC__StreamMetadata * metadata_compare = *metadata_block_transfer;
506
362
          metadata_block_transfer->get_is_last();
507
362
          metadata_block_transfer->get_length();
508
362
          metadata_block_transfer->set_is_last(data[i] & 16);
509
362
          FLAC__metadata_object_is_equal(metadata_compare, metadata_compare);
510
362
        }
511
395
        break;
512
11.3k
    }
513
11.3k
  }
514
2.49k
  if(metadata_block_transfer != 0) {
515
2.17k
    delete metadata_block_transfer;
516
2.17k
    metadata_block_transfer = nullptr;
517
2.17k
  }
518
519
2.49k
  chain.status();
520
2.49k
  chain.sort_padding();
521
2.49k
  chain.merge_padding();
522
523
2.49k
  chain.check_if_tempfile_needed(!use_padding);
524
2.49k
  chain.write(use_padding);
525
526
2.49k
}