Blame SOURCES/libarchive-3.3.2-CVE-2019-19221.patch

557ba4
From 72085b30bf30867360c4aa77bd43de5e1788d875 Mon Sep 17 00:00:00 2001
557ba4
From: Ondrej Dubaj <odubaj@redhat.com>
557ba4
Date: Tue, 24 Mar 2020 09:22:47 +0100
557ba4
Subject: [PATCH] Bugfix and optimize archive_wstring_append_from_mbs()
557ba4
557ba4
The cal to mbrtowc() or mbtowc() should read up to mbs_length
557ba4
bytes and not wcs_length. This avoids out-of-bounds reads.
557ba4
557ba4
mbrtowc() and mbtowc() return (size_t)-1 wit errno EILSEQ when
557ba4
they encounter an invalid multibyte character and (size_t)-2 when
557ba4
they they encounter an incomplete multibyte character. As we return
557ba4
failure and all our callers error out it makes no sense to continue
557ba4
parsing mbs.
557ba4
557ba4
As we allocate `len` wchars at the beginning and each wchar has
557ba4
at least one byte, there will never be need to grow the buffer,
557ba4
so the code can be left out. On the other hand, we are always
557ba4
allocatng more memory than we need.
557ba4
557ba4
As long as wcs_length == mbs_length == len we can omit wcs_length.
557ba4
We keep the old code commented if we decide to save memory and
557ba4
use autoexpanding wcs_length in the future.
557ba4
---
557ba4
 libarchive/archive_string.c | 28 +++++++++++++++++-----------
557ba4
 1 file changed, 17 insertions(+), 11 deletions(-)
557ba4
557ba4
diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c
557ba4
index 5ae09b6..d7541dc 100644
557ba4
--- a/libarchive/archive_string.c
557ba4
+++ b/libarchive/archive_string.c
557ba4
@@ -590,7 +590,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
557ba4
 	 * No single byte will be more than one wide character,
557ba4
 	 * so this length estimate will always be big enough.
557ba4
 	 */
557ba4
-	size_t wcs_length = len;
557ba4
+	//size_t wcs_length = len;
557ba4
 	size_t mbs_length = len;
557ba4
 	const char *mbs = p;
557ba4
 	wchar_t *wcs;
557ba4
@@ -599,7 +599,11 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
557ba4
 
557ba4
 	memset(&shift_state, 0, sizeof(shift_state));
557ba4
 #endif
557ba4
-	if (NULL == archive_wstring_ensure(dest, dest->length + wcs_length + 1))
557ba4
+	/*
557ba4
+	 * As we decided to have wcs_length == mbs_length == len
557ba4
+	 * we can use len here instead of wcs_length
557ba4
+	 */
557ba4
+	if (NULL == archive_wstring_ensure(dest, dest->length + len + 1))
557ba4
 		return (-1);
557ba4
 	wcs = dest->s + dest->length;
557ba4
 	/*
557ba4
@@ -608,6 +612,12 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
557ba4
 	 * multi bytes.
557ba4
 	 */
557ba4
 	while (*mbs && mbs_length > 0) {
557ba4
+		/*
557ba4
+		 * The buffer we allocated is always big enough.
557ba4
+		 * Keep this code path in a comment if we decide to choose
557ba4
+		 * smaller wcs_length in the future
557ba4
+		 */
557ba4
+/*
557ba4
 		if (wcs_length == 0) {
557ba4
 			dest->length = wcs - dest->s;
557ba4
 			dest->s[dest->length] = L'\0';
557ba4
@@ -617,24 +627,20 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
557ba4
 				return (-1);
557ba4
 			wcs = dest->s + dest->length;
557ba4
 		}
557ba4
+*/
557ba4
 #if HAVE_MBRTOWC
557ba4
-		r = mbrtowc(wcs, mbs, wcs_length, &shift_state);
557ba4
+		r = mbrtowc(wcs, mbs, mbs_length, &shift_state);
557ba4
 #else
557ba4
-		r = mbtowc(wcs, mbs, wcs_length);
557ba4
+		r = mbtowc(wcs, mbs, mbs_length);
557ba4
 #endif
557ba4
 		if (r == (size_t)-1 || r == (size_t)-2) {
557ba4
 			ret_val = -1;
557ba4
-			if (errno == EILSEQ) {
557ba4
-				++mbs;
557ba4
-				--mbs_length;
557ba4
-				continue;
557ba4
-			} else
557ba4
-				break;
557ba4
+			break;
557ba4
 		}
557ba4
 		if (r == 0 || r > mbs_length)
557ba4
 			break;
557ba4
 		wcs++;
557ba4
-		wcs_length--;
557ba4
+		//wcs_length--;
557ba4
 		mbs += r;
557ba4
 		mbs_length -= r;
557ba4
 	}
557ba4
-- 
557ba4
2.24.1
557ba4