Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Dec 2016 09:30:13 +0000 (UTC)
From:      Martin Matuska <mm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r309405 - head/contrib/libarchive/libarchive
Message-ID:  <201612020930.uB29UDQR031063@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mm
Date: Fri Dec  2 09:30:13 2016
New Revision: 309405
URL: https://svnweb.freebsd.org/changeset/base/309405

Log:
  MFV r309403:
  
  Sync libarchive with vendor.
  
  Vendor bugfixes:
  Fix for heap-buffer-overflow in archive_le16dec()
  Fix for heap-buffer-overflow in uudecode_bidder_bid()
  Reworked fix for compatibility with archives created by Perl Archive::Tar
  
  MFC after:	1 week

Modified:
  head/contrib/libarchive/libarchive/archive_read_support_filter_uu.c
  head/contrib/libarchive/libarchive/archive_read_support_format_cab.c
  head/contrib/libarchive/libarchive/archive_read_support_format_tar.c
Directory Properties:
  head/contrib/libarchive/   (props changed)

Modified: head/contrib/libarchive/libarchive/archive_read_support_filter_uu.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_support_filter_uu.c	Fri Dec  2 09:29:22 2016	(r309404)
+++ head/contrib/libarchive/libarchive/archive_read_support_filter_uu.c	Fri Dec  2 09:30:13 2016	(r309405)
@@ -312,6 +312,7 @@ uudecode_bidder_bid(struct archive_read_
 	avail -= len;
 
 	if (l == 6) {
+		/* "begin " */
 		if (!uuchar[*b])
 			return (0);
 		/* Get a length of decoded bytes. */
@@ -352,8 +353,8 @@ uudecode_bidder_bid(struct archive_read_
 		b += nl;
 		if (avail && uuchar[*b])
 			return (firstline+30);
-	}
-	if (l == 13) {
+	} else if (l == 13) {
+		/* "begin-base64 " */
 		while (len-nl > 0) {
 			if (!base64[*b++])
 				return (0);

Modified: head/contrib/libarchive/libarchive/archive_read_support_format_cab.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_support_format_cab.c	Fri Dec  2 09:29:22 2016	(r309404)
+++ head/contrib/libarchive/libarchive/archive_read_support_format_cab.c	Fri Dec  2 09:30:13 2016	(r309405)
@@ -645,12 +645,13 @@ cab_read_header(struct archive_read *a)
 	cab = (struct cab *)(a->format->data);
 	if (cab->found_header == 0 &&
 	    p[0] == 'M' && p[1] == 'Z') {
-		/* This is an executable?  Must be self-extracting... 	*/
+		/* This is an executable?  Must be self-extracting... */
 		err = cab_skip_sfx(a);
 		if (err < ARCHIVE_WARN)
 			return (err);
 
-		if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL)
+		/* Re-read header after processing the SFX. */
+		if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
 			return (truncated_error(a));
 	}
 

Modified: head/contrib/libarchive/libarchive/archive_read_support_format_tar.c
==============================================================================
--- head/contrib/libarchive/libarchive/archive_read_support_format_tar.c	Fri Dec  2 09:29:22 2016	(r309404)
+++ head/contrib/libarchive/libarchive/archive_read_support_format_tar.c	Fri Dec  2 09:30:13 2016	(r309405)
@@ -297,58 +297,50 @@ archive_read_format_tar_cleanup(struct a
 /*
  * Validate number field
  *
- * Flags:
- * 1 - allow double \0 at field end
+ * This has to be pretty lenient in order to accomodate the enormous
+ * variety of tar writers in the world:
+ *  = POSIX ustar requires octal values with leading zeros and
+ *    specific termination on fields
+ *  = Many writers use different termination (in particular, libarchive
+ *    omits terminator bytes to squeeze one or two more digits)
+ *  = Many writers pad with space and omit leading zeros
+ *  = GNU tar and star write base-256 values if numbers are too
+ *    big to be represented in octal
+ *
+ * This should tolerate all variants in use.  It will reject a field
+ * where the writer just left garbage after a trailing NUL.
  */
 static int
-validate_number_field(const char* p_field, size_t i_size, int flags)
+validate_number_field(const char* p_field, size_t i_size)
 {
 	unsigned char marker = (unsigned char)p_field[0];
-	/* octal? */
-	if ((marker >= '0' && marker <= '7') || marker == ' ') {
+	if (marker == 128 || marker == 255 || marker == 0) {
+		/* Base-256 marker, there's nothing we can check. */
+		return 1;
+	} else {
+		/* Must be octal */
 		size_t i = 0;
-		int octal_found = 0;
-		for (i = 0; i < i_size; ++i) {
-			switch (p_field[i])
-			{
-			case ' ':
-				/* skip any leading spaces and trailing space */
-				if (octal_found == 0 || i == i_size - 1) {
-					continue;
-				}
-				break;
-			case '\0':
-				/*
-				 * null should be allowed only at the end
-				 *
-				 * Perl Archive::Tar terminates some fields
-				 * with two nulls. We must allow this to stay
-				 * compatible.
-				 */
-				if (i != i_size - 1) {
-					if (((flags & 1) == 0)
-					    || i != i_size - 2)
-						return 0;
-				}
-				break;
-			/* rest must be octal digits */
-			case '0': case '1': case '2': case '3':
-			case '4': case '5': case '6': case '7':
-				++octal_found;
-				break;
+		/* Skip any leading spaces */
+		while (i < i_size && p_field[i] == ' ') {
+			++i;
+		}
+		/* Must be at least one octal digit. */
+		if (i >= i_size || p_field[i] < '0' || p_field[i] > '7') {
+			return 0;
+		}
+		/* Skip remaining octal digits. */
+		while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') {
+			++i;
+		}
+		/* Any remaining characters must be space or NUL padding. */
+		while (i < i_size) {
+			if (p_field[i] != ' ' && p_field[i] != 0) {
+				return 0;
 			}
+			++i;
 		}
-		return octal_found > 0;
-	}
-	/* base 256 (i.e. binary number) */
-	else if (marker == 128 || marker == 255 || marker == 0) {
-		/* nothing to check */
 		return 1;
 	}
-	/* not a number field */
-	else {
-		return 0;
-	}
 }
 
 static int
@@ -404,26 +396,15 @@ archive_read_format_tar_bid(struct archi
 
 	/*
 	 * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
-	 * These are usually octal numbers but GNU tar encodes "big" values as
-	 * base256 and leading zeroes are sometimes replaced by spaces.
-	 * Even the null terminator is sometimes omitted. Anyway, must be
-	 * checked to avoid false positives.
-	 *
-	 * Perl Archive::Tar does not follow the spec and terminates mode, uid,
-	 * gid, rdevmajor and rdevminor with a double \0. For compatibility
-	 * reasons we allow this deviation.
 	 */
 	if (bid > 0 && (
-	    validate_number_field(header->mode, sizeof(header->mode), 1) == 0
-	    || validate_number_field(header->uid, sizeof(header->uid), 1) == 0
-	    || validate_number_field(header->gid, sizeof(header->gid), 1) == 0 
-	    || validate_number_field(header->mtime, sizeof(header->mtime),
-	    0) == 0
-	    || validate_number_field(header->size, sizeof(header->size), 0) == 0
-	    || validate_number_field(header->rdevmajor,
-	    sizeof(header->rdevmajor), 1) == 0
-	    || validate_number_field(header->rdevminor,
-	    sizeof(header->rdevminor), 1) == 0)) {
+	    validate_number_field(header->mode, sizeof(header->mode)) == 0
+	    || validate_number_field(header->uid, sizeof(header->uid)) == 0
+	    || validate_number_field(header->gid, sizeof(header->gid)) == 0
+	    || validate_number_field(header->mtime, sizeof(header->mtime)) == 0
+	    || validate_number_field(header->size, sizeof(header->size)) == 0
+	    || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
+	    || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
 		bid = 0;
 	}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612020930.uB29UDQR031063>