From: Tim Kientzle Date: Tue, 20 May 2008 19:57:10 +0000 (-0400) Subject: Guard against a number of theoretical buffer and integer X-Git-Tag: v2.6.0~215 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=28bffcb0cf9a34f46f12cdda79fc9b3973c0a0ec;p=thirdparty%2Flibarchive.git Guard against a number of theoretical buffer and integer overflows. As far as I can tell, none of these are actually exploitable. Thanks to David Remahl at Apple for pointing these out. MFP4 after: 1 day SVN-Revision: 77 --- diff --git a/libarchive/archive_read_support_format_ar.c b/libarchive/archive_read_support_format_ar.c index f6e4cc7e2..846b4ad94 100644 --- a/libarchive/archive_read_support_format_ar.c +++ b/libarchive/archive_read_support_format_ar.c @@ -350,12 +350,16 @@ archive_read_format_ar_read_header(struct archive_read *a, /* Parse the size of the name, adjust the file size. */ number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); - if ((off_t)number > ar->entry_bytes_remaining) { + bsd_name_length = (size_t)number; + /* Guard against the filename + trailing NUL + * overflowing a size_t and against the filename size + * being larger than the entire entry. */ + if (number > (uint64_t)(bsd_name_length + 1) + || (uint64_t)bsd_name_length > ar->entry_bytes_remaining) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Bad input file size"); return (ARCHIVE_FATAL); } - bsd_name_length = (size_t)number; ar->entry_bytes_remaining -= bsd_name_length; /* Adjust file size reported to client. */ archive_entry_set_size(entry, ar->entry_bytes_remaining); diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c index 08d64ed78..c10870495 100644 --- a/libarchive/archive_read_support_format_iso9660.c +++ b/libarchive/archive_read_support_format_iso9660.c @@ -595,6 +595,9 @@ add_entry(struct iso9660 *iso9660, struct file_info *file) struct file_info **new_pending_files; int new_size = iso9660->pending_files_allocated * 2; + /* Overflow might keep us from growing the list. */ + if (new_size <= iso9660->pending_files_allocated) + __archive_errx(1, "Out of memory"); if (new_size < 1024) new_size = 1024; new_pending_files = (struct file_info **)malloc(new_size * sizeof(new_pending_files[0])); diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 147ec0b27..6d7f048a4 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -2303,7 +2303,7 @@ base64_decode(const char *s, size_t len, size_t *out_len) /* Allocate enough space to hold the entire output. */ /* Note that we may not use all of this... */ - out = (char *)malloc((len * 3 + 3) / 4); + out = (char *)malloc(len - len / 4 + 1); if (out == NULL) { *out_len = 0; return (NULL); diff --git a/tar/util.c b/tar/util.c index 2ae430336..1d50dcd80 100644 --- a/tar/util.c +++ b/tar/util.c @@ -178,7 +178,7 @@ yes(const char *fmt, ...) fprintf(stderr, " (y/N)? "); fflush(stderr); - l = read(2, buff, sizeof(buff)); + l = read(2, buff, sizeof(buff) - 1); if (l <= 0) return (0); buff[l] = 0; @@ -215,7 +215,7 @@ process_lines(struct bsdtar *bsdtar, const char *pathname, { FILE *f; char *buff, *buff_end, *line_start, *line_end, *p; - size_t buff_length, bytes_read, bytes_wanted; + size_t buff_length, new_buff_length, bytes_read, bytes_wanted; int separator; int ret; @@ -262,7 +262,12 @@ process_lines(struct bsdtar *bsdtar, const char *pathname, line_start = buff; } else { /* Line is too big; enlarge the buffer. */ - p = realloc(buff, buff_length *= 2); + new_buff_length = buff_length * 2; + if (new_buff_length <= buff_length) + bsdtar_errc(bsdtar, 1, ENOMEM, + "Line too long in %s", pathname); + buff_length = new_buff_length; + p = realloc(buff, buff_length); if (p == NULL) bsdtar_errc(bsdtar, 1, ENOMEM, "Line too long in %s", pathname);