CVE-2017-7741 (published 2017-04-12T18:59Z)

In libsndfile before 1.0.28, an error in the "flac_buffer_copy()" function (flac.c) can be exploited to cause a segmentation violation (with write memory access) via a specially crafted FLAC file during a resample attempt, a similar issue to CVE-2017-7585.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 5.5, MEDIUM (CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-119
cwe_name: Improper Restriction of Operations within the Bounds of a Memory Buffer
description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
extended_description: 
            Certain languages allow direct addressing of memory locations and do not automatically ensure that these locations are valid for the memory buffer that is being referenced. This can cause read or write operations to be performed on memory locations that may be associated with other variables, data structures, or internal program data.
         
         

Fix information:
repo_url: https://github.com/erikd/libsndfile
commit_details: repo_url: https://github.com/erikd/libsndfile
author: Erik de Castro Lopo
author_date: 2017-03-24 20:51:59+11:00
msg: src/flac.c: Improve error handling

Especially when dealing with corrupt or malicious files.
repository: repo_url: https://github.com/erikd/libsndfile
repo_name: libsndfile/libsndfile
description: A C library for reading and writing sound files containing sampled audio data.
repo_language: C
owner: erikd
file_changes: filename: flac.c
change_type: ModificationType.MODIFY
diff: @@ -68,9 +68,9 @@ typedef struct
 	unsigned bufferpos ;
 
 	const FLAC__Frame *frame ;
-	FLAC__bool bufferbackup ;
 
 	unsigned compression ;
+
 } FLAC_PRIVATE ;
 
 typedef struct
@@ -187,10 +187,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 < channels ; i++)
 		{
 			if (pflac->rbuffer [i] == NULL)
@@ -206,6 +205,11 @@ flac_buffer_copy (SF_PRIVATE *psf)
 
 	len = SF_MIN (pflac->len, frame->header.blocksize) ;
 
+	if (pflac->remain % channels != 0)
+	{	psf_log_printf (psf, "Error: pflac->remain %u    channels %u\n", pflac->remain, channels) ;
+		return 0 ;
+		} ;
+
 	switch (pflac->pcmtype)
 	{	case PFLAC_PCM_SHORT :
 			{	short *retpcm = (short*) pflac->ptr ;
@@ -381,7 +385,6 @@ sf_flac_write_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC
 	pflac->frame = frame ;
 	pflac->bufferpos = 0 ;
 
-	pflac->bufferbackup = SF_FALSE ;
 	pflac->wbuffer = buffer ;
 
 	flac_buffer_copy (psf) ;
@@ -907,11 +910,19 @@ 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) ;
@@ -920,8 +931,13 @@ flac_read_loop (SF_PRIVATE *psf, unsigned len)
 	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 ;

programming_language: C