File 0003-src-flac.c-Improve-error-handling.patch of Package libsndfile.4624
From 60b234301adf258786d8b90be5c1d437fc8799e0 Mon Sep 17 00:00:00 2001
From: Erik de Castro Lopo <erikd@mega-nerd.com>
Date: Fri, 24 Mar 2017 20:51:59 +1100
Subject: [PATCH] src/flac.c: Improve error handling
Especially when dealing with corrupt or malicious files.
---
src/flac.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
--- a/src/flac.c
+++ b/src/flac.c
@@ -66,7 +66,6 @@ typedef struct
unsigned bufferpos ;
const FLAC__Frame *frame ;
- FLAC__bool bufferbackup ;
} FLAC_PRIVATE ;
typedef struct
@@ -177,10 +176,9 @@ flac_buffer_copy (SF_PRIVATE *psf)
if (pflac->ptr == NULL)
{ /*
- ** Not sure why this code is here and not elsewhere.
- ** Removing it causes valgrind errors.
+ ** This pointer is reset to NULL each time the current frame has been
+ ** decoded. Somehow its used during encoding and decoding.
*/
- pflac->bufferbackup = SF_TRUE ;
for (i = 0 ; i < frame->header.channels ; i++)
{
if (pflac->rbuffer [i] == NULL)
@@ -193,6 +191,11 @@ flac_buffer_copy (SF_PRIVATE *psf)
return 0 ;
} ;
+ if (pflac->remain % frame->header.channels != 0)
+ { psf_log_printf (psf, "Error: pflac->remain %u channels %u\n", pflac->remain, frame->header.channels) ;
+ return 0 ;
+ } ;
+
switch (pflac->pcmtype)
{ case PFLAC_PCM_SHORT :
{ short *retpcm = (short*) pflac->ptr ;
@@ -353,7 +356,6 @@ sf_flac_write_callback (const FLAC__Stre
pflac->frame = frame ;
pflac->bufferpos = 0 ;
- pflac->bufferbackup = SF_FALSE ;
pflac->wbuffer = buffer ;
flac_buffer_copy (psf) ;
@@ -835,18 +837,33 @@ flac_init (SF_PRIVATE *psf)
static unsigned
flac_read_loop (SF_PRIVATE *psf, unsigned len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
+ FLAC__StreamDecoderState state ;
pflac->pos = 0 ;
pflac->len = len ;
pflac->remain = len ;
+
+ state = FLAC__stream_decoder_get_state (pflac->fsd) ;
+ if (state > FLAC__STREAM_DECODER_END_OF_STREAM)
+ { psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ;
+ /* Current frame is busted, so NULL the pointer. */
+ pflac->frame = NULL ;
+ } ;
+
+ /* First copy data that has already been decoded and buffered. */
if (pflac->frame != NULL && pflac->bufferpos < pflac->frame->header.blocksize)
flac_buffer_copy (psf) ;
while (pflac->pos < pflac->len)
{ if (FLAC__stream_decoder_process_single (pflac->fsd) == 0)
break ;
- if (FLAC__stream_decoder_get_state (pflac->fsd) >= FLAC__STREAM_DECODER_END_OF_STREAM)
+ state = FLAC__stream_decoder_get_state (pflac->fsd) ;
+ if (state >= FLAC__STREAM_DECODER_END_OF_STREAM)
+ { psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ;
+ /* Current frame is busted, so NULL the pointer. */
+ pflac->frame = NULL ;
break ;
+ } ;
} ;
pflac->ptr = NULL ;