Skip to content

Commit 60b2343

Browse files
committed
src/flac.c: Improve error handling
Especially when dealing with corrupt or malicious files.
1 parent febad46 commit 60b2343

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

src/flac.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ typedef struct
6868
unsigned bufferpos ;
6969

7070
const FLAC__Frame *frame ;
71-
FLAC__bool bufferbackup ;
7271

7372
unsigned compression ;
73+
7474
} FLAC_PRIVATE ;
7575

7676
typedef struct
@@ -187,10 +187,9 @@ flac_buffer_copy (SF_PRIVATE *psf)
187187

188188
if (pflac->ptr == NULL)
189189
{ /*
190-
** Not sure why this code is here and not elsewhere.
191-
** Removing it causes valgrind errors.
190+
** This pointer is reset to NULL each time the current frame has been
191+
** decoded. Somehow its used during encoding and decoding.
192192
*/
193-
pflac->bufferbackup = SF_TRUE ;
194193
for (i = 0 ; i < channels ; i++)
195194
{
196195
if (pflac->rbuffer [i] == NULL)
@@ -206,6 +205,11 @@ flac_buffer_copy (SF_PRIVATE *psf)
206205

207206
len = SF_MIN (pflac->len, frame->header.blocksize) ;
208207

208+
if (pflac->remain % channels != 0)
209+
{ psf_log_printf (psf, "Error: pflac->remain %u channels %u\n", pflac->remain, channels) ;
210+
return 0 ;
211+
} ;
212+
209213
switch (pflac->pcmtype)
210214
{ case PFLAC_PCM_SHORT :
211215
{ short *retpcm = (short*) pflac->ptr ;
@@ -381,7 +385,6 @@ sf_flac_write_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC
381385
pflac->frame = frame ;
382386
pflac->bufferpos = 0 ;
383387

384-
pflac->bufferbackup = SF_FALSE ;
385388
pflac->wbuffer = buffer ;
386389

387390
flac_buffer_copy (psf) ;
@@ -907,11 +910,19 @@ flac_init (SF_PRIVATE *psf)
907910
static unsigned
908911
flac_read_loop (SF_PRIVATE *psf, unsigned len)
909912
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
913+
FLAC__StreamDecoderState state ;
910914

911915
pflac->pos = 0 ;
912916
pflac->len = len ;
913917
pflac->remain = len ;
914918

919+
state = FLAC__stream_decoder_get_state (pflac->fsd) ;
920+
if (state > FLAC__STREAM_DECODER_END_OF_STREAM)
921+
{ psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ;
922+
/* Current frame is busted, so NULL the pointer. */
923+
pflac->frame = NULL ;
924+
} ;
925+
915926
/* First copy data that has already been decoded and buffered. */
916927
if (pflac->frame != NULL && pflac->bufferpos < pflac->frame->header.blocksize)
917928
flac_buffer_copy (psf) ;
@@ -920,8 +931,13 @@ flac_read_loop (SF_PRIVATE *psf, unsigned len)
920931
while (pflac->pos < pflac->len)
921932
{ if (FLAC__stream_decoder_process_single (pflac->fsd) == 0)
922933
break ;
923-
if (FLAC__stream_decoder_get_state (pflac->fsd) >= FLAC__STREAM_DECODER_END_OF_STREAM)
934+
state = FLAC__stream_decoder_get_state (pflac->fsd) ;
935+
if (state >= FLAC__STREAM_DECODER_END_OF_STREAM)
936+
{ psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ;
937+
/* Current frame is busted, so NULL the pointer. */
938+
pflac->frame = NULL ;
924939
break ;
940+
} ;
925941
} ;
926942

927943
pflac->ptr = NULL ;

0 commit comments

Comments
 (0)