Blame SOURCES/libsndfile-1.0.28-cve2017_12562.patch

327a27
From cf7a8182c2642c50f1cf90dddea9ce96a8bad2e8 Mon Sep 17 00:00:00 2001
327a27
From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= <osmanx@problemloesungsmaschine.de>
327a27
Date: Wed, 14 Jun 2017 12:25:40 +0200
327a27
Subject: [PATCH] src/common.c: Fix heap buffer overflows when writing strings
327a27
 in binheader
327a27
327a27
Fixes the following problems:
327a27
 1. Case 's' only enlarges the buffer by 16 bytes instead of size bytes.
327a27
 2. psf_binheader_writef() enlarges the header buffer (if needed) prior to the
327a27
    big switch statement by an amount (16 bytes) which is enough for all cases
327a27
    where only a single value gets added. Cases 's', 'S', 'p' however
327a27
    additionally write an arbitrary length block of data and again enlarge the
327a27
    buffer to the required amount. However, the required space calculation does
327a27
    not take into account the size of the length field which gets output before
327a27
    the data.
327a27
 3. Buffer size requirement calculation in case 'S' does not account for the
327a27
    padding byte ("size += (size & 1) ;" happens after the calculation which
327a27
    uses "size").
327a27
 4. Case 'S' can overrun the header buffer by 1 byte when no padding is
327a27
    involved
327a27
    ("memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size + 1) ;" while
327a27
    the buffer is only guaranteed to have "size" space available).
327a27
 5. "psf->header.ptr [psf->header.indx] = 0 ;" in case 'S' always writes 1 byte
327a27
    beyond the space which is guaranteed to be allocated in the header buffer.
327a27
 6. Case 's' can overrun the provided source string by 1 byte if padding is
327a27
    involved ("memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;"
327a27
    where "size" is "strlen (strptr) + 1" (which includes the 0 terminator,
327a27
    plus optionally another 1 which is padding and not guaranteed to be
327a27
    readable via the source string pointer).
327a27
327a27
Closes: https://github.com/erikd/libsndfile/issues/292
327a27
---
327a27
 src/common.c | 15 +++++++--------
327a27
 1 file changed, 7 insertions(+), 8 deletions(-)
327a27
327a27
diff --git a/src/common.c b/src/common.c
327a27
index 1a6204ca..6b2a2ee9 100644
327a27
--- a/src/common.c
327a27
+++ b/src/common.c
327a27
@@ -681,16 +681,16 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
327a27
 					/* Write a C string (guaranteed to have a zero terminator). */
327a27
 					strptr = va_arg (argptr, char *) ;
327a27
 					size = strlen (strptr) + 1 ;
327a27
-					size += (size & 1) ;
327a27
 
327a27
-					if (psf->header.indx + (sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, 16))
327a27
+					if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
327a27
 						return count ;
327a27
 
327a27
 					if (psf->rwf_endian == SF_ENDIAN_BIG)
327a27
-						header_put_be_int (psf, size) ;
327a27
+						header_put_be_int (psf, size + (size & 1)) ;
327a27
 					else
327a27
-						header_put_le_int (psf, size) ;
327a27
+						header_put_le_int (psf, size + (size & 1)) ;
327a27
 					memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
327a27
+					size += (size & 1) ;
327a27
 					psf->header.indx += size ;
327a27
 					psf->header.ptr [psf->header.indx - 1] = 0 ;
327a27
 					count += 4 + size ;
327a27
@@ -703,16 +703,15 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
327a27
 					*/
327a27
 					strptr = va_arg (argptr, char *) ;
327a27
 					size = strlen (strptr) ;
327a27
-					if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
327a27
+					if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
327a27
 						return count ;
327a27
 					if (psf->rwf_endian == SF_ENDIAN_BIG)
327a27
 						header_put_be_int (psf, size) ;
327a27
 					else
327a27
 						header_put_le_int (psf, size) ;
327a27
-					memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size + 1) ;
327a27
+					memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size + (size & 1)) ;
327a27
 					size += (size & 1) ;
327a27
 					psf->header.indx += size ;
327a27
-					psf->header.ptr [psf->header.indx] = 0 ;
327a27
 					count += 4 + size ;
327a27
 					break ;
327a27
 
327a27
@@ -724,7 +723,7 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
327a27
 					size = (size & 1) ? size : size + 1 ;
327a27
 					size = (size > 254) ? 254 : size ;
327a27
 
327a27
-					if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
327a27
+					if (psf->header.indx + 1 + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, 1 + size))
327a27
 						return count ;
327a27
 
327a27
 					header_put_byte (psf, size) ;