mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-05 12:56:08 +00:00
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
This commit is contained in:
commit
c4247af46a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=309405
@ -312,6 +312,7 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
|
|||||||
avail -= len;
|
avail -= len;
|
||||||
|
|
||||||
if (l == 6) {
|
if (l == 6) {
|
||||||
|
/* "begin " */
|
||||||
if (!uuchar[*b])
|
if (!uuchar[*b])
|
||||||
return (0);
|
return (0);
|
||||||
/* Get a length of decoded bytes. */
|
/* Get a length of decoded bytes. */
|
||||||
@ -352,8 +353,8 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
|
|||||||
b += nl;
|
b += nl;
|
||||||
if (avail && uuchar[*b])
|
if (avail && uuchar[*b])
|
||||||
return (firstline+30);
|
return (firstline+30);
|
||||||
}
|
} else if (l == 13) {
|
||||||
if (l == 13) {
|
/* "begin-base64 " */
|
||||||
while (len-nl > 0) {
|
while (len-nl > 0) {
|
||||||
if (!base64[*b++])
|
if (!base64[*b++])
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -645,12 +645,13 @@ cab_read_header(struct archive_read *a)
|
|||||||
cab = (struct cab *)(a->format->data);
|
cab = (struct cab *)(a->format->data);
|
||||||
if (cab->found_header == 0 &&
|
if (cab->found_header == 0 &&
|
||||||
p[0] == 'M' && p[1] == 'Z') {
|
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);
|
err = cab_skip_sfx(a);
|
||||||
if (err < ARCHIVE_WARN)
|
if (err < ARCHIVE_WARN)
|
||||||
return (err);
|
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));
|
return (truncated_error(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,57 +297,49 @@ archive_read_format_tar_cleanup(struct archive_read *a)
|
|||||||
/*
|
/*
|
||||||
* Validate number field
|
* Validate number field
|
||||||
*
|
*
|
||||||
* Flags:
|
* This has to be pretty lenient in order to accomodate the enormous
|
||||||
* 1 - allow double \0 at field end
|
* 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
|
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];
|
unsigned char marker = (unsigned char)p_field[0];
|
||||||
/* octal? */
|
if (marker == 128 || marker == 255 || marker == 0) {
|
||||||
if ((marker >= '0' && marker <= '7') || marker == ' ') {
|
/* Base-256 marker, there's nothing we can check. */
|
||||||
size_t i = 0;
|
return 1;
|
||||||
int octal_found = 0;
|
} else {
|
||||||
for (i = 0; i < i_size; ++i) {
|
/* Must be octal */
|
||||||
switch (p_field[i])
|
size_t i = 0;
|
||||||
{
|
/* Skip any leading spaces */
|
||||||
case ' ':
|
while (i < i_size && p_field[i] == ' ') {
|
||||||
/* skip any leading spaces and trailing space */
|
++i;
|
||||||
if (octal_found == 0 || i == i_size - 1) {
|
}
|
||||||
continue;
|
/* Must be at least one octal digit. */
|
||||||
}
|
if (i >= i_size || p_field[i] < '0' || p_field[i] > '7') {
|
||||||
break;
|
return 0;
|
||||||
case '\0':
|
}
|
||||||
/*
|
/* Skip remaining octal digits. */
|
||||||
* null should be allowed only at the end
|
while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') {
|
||||||
*
|
++i;
|
||||||
* Perl Archive::Tar terminates some fields
|
}
|
||||||
* with two nulls. We must allow this to stay
|
/* Any remaining characters must be space or NUL padding. */
|
||||||
* compatible.
|
while (i < i_size) {
|
||||||
*/
|
if (p_field[i] != ' ' && p_field[i] != 0) {
|
||||||
if (i != i_size - 1) {
|
return 0;
|
||||||
if (((flags & 1) == 0)
|
}
|
||||||
|| i != i_size - 2)
|
++i;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return octal_found > 0;
|
|
||||||
}
|
|
||||||
/* base 256 (i.e. binary number) */
|
|
||||||
else if (marker == 128 || marker == 255 || marker == 0) {
|
|
||||||
/* nothing to check */
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
/* not a number field */
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,26 +396,15 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
|
* 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 && (
|
if (bid > 0 && (
|
||||||
validate_number_field(header->mode, sizeof(header->mode), 1) == 0
|
validate_number_field(header->mode, sizeof(header->mode)) == 0
|
||||||
|| validate_number_field(header->uid, sizeof(header->uid), 1) == 0
|
|| validate_number_field(header->uid, sizeof(header->uid)) == 0
|
||||||
|| validate_number_field(header->gid, sizeof(header->gid), 1) == 0
|
|| validate_number_field(header->gid, sizeof(header->gid)) == 0
|
||||||
|| validate_number_field(header->mtime, sizeof(header->mtime),
|
|| validate_number_field(header->mtime, sizeof(header->mtime)) == 0
|
||||||
0) == 0
|
|| validate_number_field(header->size, sizeof(header->size)) == 0
|
||||||
|| validate_number_field(header->size, sizeof(header->size), 0) == 0
|
|| validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
|
||||||
|| validate_number_field(header->rdevmajor,
|
|| validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
|
||||||
sizeof(header->rdevmajor), 1) == 0
|
|
||||||
|| validate_number_field(header->rdevminor,
|
|
||||||
sizeof(header->rdevminor), 1) == 0)) {
|
|
||||||
bid = 0;
|
bid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user