diff --git a/include/FLAC/assert.h b/include/FLAC/assert.h index a99ced3353..86e0486ad3 100644 --- a/include/FLAC/assert.h +++ b/include/FLAC/assert.h @@ -36,14 +36,17 @@ /* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #define FLAC__ASSERT(x) if(!(x)) __builtin_abort(); +#define FLAC__ASSERT_IF_NOT_FUZZING(x) #define FLAC__ASSERT_DECLARATION(x) x #else #ifndef NDEBUG #include #define FLAC__ASSERT(x) assert(x) +#define FLAC__ASSERT_IF_NOT_FUZZING(x) assert(x) #define FLAC__ASSERT_DECLARATION(x) x #else #define FLAC__ASSERT(x) +#define FLAC__ASSERT_IF_NOT_FUZZING(x) #define FLAC__ASSERT_DECLARATION(x) #endif #endif diff --git a/oss-fuzz/encoder_v2.cc b/oss-fuzz/encoder_v2.cc index 3dc02549ec..410c993ebe 100644 --- a/oss-fuzz/encoder_v2.cc +++ b/oss-fuzz/encoder_v2.cc @@ -187,8 +187,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) } if(encoder_valid && (metadata_mask & 4) && size > 20){ FLAC__byte * application_data = (FLAC__byte *)malloc(size-20); - if(0 != application_data && ((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) == NULL)) + if(0 != application_data && ((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) == NULL)) { encoder_valid = false; + free(application_data); + } else { memcpy(application_data,data+20,size-20); FLAC__metadata_object_application_set_data(metadata[num_metadata++], application_data, size-20, 0); diff --git a/oss-fuzz/metadata.cc b/oss-fuzz/metadata.cc index 6f1595e93b..fe3f0466d4 100644 --- a/oss-fuzz/metadata.cc +++ b/oss-fuzz/metadata.cc @@ -40,6 +40,12 @@ #define min(x,y) (x> 4; - if(0)//data[1] < 128) /* Use MSB as on/off */ + if(data[1] < 128) /* Use MSB as on/off */ alloc_check_threshold = data[1]; else alloc_check_threshold = INT32_MAX; @@ -83,7 +89,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) } run_tests_with_level_0_interface(filename); + alloc_check_counter = 0; run_tests_with_level_1_interface(filename, init_bools[1], init_bools[2], data+CONFIG_LENGTH, command_length/2); + alloc_check_counter = 0; /* Dump input to file, to start fresh for level 2 */ if(!init_bools[1]){ @@ -177,7 +185,7 @@ static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use FLAC::Metadata::Prototype *metadata_block_transfer = nullptr; FLAC::Metadata::Prototype *metadata_block_put = nullptr; - if(!chain.is_valid()) + if(!chain.is_valid() || !iterator.is_valid()) return; if(!chain.read(filename, ogg)) @@ -207,10 +215,14 @@ static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use delete metadata_block_transfer; metadata_block_transfer = nullptr; metadata_block_transfer = FLAC::Metadata::clone(metadata_block_get); + if(!metadata_block_transfer->is_valid()) + THROW_AWAY_TRANSFER } } else { metadata_block_transfer = FLAC::Metadata::clone(metadata_block_get); + if(!metadata_block_transfer->is_valid()) + THROW_AWAY_TRANSFER } } delete metadata_block_get; @@ -293,14 +305,16 @@ static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use num_tracks = cuesheet->get_num_tracks(); if(num_tracks > 0) { FLAC::Metadata::CueSheet::Track track = cuesheet->get_track(min(data[i]>>4,num_tracks-1)); - track.get_offset(); - track.get_number(); - track.get_isrc(); - track.get_pre_emphasis(); - num_indices = track.get_num_indices(); - if(num_indices > 0) { - FLAC__StreamMetadata_CueSheet_Index index = track.get_index(min(data[i]>>4,num_indices-1)); - (void)index; + if(track.is_valid()) { + track.get_offset(); + track.get_number(); + track.get_isrc(); + track.get_pre_emphasis(); + num_indices = track.get_num_indices(); + if(num_indices > 0) { + FLAC__StreamMetadata_CueSheet_Index index = track.get_index(min(data[i]>>4,num_indices-1)); + (void)index; + } } } } @@ -442,9 +456,11 @@ static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use num_tracks = cuesheet->get_num_tracks(); if(num_tracks > 0) { FLAC::Metadata::CueSheet::Track track = cuesheet->get_track(min(data[i]>>4,num_tracks-1)); - if(track.get_num_indices() > 0) - cuesheet->delete_index(min(data[i]>>4,num_tracks-1),0); - cuesheet->delete_track(0); + if(track.is_valid()) { + if(track.get_num_indices() > 0) + cuesheet->delete_index(min(data[i]>>4,num_tracks-1),0); + cuesheet->delete_track(0); + } } } break; @@ -478,7 +494,8 @@ static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast(metadata_block_transfer); if(vorbiscomment == 0) break; - vorbiscomment->resize_comments(data[i]>>4); + if(!vorbiscomment->resize_comments(data[i]>>4)) + THROW_AWAY_TRANSFER } break; case FLAC__METADATA_TYPE_CUESHEET: diff --git a/src/libFLAC++/metadata.cpp b/src/libFLAC++/metadata.cpp index 9edf6a97c9..d13dd705df 100644 --- a/src/libFLAC++/metadata.cpp +++ b/src/libFLAC++/metadata.cpp @@ -152,7 +152,9 @@ namespace FLAC { object_(copy? ::FLAC__metadata_object_clone(object) : object), is_reference_(false) { +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION FLAC__ASSERT(0 != object); +#endif } Prototype::~Prototype() @@ -599,7 +601,7 @@ namespace FLAC { VorbisComment::Entry &VorbisComment::Entry::operator=(const Entry &entry) { - FLAC__ASSERT(entry.is_valid()); + FLAC__ASSERT_IF_NOT_FUZZING(entry.is_valid()); clear(); construct(reinterpret_cast(entry.entry_.entry), entry.entry_.length); return *this; diff --git a/src/libFLAC/bitreader.c b/src/libFLAC/bitreader.c index 11f2af4866..f928b3ca35 100644 --- a/src/libFLAC/bitreader.c +++ b/src/libFLAC/bitreader.c @@ -42,6 +42,7 @@ #include "private/cpu.h" #include "private/macros.h" #include "FLAC/assert.h" +#include "share/alloc.h" #include "share/compat.h" #include "share/endswap.h" @@ -255,7 +256,7 @@ static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) FLAC__BitReader *FLAC__bitreader_new(void) { - FLAC__BitReader *br = calloc(1, sizeof(FLAC__BitReader)); + FLAC__BitReader *br = safe_calloc_(1, sizeof(FLAC__BitReader)); /* calloc() implies: memset(br, 0, sizeof(FLAC__BitReader)); @@ -290,7 +291,7 @@ FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__BitReaderReadCallback br->words = br->bytes = 0; br->consumed_words = br->consumed_bits = 0; br->capacity = FLAC__BITREADER_DEFAULT_CAPACITY; - br->buffer = malloc(sizeof(brword) * br->capacity); + br->buffer = safe_malloc_(sizeof(brword) * br->capacity); if(br->buffer == 0) return false; br->read_callback = rcb; diff --git a/src/libFLAC/bitwriter.c b/src/libFLAC/bitwriter.c index de3ebea2ae..c20b09bd87 100644 --- a/src/libFLAC/bitwriter.c +++ b/src/libFLAC/bitwriter.c @@ -156,7 +156,7 @@ FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, uint32_t bits_to_add) FLAC__BitWriter *FLAC__bitwriter_new(void) { - FLAC__BitWriter *bw = calloc(1, sizeof(FLAC__BitWriter)); + FLAC__BitWriter *bw = safe_calloc_(1, sizeof(FLAC__BitWriter)); /* note that calloc() sets all members to 0 for us */ return bw; } @@ -181,7 +181,7 @@ FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw) bw->words = bw->bits = 0; bw->capacity = FLAC__BITWRITER_DEFAULT_CAPACITY; - bw->buffer = malloc(sizeof(bwword) * bw->capacity); + bw->buffer = safe_malloc_(sizeof(bwword) * bw->capacity); if(bw->buffer == 0) return false; diff --git a/src/libFLAC/memory.c b/src/libFLAC/memory.c index 963f4ad43d..ed5b41e876 100644 --- a/src/libFLAC/memory.c +++ b/src/libFLAC/memory.c @@ -212,8 +212,8 @@ FLAC__bool FLAC__memory_alloc_aligned_real_array(size_t elements, FLAC__real **u void *safe_malloc_mul_2op_p(size_t size1, size_t size2) { if(!size1 || !size2) - return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + return safe_malloc_(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ if(size1 > SIZE_MAX / size2) return 0; - return malloc(size1*size2); + return safe_malloc_(size1*size2); } diff --git a/src/libFLAC/metadata_iterators.c b/src/libFLAC/metadata_iterators.c index f68b451b60..e10f84e27b 100644 --- a/src/libFLAC/metadata_iterators.c +++ b/src/libFLAC/metadata_iterators.c @@ -385,7 +385,7 @@ FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[] = { FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void) { - FLAC__Metadata_SimpleIterator *iterator = calloc(1, sizeof(FLAC__Metadata_SimpleIterator)); + FLAC__Metadata_SimpleIterator *iterator = safe_calloc_(1, sizeof(FLAC__Metadata_SimpleIterator)); if(0 != iterator) { iterator->file = 0; @@ -982,7 +982,7 @@ FLAC_API const char * const FLAC__Metadata_ChainStatusString[] = { static FLAC__Metadata_Node *node_new_(void) { - return calloc(1, sizeof(FLAC__Metadata_Node)); + return safe_calloc_(1, sizeof(FLAC__Metadata_Node)); } static void node_delete_(FLAC__Metadata_Node *node) @@ -1582,7 +1582,7 @@ static FLAC__bool chain_rewrite_file_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHa FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void) { - FLAC__Metadata_Chain *chain = calloc(1, sizeof(FLAC__Metadata_Chain)); + FLAC__Metadata_Chain *chain = safe_calloc_(1, sizeof(FLAC__Metadata_Chain)); if(0 != chain) chain_init_(chain); @@ -1976,7 +1976,7 @@ FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain) FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void) { - FLAC__Metadata_Iterator *iterator = calloc(1, sizeof(FLAC__Metadata_Iterator)); + FLAC__Metadata_Iterator *iterator = safe_calloc_(1, sizeof(FLAC__Metadata_Iterator)); /* calloc() implies: iterator->current = 0; @@ -2312,7 +2312,7 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLA block->data = 0; } else { - if(0 == (block->data = malloc(block_length))) + if(0 == (block->data = safe_malloc_(block_length))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; if(read_cb(block->data, 1, block_length, handle) != block_length) @@ -2413,7 +2413,7 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_( status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA; goto skip; } - else if(0 == (block->comments = calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { + else if(0 == (block->comments = safe_calloc_(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { block->num_comments = 0; return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; } @@ -2483,7 +2483,7 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_( if(track->num_indices == 0) { track->indices = 0; } - else if(0 == (track->indices = calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) + else if(0 == (track->indices = safe_calloc_(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; for(i = 0; i < track->num_indices; i++) { @@ -2543,7 +2543,7 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__ if(block->num_tracks == 0) { return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA; } - else if(0 == (block->tracks = calloc(block->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) + else if(0 == (block->tracks = safe_calloc_(block->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; for(i = 0; i < block->num_tracks; i++) { @@ -2649,7 +2649,7 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__I block->data = 0; } else { - if(0 == (block->data = malloc(block_length))) + if(0 == (block->data = safe_malloc_(block_length))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; if(read_cb(block->data, 1, block_length, handle) != block_length) diff --git a/src/libFLAC/metadata_object.c b/src/libFLAC/metadata_object.c index d0106d2a72..082116e6c8 100644 --- a/src/libFLAC/metadata_object.c +++ b/src/libFLAC/metadata_object.c @@ -437,7 +437,7 @@ FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_new(FLAC__MetadataType type if (type > FLAC__MAX_METADATA_TYPE) return 0; - object = calloc(1, sizeof(FLAC__StreamMetadata)); + object = safe_calloc_(1, sizeof(FLAC__StreamMetadata)); if (object != NULL) { object->is_last = false; object->type = type; @@ -958,7 +958,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMe else { /* Leave object->data.seek_table.points untouched if realloc fails */ FLAC__StreamMetadata_SeekPoint *tmpptr; - if ((tmpptr = realloc(object->data.seek_table.points, new_size)) == NULL) + if ((tmpptr = realloc_(object->data.seek_table.points, new_size)) == NULL) return false; object->data.seek_table.points = tmpptr; } @@ -1217,7 +1217,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__St else { /* Leave object->data.vorbis_comment.comments untouched if realloc fails */ FLAC__StreamMetadata_VorbisComment_Entry *tmpptr; - if ((tmpptr = realloc(object->data.vorbis_comment.comments, new_size)) == NULL) + if ((tmpptr = realloc_(object->data.vorbis_comment.comments, new_size)) == NULL) return false; object->data.vorbis_comment.comments = tmpptr; } @@ -1465,7 +1465,7 @@ FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__S FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void) { - return calloc(1, sizeof(FLAC__StreamMetadata_CueSheet_Track)); + return safe_calloc_(1, sizeof(FLAC__StreamMetadata_CueSheet_Track)); } FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_clone(const FLAC__StreamMetadata_CueSheet_Track *object) @@ -1533,7 +1533,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__St else { /* Leave track->indices untouched if realloc fails */ FLAC__StreamMetadata_CueSheet_Index *tmpptr; - if ((tmpptr = realloc(track->indices, new_size)) == NULL) + if ((tmpptr = realloc_(track->indices, new_size)) == NULL) return false; track->indices = tmpptr; } @@ -1633,7 +1633,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMet else { /* Leave object->data.cue_sheet.tracks untouched if realloc fails */ FLAC__StreamMetadata_CueSheet_Track *tmpptr; - if ((tmpptr = realloc(object->data.cue_sheet.tracks, new_size)) == NULL) + if ((tmpptr = realloc_(object->data.cue_sheet.tracks, new_size)) == NULL) return false; object->data.cue_sheet.tracks = tmpptr; } diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c index 5f21719395..88f891102b 100644 --- a/src/libFLAC/stream_decoder.c +++ b/src/libFLAC/stream_decoder.c @@ -280,7 +280,7 @@ FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void) } decoder->private_->metadata_filter_ids_capacity = 16; - if(0 == (decoder->private_->metadata_filter_ids = malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) { + if(0 == (decoder->private_->metadata_filter_ids = safe_malloc_((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) { FLAC__bitreader_delete(decoder->private_->input); free(decoder->private_); free(decoder->protected_); @@ -1622,7 +1622,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) case FLAC__METADATA_TYPE_APPLICATION: /* remember, we read the ID already */ if(real_length > 0) { - if(0 == (block.data.application.data = malloc(real_length))) { + if(0 == (block.data.application.data = safe_malloc_(real_length))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; ok = false; } @@ -1650,7 +1650,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) break; default: if(real_length > 0) { - if(0 == (block.data.unknown.data = malloc(real_length))) { + if(0 == (block.data.unknown.data = safe_malloc_(real_length))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; ok = false; }