Version in base suite: 1.1.1-5 Version in overlay suite: 1.1.1-5sarge1 Base version: flac_1.1.1-5 Target version: flac_1.1.1-5sarge1 Base file: /org/ftp.debian.org/ftp/pool/main/f/flac/flac_1.1.1-5.dsc Target file: /org/ftp.debian.org/ftp/pool/main/f/flac/flac_1.1.1-5sarge1.dsc diff -u flac-1.1.1/debian/changelog flac-1.1.1/debian/changelog --- flac-1.1.1/debian/changelog +++ flac-1.1.1/debian/changelog @@ -1,3 +1,9 @@ +flac (1.1.1-5sarge1) oldstable-security; urgency=high + + * Fix several vulnerabilities. + + -- Moritz Muehlenhoff Sat, 19 Jan 2008 14:43:56 +0100 + flac (1.1.1-5) unstable; urgency=low * libflac++4 Conflicts: libflac++2c102 (= 1.1.1-1) for the same reasons only in patch2: unchanged: --- flac-1.1.1.orig/include/share/alloc.h +++ flac-1.1.1/include/share/alloc.h @@ -0,0 +1,212 @@ +/* alloc - Convenience routines for safely allocating memory + * Copyright (C) 2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FLAC__SHARE__ALLOC_H +#define FLAC__SHARE__ALLOC_H + +#if HAVE_CONFIG_H +# include +#endif + +/* WATCHOUT: for c++ you may have to #define __STDC_LIMIT_MACROS 1 real early + * before #including this file, otherwise SIZE_MAX might not be defined + */ + +#include /* for SIZE_MAX */ +#if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__ +#include /* for SIZE_MAX in case limits.h didn't get it */ +#endif +#include /* for size_t, malloc(), etc */ + +#ifndef SIZE_MAX +# ifndef SIZE_T_MAX +# ifdef _MSC_VER +# define SIZE_T_MAX UINT_MAX +# else +# error +# endif +# endif +# define SIZE_MAX SIZE_T_MAX +#endif + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +/* avoid malloc()ing 0 bytes, see: + * https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003 +*/ +static FLaC__INLINE void *safe_malloc_(size_t size) +{ + /* malloc(0) is undefined; FLAC src convention is to always allocate */ + if(!size) + size++; + return malloc(size); +} + +static FLaC__INLINE void *safe_calloc_(size_t nmemb, size_t size) +{ + if(!nmemb || !size) + return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + return calloc(nmemb, size); +} + +/*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */ + +static FLaC__INLINE void *safe_malloc_add_2op_(size_t size1, size_t size2) +{ + size2 += size1; + if(size2 < size1) + return 0; + return safe_malloc_(size2); +} + +static FLaC__INLINE void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3) +{ + size2 += size1; + if(size2 < size1) + return 0; + size3 += size2; + if(size3 < size2) + return 0; + return safe_malloc_(size3); +} + +static FLaC__INLINE void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4) +{ + size2 += size1; + if(size2 < size1) + return 0; + size3 += size2; + if(size3 < size2) + return 0; + size4 += size3; + if(size4 < size3) + return 0; + return safe_malloc_(size4); +} + +static FLaC__INLINE void *safe_malloc_mul_2op_(size_t size1, size_t size2) +#if 0 +needs support for cases where sizeof(size_t) != 4 +{ + /* could be faster #ifdef'ing off SIZEOF_SIZE_T */ + if(sizeof(size_t) == 4) { + if ((double)size1 * (double)size2 < 4294967296.0) + return malloc(size1*size2); + } + return 0; +} +#else +/* better? */ +{ + if(!size1 || !size2) + return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + if(size1 > SIZE_MAX / size2) + return 0; + return malloc(size1*size2); +} +#endif + +static FLaC__INLINE void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3) +{ + if(!size1 || !size2 || !size3) + return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + if(size1 > SIZE_MAX / size2) + return 0; + size1 *= size2; + if(size1 > SIZE_MAX / size3) + return 0; + return malloc(size1*size3); +} + +/* size1*size2 + size3 */ +static FLaC__INLINE void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3) +{ + if(!size1 || !size2) + return safe_malloc_(size3); + if(size1 > SIZE_MAX / size2) + return 0; + return safe_malloc_add_2op_(size1*size2, size3); +} + +/* size1 * (size2 + size3) */ +static FLaC__INLINE void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3) +{ + if(!size1 || (!size2 && !size3)) + return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + size2 += size3; + if(size2 < size3) + return 0; + return safe_malloc_mul_2op_(size1, size2); +} + +static FLaC__INLINE void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) +{ + size2 += size1; + if(size2 < size1) + return 0; + return realloc(ptr, size2); +} + +static FLaC__INLINE void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) +{ + size2 += size1; + if(size2 < size1) + return 0; + size3 += size2; + if(size3 < size2) + return 0; + return realloc(ptr, size3); +} + +static FLaC__INLINE void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) +{ + size2 += size1; + if(size2 < size1) + return 0; + size3 += size2; + if(size3 < size2) + return 0; + size4 += size3; + if(size4 < size3) + return 0; + return realloc(ptr, size4); +} + +static FLaC__INLINE void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) +{ + if(!size1 || !size2) + return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ + if(size1 > SIZE_MAX / size2) + return 0; + return realloc(ptr, size1*size2); +} + +/* size1 * (size2 + size3) */ +static FLaC__INLINE void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) +{ + if(!size1 || (!size2 && !size3)) + return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ + size2 += size3; + if(size2 < size3) + return 0; + return safe_realloc_mul_2op_(ptr, size1, size2); +} + +#endif only in patch2: unchanged: --- flac-1.1.1.orig/src/libFLAC/md5.c +++ flac-1.1.1/src/libFLAC/md5.c @@ -38,6 +38,8 @@ static FLAC__bool is_big_endian_host_; +#include "share/alloc.h" + #ifndef ASM_MD5 /* The four core functions - F1 is optimized somewhat */ @@ -230,7 +232,13 @@ unsigned channel, sample, a_byte; FLAC__int32 a_word; FLAC__byte *buf_; - const unsigned bytes_needed = channels * samples * bytes_per_sample; + const size_t bytes_needed = (size_t)channels * (size_t)samples * (size_t)bytes_per_sample; + + /* overflow check */ + if((size_t)channels > SIZE_MAX / (size_t)bytes_per_sample) + return false; + if((size_t)channels * (size_t)bytes_per_sample > SIZE_MAX / (size_t)samples) + return false; if(ctx->capacity < bytes_needed) { FLAC__byte *tmp = (FLAC__byte*)realloc(ctx->internal_buf, bytes_needed); only in patch2: unchanged: --- flac-1.1.1.orig/src/libFLAC/memory.c +++ flac-1.1.1/src/libFLAC/memory.c @@ -31,6 +31,7 @@ #include "private/memory.h" #include "FLAC/assert.h" +#include "share/alloc.h" #ifdef HAVE_CONFIG_H #include @@ -44,10 +45,10 @@ #ifdef FLAC__ALIGN_MALLOC_DATA /* align on 32-byte (256-bit) boundary */ - x = malloc(bytes+31); + x = safe_malloc_add_2op_(bytes, /*+*/31); *aligned_address = (void*)(((unsigned)x + 31) & -32); #else - x = malloc(bytes); + x = safe_malloc_(bytes); *aligned_address = x; #endif return x; @@ -62,6 +63,9 @@ FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + pu = (FLAC__int32*)FLAC__memory_alloc_aligned(sizeof(FLAC__int32) * elements, (void**)&pa); if(0 == pu) { return false; @@ -84,6 +88,9 @@ FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + pu = (FLAC__uint32*)FLAC__memory_alloc_aligned(sizeof(FLAC__uint32) * elements, (void**)&pa); if(0 == pu) { return false; @@ -106,6 +113,9 @@ FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + pu = (FLAC__uint64*)FLAC__memory_alloc_aligned(sizeof(FLAC__uint64) * elements, (void**)&pa); if(0 == pu) { return false; @@ -128,6 +138,9 @@ FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + pu = (unsigned*)FLAC__memory_alloc_aligned(sizeof(unsigned) * elements, (void**)&pa); if(0 == pu) { return false; @@ -150,6 +163,9 @@ FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + pu = (FLAC__real*)FLAC__memory_alloc_aligned(sizeof(FLAC__real) * elements, (void**)&pa); if(0 == pu) { return false; only in patch2: unchanged: --- flac-1.1.1.orig/src/libFLAC/metadata_iterators.c +++ flac-1.1.1/src/libFLAC/metadata_iterators.c @@ -48,6 +48,7 @@ #include "FLAC/assert.h" #include "FLAC/file_decoder.h" +#include "share/alloc.h" #ifdef max #undef max @@ -1922,6 +1923,9 @@ if(read_cb(block->id, 1, id_bytes, handle) != id_bytes) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + if(block_length < id_bytes) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block_length -= id_bytes; if(block_length == 0) { @@ -1949,7 +1953,7 @@ if(block->num_points == 0) block->points = 0; - else if(0 == (block->points = (FLAC__StreamMetadata_SeekPoint*)malloc(block->num_points * sizeof(FLAC__StreamMetadata_SeekPoint)))) + else if(0 == (block->points = (FLAC__StreamMetadata_SeekPoint*)safe_malloc_mul_2op_(block->num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; for(i = 0; i < block->num_points; i++) { @@ -2011,7 +2015,7 @@ if(block->num_comments == 0) { block->comments = 0; } - else if(0 == (block->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) + else if(0 == (block->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)safe_calloc_(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; for(i = 0; i < block->num_comments; i++) { @@ -2066,7 +2070,7 @@ if(track->num_indices == 0) { track->indices = 0; } - else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) + else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)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++) { @@ -2126,7 +2130,7 @@ if(block->num_tracks == 0) { block->tracks = 0; } - else if(0 == (block->tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc(block->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) + else if(0 == (block->tracks = (FLAC__StreamMetadata_CueSheet_Track*)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++) { @@ -2810,7 +2814,7 @@ { static const char *tempfile_suffix = ".metadata_edit"; if(0 == tempfile_path_prefix) { - if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1))) { + if(0 == (*tempfilename = (char*)safe_malloc_add_3op_(strlen(filename), /*+*/strlen(tempfile_suffix), /*+*/1))) { *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; return false; } @@ -2824,7 +2828,7 @@ else p++; - if(0 == (*tempfilename = (char*)malloc(strlen(tempfile_path_prefix) + 1 + strlen(p) + strlen(tempfile_suffix) + 1))) { + if(0 == (*tempfilename = (char*)safe_malloc_add_4op_(strlen(tempfile_path_prefix), /*+*/strlen(p), /*+*/strlen(tempfile_suffix), /*+*/2))) { *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; return false; } only in patch2: unchanged: --- flac-1.1.1.orig/src/libFLAC/metadata_object.c +++ flac-1.1.1/src/libFLAC/metadata_object.c @@ -35,6 +35,7 @@ #include "private/metadata.h" #include "FLAC/assert.h" +#include "share/alloc.h" /**************************************************************************** @@ -47,7 +48,7 @@ { if(bytes > 0 && 0 != from) { FLAC__byte *x; - if(0 == (x = (FLAC__byte*)malloc(bytes))) + if(0 == (x = (FLAC__byte*)safe_malloc_(bytes))) return false; memcpy(x, from, bytes); *to = x; @@ -87,7 +88,7 @@ else { FLAC__StreamMetadata_CueSheet_Index *x; FLAC__ASSERT(from->num_indices > 0); - if(0 == (x = (FLAC__StreamMetadata_CueSheet_Index*)malloc(from->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index)))) + if(0 == (x = (FLAC__StreamMetadata_CueSheet_Index*)safe_malloc_mul_2op_(from->num_indices, /*times*/sizeof(FLAC__StreamMetadata_CueSheet_Index)))) return false; memcpy(x, from->indices, from->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index)); to->indices = x; @@ -109,7 +110,7 @@ FLAC__ASSERT(num_points > 0); - object_array = (FLAC__StreamMetadata_SeekPoint*)malloc(num_points * sizeof(FLAC__StreamMetadata_SeekPoint)); + object_array = (FLAC__StreamMetadata_SeekPoint*)safe_malloc_mul_2op_(num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)); if(0 != object_array) { unsigned i; @@ -142,7 +143,7 @@ { FLAC__ASSERT(num_comments > 0); - return (FLAC__StreamMetadata_VorbisComment_Entry*)calloc(num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)); + return (FLAC__StreamMetadata_VorbisComment_Entry*)safe_calloc_(num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)); } static void vorbiscomment_entry_array_delete_(FLAC__StreamMetadata_VorbisComment_Entry *object_array, unsigned num_comments) @@ -248,14 +249,14 @@ { FLAC__ASSERT(num_indices > 0); - return (FLAC__StreamMetadata_CueSheet_Index*)calloc(num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)); + return (FLAC__StreamMetadata_CueSheet_Index*)safe_calloc_(num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)); } static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_new_(unsigned num_tracks) { FLAC__ASSERT(num_tracks > 0); - return (FLAC__StreamMetadata_CueSheet_Track*)calloc(num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)); + return (FLAC__StreamMetadata_CueSheet_Track*)safe_calloc_(num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)); } static void cuesheet_track_array_delete_(FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks) @@ -408,6 +409,10 @@ case FLAC__METADATA_TYPE_PADDING: break; case FLAC__METADATA_TYPE_APPLICATION: + if(to->length < FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8) { /* underflow check */ + FLAC__metadata_object_delete(to); + return 0; + } memcpy(&to->data.application.id, &object->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8); if(!copy_bytes_(&to->data.application.data, object->data.application.data, object->length - FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)) { FLAC__metadata_object_delete(to); @@ -416,6 +421,10 @@ break; case FLAC__METADATA_TYPE_SEEKTABLE: to->data.seek_table.num_points = object->data.seek_table.num_points; + if(to->data.seek_table.num_points > SIZE_MAX / sizeof(FLAC__StreamMetadata_SeekPoint)) { /* overflow check */ + FLAC__metadata_object_delete(to); + return 0; + } if(!copy_bytes_((FLAC__byte**)&to->data.seek_table.points, (FLAC__byte*)object->data.seek_table.points, object->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint))) { FLAC__metadata_object_delete(to); return 0; @@ -742,8 +751,12 @@ return false; } else { - const unsigned old_size = object->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint); - const unsigned new_size = new_num_points * sizeof(FLAC__StreamMetadata_SeekPoint); + const size_t old_size = object->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint); + const size_t new_size = new_num_points * sizeof(FLAC__StreamMetadata_SeekPoint); + + /* overflow check */ + if((size_t)new_num_points > SIZE_MAX / sizeof(FLAC__StreamMetadata_SeekPoint)) + return false; FLAC__ASSERT(object->data.seek_table.num_points > 0); @@ -934,8 +947,12 @@ return false; } else { - const unsigned old_size = object->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry); - const unsigned new_size = new_num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry); + const size_t old_size = object->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry); + const size_t new_size = new_num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry); + + /* overflow check */ + if((size_t)new_num_comments > SIZE_MAX / sizeof(FLAC__StreamMetadata_VorbisComment_Entry)) + return false; FLAC__ASSERT(object->data.vorbis_comment.num_comments > 0); @@ -1139,8 +1156,12 @@ return false; } else { - const unsigned old_size = track->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index); - const unsigned new_size = new_num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index); + const size_t old_size = track->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index); + const size_t new_size = new_num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index); + + /* overflow check */ + if((size_t)new_num_indices > SIZE_MAX / sizeof(FLAC__StreamMetadata_CueSheet_Index)) + return false; FLAC__ASSERT(track->num_indices > 0); @@ -1223,8 +1244,12 @@ return false; } else { - const unsigned old_size = object->data.cue_sheet.num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track); - const unsigned new_size = new_num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track); + const size_t old_size = object->data.cue_sheet.num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track); + const size_t new_size = new_num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track); + + /* overflow check */ + if((size_t)new_num_tracks > SIZE_MAX / sizeof(FLAC__StreamMetadata_CueSheet_Track)) + return false; FLAC__ASSERT(object->data.cue_sheet.num_tracks > 0); only in patch2: unchanged: --- flac-1.1.1.orig/src/libFLAC/stream_decoder.c +++ flac-1.1.1/src/libFLAC/stream_decoder.c @@ -33,6 +33,7 @@ #include /* for malloc() */ #include /* for memset/memcpy() */ #include "FLAC/assert.h" +#include "share/alloc.h" #include "protected/stream_decoder.h" #include "private/bitbuffer.h" #include "private/bitmath.h" @@ -127,7 +128,7 @@ FLAC__StreamMetadata seek_table; FLAC__bool metadata_filter[128]; /* MAGIC number 128 == total number of metadata block types == 1 << 7 */ FLAC__byte *metadata_filter_ids; - unsigned metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */ + size_t metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */ FLAC__Frame frame; FLAC__bool cached; /* true if there is a byte in lookahead */ FLAC__CPUInfo cpuinfo; @@ -213,7 +214,7 @@ } decoder->private_->metadata_filter_ids_capacity = 16; - if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) { + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)safe_malloc_mul_2op_((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), decoder->private_->metadata_filter_ids_capacity))) { FLAC__bitbuffer_delete(decoder->private_->input); free(decoder->private_); free(decoder->protected_); @@ -453,7 +454,7 @@ FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { - if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2))) + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; decoder->private_->metadata_filter_ids_capacity *= 2; } @@ -510,7 +511,7 @@ FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { - if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2))) + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; decoder->private_->metadata_filter_ids_capacity *= 2; } @@ -800,7 +801,7 @@ * (at negative indices) for alignment purposes; we use 4 * to keep the data well-aligned. */ - tmp = (FLAC__int32*)malloc(sizeof(FLAC__int32)*(size+4)); + tmp = (FLAC__int32*)safe_malloc_muladd2_(sizeof(FLAC__int32), /*times (*/size, /*+*/4/*)*/); if(tmp == 0) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; @@ -825,7 +826,7 @@ FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id) { - unsigned i; + size_t i; FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); @@ -943,6 +944,11 @@ if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8, read_callback_, decoder)) return false; /* the read_callback_ sets the state for us */ + if(real_length < FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) { /* underflow check */ + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;/*@@@@@@ maybe wrong error? need to resync?*/ + return false; + } + real_length -= FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8; if(decoder->private_->metadata_filter_ids_count > 0 && has_id_filtered_(decoder, block.data.application.id)) @@ -1000,7 +1006,7 @@ } decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data); - /* now we have to free any malloc'ed data in the block */ + /* now we have to free any malloc()ed data in the block */ switch(type) { case FLAC__METADATA_TYPE_PADDING: break; @@ -1128,7 +1134,7 @@ decoder->private_->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; /* use realloc since we may pass through here several times (e.g. after seeking) */ - if(0 == (decoder->private_->seek_table.data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)realloc(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint)))) { + if(0 == (decoder->private_->seek_table.data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)safe_realloc_mul_2op_(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; } @@ -1184,7 +1190,7 @@ /* read comments */ if(obj->num_comments > 0) { - if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc(obj->num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { + if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)safe_malloc_mul_2op_(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; } @@ -1238,7 +1244,7 @@ obj->num_tracks = x; if(obj->num_tracks > 0) { - if(0 == (obj->tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc(obj->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) { + if(0 == (obj->tracks = (FLAC__StreamMetadata_CueSheet_Track*)safe_calloc_(obj->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; } @@ -1271,7 +1277,7 @@ track->num_indices = (FLAC__byte)x; if(track->num_indices > 0) { - if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) { + if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)safe_calloc_(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; } only in patch2: unchanged: --- flac-1.1.1.orig/src/libFLAC/stream_encoder.c +++ flac-1.1.1/src/libFLAC/stream_encoder.c @@ -35,6 +35,7 @@ #include /* for memcpy() */ #include "FLAC/assert.h" #include "FLAC/stream_decoder.h" +#include "share/alloc.h" #include "protected/stream_encoder.h" #include "private/bitbuffer.h" #include "private/bitmath.h" @@ -802,7 +803,7 @@ */ encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize; for(i = 0; i < encoder->protected_->channels; i++) { - if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size))) + if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)safe_malloc_mul_2op_(sizeof(FLAC__int32), encoder->private_->verify.input_fifo.size))) return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; } encoder->private_->verify.input_fifo.tail = 0; only in patch2: unchanged: --- flac-1.1.1.orig/src/libFLAC/include/private/md5.h +++ flac-1.1.1/src/libFLAC/include/private/md5.h @@ -41,7 +41,7 @@ FLAC__uint32 bytes[2]; FLAC__uint32 in[16]; FLAC__byte *internal_buf; - unsigned capacity; + size_t capacity; }; FLAC_API void FLAC__MD5Init(struct FLAC__MD5Context *context); only in patch2: unchanged: --- flac-1.1.1.orig/src/libFLAC++/metadata.cpp +++ flac-1.1.1/src/libFLAC++/metadata.cpp @@ -29,6 +29,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define __STDC_LIMIT_MACROS 1 /* otherwise SIZE_MAX is not defined for c++ */ +#include "share/alloc.h" #include "FLAC++/metadata.h" #include "FLAC/assert.h" #include // for malloc(), free() @@ -540,7 +542,7 @@ clear_entry(); - if(0 == (entry_.entry = (FLAC__byte*)malloc(field_length))) { + if(0 == (entry_.entry = (FLAC__byte*)safe_malloc_(field_length))) { is_valid_ = false; } else { @@ -577,7 +579,7 @@ clear_field_value(); - if(0 == (field_value_ = (char *)malloc(field_value_length))) { + if(0 == (field_value_ = (char *)safe_malloc_(field_value_length))) { is_valid_ = false; } else { @@ -651,7 +653,7 @@ { clear_entry(); - if(0 == (entry_.entry = (FLAC__byte*)malloc(field_name_length_ + 1 + field_value_length_))) { + if(0 == (entry_.entry = (FLAC__byte*)safe_malloc_add_3op_(field_name_length_, /*+*/ 1, /*+*/ field_value_length_))) { is_valid_ = false; } else { @@ -676,7 +678,7 @@ p = (const char *)entry_.entry + entry_.length; field_name_length_ = p - (const char *)entry_.entry; - if(0 == (field_name_ = (char *)malloc(field_name_length_ + 1))) { // +1 for the trailing \0 + if(0 == (field_name_ = (char *)safe_malloc_add_2op_(field_name_length_, /*+*/1))) { // +1 for the trailing \0 is_valid_ = false; return; } @@ -685,14 +687,14 @@ if(entry_.length - field_name_length_ == 0) { field_value_length_ = 0; - if(0 == (field_value_ = (char *)malloc(0))) { + if(0 == (field_value_ = (char *)safe_malloc_(0))) { is_valid_ = false; return; } } else { field_value_length_ = entry_.length - field_name_length_ - 1; - if(0 == (field_value_ = (char *)malloc(field_value_length_))) { + if(0 == (field_value_ = (char *)safe_malloc_(field_value_length_))) { is_valid_ = false; return; } only in patch2: unchanged: --- flac-1.1.1.orig/src/share/utf8/charset.c +++ flac-1.1.1/src/share/utf8/charset.c @@ -35,6 +35,7 @@ #include +#include "share/alloc.h" #include "charset.h" #include "charmaps.h" @@ -492,7 +493,7 @@ if (!charset1 || !charset2 ) return -1; - tobuf = (char *)malloc(fromlen * charset2->max + 1); + tobuf = (char *)safe_malloc_mul2add_(fromlen, /*times*/charset2->max, /*+*/1); if (!tobuf) return -2; only in patch2: unchanged: --- flac-1.1.1.orig/src/share/utf8/iconvert.c +++ flac-1.1.1/src/share/utf8/iconvert.c @@ -27,6 +27,7 @@ #include #include #include +#include "share/alloc.h" /* * Convert data from one encoding to another. Return: @@ -79,7 +80,7 @@ * This is deliberately not a config option as people often * change their iconv library without rebuilding applications. */ - tocode1 = (char *)malloc(strlen(tocode) + 11); + tocode1 = (char *)safe_malloc_add_2op_(strlen(tocode), /*+*/11); if (!tocode1) goto fail; @@ -117,6 +118,8 @@ break; if (obl < 6) { /* Enlarge the buffer */ + if(utflen*2 < utflen) /* overflow check */ + goto fail; utflen *= 2; newbuf = (char *)realloc(utfbuf, utflen); if (!newbuf) @@ -143,7 +146,7 @@ iconv_close(cd1); return ret; } - newbuf = (char *)realloc(utfbuf, (ob - utfbuf) + 1); + newbuf = (char *)safe_realloc_add_2op_(utfbuf, (ob - utfbuf), /*+*/1); if (!newbuf) goto fail; ob = (ob - utfbuf) + newbuf; @@ -194,7 +197,7 @@ outlen += ob - tbuf; /* Convert from UTF-8 for real */ - outbuf = (char *)malloc(outlen + 1); + outbuf = (char *)safe_malloc_add_2op_(outlen, /*+*/1); if (!outbuf) goto fail; ib = utfbuf; only in patch2: unchanged: --- flac-1.1.1.orig/src/share/utf8/utf8.c +++ flac-1.1.1/src/share/utf8/utf8.c @@ -2,6 +2,8 @@ * Copyright (C) 2001 Peter Harris * Copyright (C) 2001 Edmund Grimley Evans * + * Buffer overflow checking added: Josh Coalson, 9/9/2007 + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -28,6 +30,7 @@ #include #endif +#include "share/alloc.h" #include "utf8.h" #include "charset.h" @@ -43,7 +46,8 @@ static unsigned char *make_utf8_string(const wchar_t *unicode) { - int size = 0, index = 0, out_index = 0; + size_t size = 0, n; + int index = 0, out_index = 0; unsigned char *out; unsigned short c; @@ -51,16 +55,19 @@ c = unicode[index++]; while(c) { if(c < 0x0080) { - size += 1; + n = 1; } else if(c < 0x0800) { - size += 2; + n = 2; } else { - size += 3; + n = 3; } + if(size+n < size) /* overflow check */ + return NULL; + size += n; c = unicode[index++]; - } + } - out = malloc(size + 1); + out = safe_malloc_add_2op_(size, /*+*/1); if (out == NULL) return NULL; index = 0; @@ -87,7 +94,8 @@ static wchar_t *make_unicode_string(const unsigned char *utf8) { - int size = 0, index = 0, out_index = 0; + size_t size = 0; + int index = 0, out_index = 0; wchar_t *out; unsigned char c; @@ -101,11 +109,15 @@ } else { index += 1; } - size += 1; + if(size + 1 == 0) /* overflow check */ + return NULL; + size++; c = utf8[index++]; - } + } - out = malloc((size + 1) * sizeof(wchar_t)); + if(size + 1 == 0) /* overflow check */ + return NULL; + out = safe_malloc_mul_2op_(size+1, /*times*/sizeof(wchar_t)); if (out == NULL) return NULL; index = 0; @@ -147,7 +159,10 @@ return -1; } - unicode = calloc(wchars + 1, sizeof(unsigned short)); + if(wchars < 0) /* underflow check */ + return -1; + + unicode = safe_calloc_((size_t)wchars + 1, sizeof(unsigned short)); if(unicode == NULL) { fprintf(stderr, "Out of memory processing string to UTF8\n"); @@ -190,6 +205,9 @@ chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); + if(chars < 0) /* underflow check */ + return -1; + if(chars == 0) { fprintf(stderr, "Unicode translation error %d\n", GetLastError()); @@ -197,7 +215,7 @@ return -1; } - *to = calloc(chars + 1, sizeof(unsigned char)); + *to = safe_calloc_((size_t)chars + 1, sizeof(unsigned char)); if(*to == NULL) { fprintf(stderr, "Out of memory processing string to local charset\n"); @@ -285,7 +303,7 @@ if (ret != -1) return ret; - s = malloc(fromlen + 1); + s = safe_malloc_add_2op_(fromlen, /*+*/1); if (!s) return -1; strcpy(s, from); only in patch2: unchanged: --- flac-1.1.1.orig/src/metaflac/operations.c +++ flac-1.1.1/src/metaflac/operations.c @@ -21,6 +21,7 @@ #include "utils.h" #include "FLAC/assert.h" #include "FLAC/metadata.h" +#include "share/alloc.h" #include "share/grabbag.h" #include #include @@ -429,8 +430,8 @@ } if( - 0 == (title_gains = (float*)malloc(sizeof(float) * num_files)) || - 0 == (title_peaks = (float*)malloc(sizeof(float) * num_files)) + 0 == (title_gains = (float*)safe_malloc_mul_2op_(sizeof(float), /*times*/num_files)) || + 0 == (title_peaks = (float*)safe_malloc_mul_2op_(sizeof(float), /*times*/num_files)) ) die("out of memory allocating space for title gains/peaks"); only in patch2: unchanged: --- flac-1.1.1.orig/src/metaflac/options.c +++ flac-1.1.1/src/metaflac/options.c @@ -20,6 +20,7 @@ #include "usage.h" #include "utils.h" #include "FLAC/assert.h" +#include "share/alloc.h" #include #include #include @@ -183,7 +184,7 @@ if(options->num_files > 0) { unsigned i = 0; - if(0 == (options->filenames = malloc(sizeof(char *) * options->num_files))) + if(0 == (options->filenames = safe_malloc_mul_2op_(sizeof(char *), /*times*/options->num_files))) die("out of memory allocating space for file names list"); while(share__optind < argc) options->filenames[i++] = local_strdup(argv[share__optind++]); @@ -655,14 +656,16 @@ { if(options->ops.capacity == 0) { options->ops.capacity = 50; - if(0 == (options->ops.operations = malloc(sizeof(Operation) * options->ops.capacity))) + if(0 == (options->ops.operations = safe_malloc_mul_2op_(sizeof(Operation), /*times*/options->ops.capacity))) die("out of memory allocating space for option list"); memset(options->ops.operations, 0, sizeof(Operation) * options->ops.capacity); } if(options->ops.capacity <= options->ops.num_operations) { unsigned original_capacity = options->ops.capacity; - options->ops.capacity *= 4; - if(0 == (options->ops.operations = realloc(options->ops.operations, sizeof(Operation) * options->ops.capacity))) + if(options->ops.capacity > SIZE_MAX / 2) /* overflow check */ + die("out of memory allocating space for option list"); + options->ops.capacity *= 2; + if(0 == (options->ops.operations = safe_realloc_mul_2op_(options->ops.operations, sizeof(Operation), /*times*/options->ops.capacity))) die("out of memory allocating space for option list"); memset(options->ops.operations + original_capacity, 0, sizeof(Operation) * (options->ops.capacity - original_capacity)); } @@ -674,14 +677,16 @@ { if(options->args.capacity == 0) { options->args.capacity = 50; - if(0 == (options->args.arguments = malloc(sizeof(Argument) * options->args.capacity))) + if(0 == (options->args.arguments = safe_malloc_mul_2op_(sizeof(Argument), /*times*/options->args.capacity))) die("out of memory allocating space for option list"); memset(options->args.arguments, 0, sizeof(Argument) * options->args.capacity); } if(options->args.capacity <= options->args.num_arguments) { unsigned original_capacity = options->args.capacity; - options->args.capacity *= 4; - if(0 == (options->args.arguments = realloc(options->args.arguments, sizeof(Argument) * options->args.capacity))) + if(options->args.capacity > SIZE_MAX / 2) /* overflow check */ + die("out of memory allocating space for option list"); + options->args.capacity *= 2; + if(0 == (options->args.arguments = safe_realloc_mul_2op_(options->args.arguments, sizeof(Argument), /*times*/options->args.capacity))) die("out of memory allocating space for option list"); memset(options->args.arguments + original_capacity, 0, sizeof(Argument) * (options->args.capacity - original_capacity)); } @@ -897,7 +902,7 @@ /* make space */ FLAC__ASSERT(out->num_entries > 0); - if(0 == (out->entries = malloc(sizeof(unsigned) * out->num_entries))) + if(0 == (out->entries = safe_malloc_mul_2op_(sizeof(unsigned), /*times*/out->num_entries))) die("out of memory allocating space for option list"); /* load 'em up */ @@ -936,7 +941,7 @@ /* make space */ FLAC__ASSERT(out->num_entries > 0); - if(0 == (out->entries = malloc(sizeof(Argument_BlockTypeEntry) * out->num_entries))) + if(0 == (out->entries = safe_malloc_mul_2op_(sizeof(Argument_BlockTypeEntry), /*times*/out->num_entries))) die("out of memory allocating space for option list"); /* load 'em up */ only in patch2: unchanged: --- flac-1.1.1.orig/src/metaflac/utils.c +++ flac-1.1.1/src/metaflac/utils.c @@ -18,6 +18,7 @@ #include "utils.h" #include "FLAC/assert.h" +#include "share/alloc.h" #include "share/utf8.h" #include #include @@ -53,7 +54,7 @@ void local_strcat(char **dest, const char *source) { - unsigned ndest, nsource; + size_t ndest, nsource; FLAC__ASSERT(0 != dest); FLAC__ASSERT(0 != source); @@ -64,7 +65,7 @@ if(nsource == 0) return; - *dest = realloc(*dest, ndest + nsource + 1); + *dest = safe_realloc_add_3op_(*dest, ndest, /*+*/ nsource, /*+*/ 1); if(0 == *dest) die("out of memory growing string"); strcpy((*dest)+ndest, source); only in patch2: unchanged: --- flac-1.1.1.orig/src/plugin_common/charset.c +++ flac-1.1.1/src/plugin_common/charset.c @@ -83,6 +83,8 @@ /* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */ /* + 1 for nul in case len == 1 */ outsize = ((length + 3) & ~3) + 1; + if(outsize < length) /* overflow check */ + return NULL; out = malloc(outsize); outleft = outsize - 1; outptr = out; @@ -95,6 +97,10 @@ { case E2BIG: used = outptr - out; + if((outsize - 1) * 2 + 1 <= outsize) { /* overflow check */ + free(out); + return NULL; + } outsize = (outsize - 1) * 2 + 1; out = realloc(out, outsize); outptr = out + used; only in patch2: unchanged: --- flac-1.1.1.orig/src/plugin_xmms/plugin.c +++ flac-1.1.1/src/plugin_xmms/plugin.c @@ -331,8 +331,13 @@ /* @@@ how to report the error? */ if(title) { static const char *errtitle = "Invalid FLAC File: "; - *title = g_malloc(strlen(errtitle) + 1 + strlen(filename) + 1 + 1); - sprintf(*title, "%s\"%s\"", errtitle, filename); + if(strlen(errtitle) + 1 + strlen(filename) + 1 + 1 < strlen(filename)) { /* overflow check */ + *title = NULL; + } + else { + *title = g_malloc(strlen(errtitle) + 1 + strlen(filename) + 1 + 1); + sprintf(*title, "%s\"%s\"", errtitle, filename); + } } if(length_in_msec) *length_in_msec = -1;