Blob Blame History Raw
From 6c2128928b93902d4af154a954ffa383591feba4 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <kientzle@acm.org>
Date: Sat, 7 Feb 2015 12:59:39 -0800
Subject: [PATCH] Issue 404: Read past end of string parsing fflags

--

Correct the spelling of 'wcscmp'.

--

A correct fix for Issue 404: Read past end of string parsing fflags

The previous fix actually broke the fflag parsing.  We
cannot use strcmp() here because we're comparing a null-terminated
string to a part of another string.

This fix explicitly tracks the various string lengths and
checks that they match before calling memcmp() or wmemcmp().
That avoids any buffer overrun without breaking the parser.

--
Generated from commits: 1cbc76faff 05a875fdb8 90632371f
---
 libarchive/archive_entry.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c
index 7958a17..787d281 100644
--- a/libarchive/archive_entry.c
+++ b/libarchive/archive_entry.c
@@ -1744,14 +1744,17 @@ ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
 		while (*end != '\0'  &&  *end != '\t'  &&
 		    *end != ' '  &&  *end != ',')
 			end++;
+		size_t length = end - start;
 		for (flag = flags; flag->name != NULL; flag++) {
-			if (memcmp(start, flag->name, end - start) == 0) {
+			size_t flag_length = strlen(flag->name);
+			if (length == flag_length
+			    && memcmp(start, flag->name, length) == 0) {
 				/* Matched "noXXXX", so reverse the sense. */
 				clear |= flag->set;
 				set |= flag->clear;
 				break;
-			} else if (memcmp(start, flag->name + 2, end - start)
-			    == 0) {
+			} else if (length == flag_length - 2
+			    && memcmp(start, flag->name + 2, length) == 0) {
 				/* Matched "XXXX", so don't reverse. */
 				set |= flag->set;
 				clear |= flag->clear;
@@ -1808,14 +1811,17 @@ ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
 		while (*end != L'\0'  &&  *end != L'\t'  &&
 		    *end != L' '  &&  *end != L',')
 			end++;
+		size_t length = end - start;
 		for (flag = flags; flag->wname != NULL; flag++) {
-			if (wmemcmp(start, flag->wname, end - start) == 0) {
+			size_t flag_length = wcslen(flag->wname);
+			if (length == flag_length
+			    && wmemcmp(start, flag->wname, length) == 0) {
 				/* Matched "noXXXX", so reverse the sense. */
 				clear |= flag->set;
 				set |= flag->clear;
 				break;
-			} else if (wmemcmp(start, flag->wname + 2, end - start)
-			    == 0) {
+			} else if (length == flag_length - 2
+			    && wmemcmp(start, flag->wname + 2, length) == 0) {
 				/* Matched "XXXX", so don't reverse. */
 				set |= flag->set;
 				clear |= flag->clear;
-- 
2.7.4