Vulnerability: An out-of-bounds read flaw was found in libsndfile's FLAC codec functionality. An attacker who is able to submit a specially crafted file (via tricking a user to open or otherwise) to an application linked with libsndfile and using the FLAC codec, could trigger an out-of-bounds read that would most likely cause a crash but could potentially leak memory information that could be used in further exploitation of other flaws.
Vulnerability ID: CVE-2021-4156
CWE: CWE-125
Severity score: 4.9
Project: https://github.com/libsndfile/libsndfile
Published: 2022-03-23
File: src/flac.c
Commit message: flac: Fix improper buffer reusing
Commit author: yuawn

Vulnerable version (before fix):
 typedef struct 	FLAC__StreamMetadata *metadata ;  	const int32_t * const * wbuffer ; 	int32_t * rbuffer [FLAC__MAX_CHANNELS] ;  	int32_t* encbuffer ; flac_buffer_copy (SF_PRIVATE *psf) 		return 0 ; 		} ;  	if (frame->header.channels > FLAC__MAX_CHANNELS) 		psf_log_printf (psf, "Ooops : frame->header.channels (%d) > FLAC__MAX_BLOCK_SIZE (%d)\n", __func__, __LINE__, frame->header.channels, FLAC__MAX_CHANNELS) ;  sf_flac_write_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC 	pflac->bufferpos = 0 ;  	pflac->wbuffer = buffer ;  	flac_buffer_copy (psf) ; 

Fixed version (after fix):
 typedef struct 	FLAC__StreamMetadata *metadata ;  	const int32_t * const * wbuffer ; 	unsigned wbuffer_size ; 	int32_t * rbuffer [FLAC__MAX_CHANNELS] ;  	int32_t* encbuffer ; flac_buffer_copy (SF_PRIVATE *psf) 		return 0 ; 		} ;  	if (frame->header.blocksize > pflac->wbuffer_size) 	{	psf_log_printf (psf, "Ooops : frame->header.blocksize (%d) > pflac->wbuffer_size (%d)\n", __func__, __LINE__, frame->header.blocksize, pflac->wbuffer_size) ; 		psf->error = SFE_INTERNAL ; 		return 0 ; 		} ;  	if (frame->header.channels > FLAC__MAX_CHANNELS) 		psf_log_printf (psf, "Ooops : frame->header.channels (%d) > FLAC__MAX_BLOCK_SIZE (%d)\n", __func__, __LINE__, frame->header.channels, FLAC__MAX_CHANNELS) ;  sf_flac_write_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC 	pflac->bufferpos = 0 ;  	pflac->wbuffer = buffer ; 	pflac->wbuffer_size = pflac->frame->header.blocksize ;  	flac_buffer_copy (psf) ; 

Patch:
patch: @@ -62,6 +62,7 @@ typedef struct
 	FLAC__StreamMetadata *metadata ;
 
 	const int32_t * const * wbuffer ;
+	unsigned wbuffer_size ;
 	int32_t * rbuffer [FLAC__MAX_CHANNELS] ;
 
 	int32_t* encbuffer ;
@@ -188,6 +189,12 @@ flac_buffer_copy (SF_PRIVATE *psf)
 		return 0 ;
 		} ;
 
+	if (frame->header.blocksize > pflac->wbuffer_size)
+	{	psf_log_printf (psf, "Ooops : frame->header.blocksize (%d) > pflac->wbuffer_size (%d)\n", __func__, __LINE__, frame->header.blocksize, pflac->wbuffer_size) ;
+		psf->error = SFE_INTERNAL ;
+		return 0 ;
+		} ;
+
 	if (frame->header.channels > FLAC__MAX_CHANNELS)
 		psf_log_printf (psf, "Ooops : frame->header.channels (%d) > FLAC__MAX_BLOCK_SIZE (%d)\n", __func__, __LINE__, frame->header.channels, FLAC__MAX_CHANNELS) ;
 
@@ -393,6 +400,7 @@ sf_flac_write_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC
 	pflac->bufferpos = 0 ;
 
 	pflac->wbuffer = buffer ;
+	pflac->wbuffer_size = pflac->frame->header.blocksize ;
 
 	flac_buffer_copy (psf) ;
path: src/flac.c