diff options
author | Tim Kientzle <kientzle@FreeBSD.org> | 2004-04-13 23:45:37 +0000 |
---|---|---|
committer | Tim Kientzle <kientzle@FreeBSD.org> | 2004-04-13 23:45:37 +0000 |
commit | d911e48507b9aa5e39f200fb1e02e31a7593ce9a (patch) | |
tree | 6b324c0c8fe5322b967c90baad9fbf3b820f985f | |
parent | 76633eae4d3d0a371e451b7265f190edfdb670e1 (diff) |
* Plug a buffer overrun in ACL parsing. (archive_entry.c)
* Re-use a single buffer for shar output formatting rather
than hammering the heap. (archive_write_set_format_shar.c)
* Fix a handful of minor memory leaks and clean up some of the
memory-management code.
Notes
Notes:
svn path=/head/; revision=128204
-rw-r--r-- | lib/libarchive/archive_entry.c | 7 | ||||
-rw-r--r-- | lib/libarchive/archive_entry.h | 1 | ||||
-rw-r--r-- | lib/libarchive/archive_read.c | 6 | ||||
-rw-r--r-- | lib/libarchive/archive_read_open_file.c | 5 | ||||
-rw-r--r-- | lib/libarchive/archive_read_open_filename.c | 5 | ||||
-rw-r--r-- | lib/libarchive/archive_read_support_format_cpio.c | 9 | ||||
-rw-r--r-- | lib/libarchive/archive_read_support_format_tar.c | 34 | ||||
-rw-r--r-- | lib/libarchive/archive_write.c | 4 | ||||
-rw-r--r-- | lib/libarchive/archive_write_set_format_cpio.c | 5 | ||||
-rw-r--r-- | lib/libarchive/archive_write_set_format_pax.c | 10 | ||||
-rw-r--r-- | lib/libarchive/archive_write_set_format_shar.c | 46 | ||||
-rw-r--r-- | lib/libarchive/archive_write_set_format_ustar.c | 18 |
12 files changed, 99 insertions, 51 deletions
diff --git a/lib/libarchive/archive_entry.c b/lib/libarchive/archive_entry.c index be261f58c2b4..7ea63fc7342d 100644 --- a/lib/libarchive/archive_entry.c +++ b/lib/libarchive/archive_entry.c @@ -481,6 +481,12 @@ archive_entry_set_hardlink(struct archive_entry *entry, const char *target) } void +archive_entry_copy_hardlink(struct archive_entry *entry, const char *target) +{ + aes_copy_mbs(&entry->ae_hardlink, target); +} + +void archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target) { aes_copy_wcs(&entry->ae_hardlink, target); @@ -1111,6 +1117,7 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, malloc(namebuff_length * sizeof(wchar_t)); } wmemcpy(namebuff, name_start, name_end - name_start); + namebuff[name_end - name_start] = L'\0'; archive_entry_acl_add_entry_w(entry, type, permset, tag, id, namebuff); } diff --git a/lib/libarchive/archive_entry.h b/lib/libarchive/archive_entry.h index 385850bfbfb8..733a60dd5470 100644 --- a/lib/libarchive/archive_entry.h +++ b/lib/libarchive/archive_entry.h @@ -97,6 +97,7 @@ void archive_entry_set_gid(struct archive_entry *, gid_t); void archive_entry_set_gname(struct archive_entry *, const char *); void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); void archive_entry_set_hardlink(struct archive_entry *, const char *); +void archive_entry_copy_hardlink(struct archive_entry *, const char *); void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); void archive_entry_set_link(struct archive_entry *, const char *); void archive_entry_set_mode(struct archive_entry *, mode_t); diff --git a/lib/libarchive/archive_read.c b/lib/libarchive/archive_read.c index ae2c8d888401..7af242a5c368 100644 --- a/lib/libarchive/archive_read.c +++ b/lib/libarchive/archive_read.c @@ -428,8 +428,8 @@ archive_read_finish(struct archive *a) /* Casting a pointer to int allows us to remove 'const.' */ free((void *)(uintptr_t)(const void *)a->nulls); - if (a->extract_mkdirpath.s != NULL) - free(a->extract_mkdirpath.s); + archive_string_free(&a->extract_mkdirpath); + archive_string_free(&a->error_string); if (a->entry) archive_entry_free(a->entry); a->magic = 0; @@ -455,7 +455,7 @@ __archive_read_register_format(struct archive *a, for (i = 0; i < number_slots; i++) { if (a->formats[i].bid == bid) - return (0); /* We've already installed */ + return (ARCHIVE_WARN); /* We've already installed */ if (a->formats[i].bid == NULL) { a->formats[i].bid = bid; a->formats[i].read_header = read_header; diff --git a/lib/libarchive/archive_read_open_file.c b/lib/libarchive/archive_read_open_file.c index f26a362cd72b..fa30bbbc1dc9 100644 --- a/lib/libarchive/archive_read_open_file.c +++ b/lib/libarchive/archive_read_open_file.c @@ -68,7 +68,7 @@ archive_read_open_file(struct archive *a, const char *filename, strcpy(mine->filename, filename); } mine->block_size = block_size; - mine->buffer = malloc(mine->block_size); + mine->buffer = NULL; mine->fd = -1; return (archive_read_open(a, mine, file_open, file_read, file_close)); } @@ -78,6 +78,7 @@ file_open(struct archive *a, void *client_data) { struct read_file_data *mine = client_data; + mine->buffer = malloc(mine->block_size); if (*mine->filename != 0) mine->fd = open(mine->filename, O_RDONLY); else @@ -108,6 +109,8 @@ file_close(struct archive *a, void *client_data) (void)a; /* UNUSED */ if (mine->fd >= 0) close(mine->fd); + if (mine->buffer != NULL) + free(mine->buffer); free(mine); return (ARCHIVE_OK); } diff --git a/lib/libarchive/archive_read_open_filename.c b/lib/libarchive/archive_read_open_filename.c index f26a362cd72b..fa30bbbc1dc9 100644 --- a/lib/libarchive/archive_read_open_filename.c +++ b/lib/libarchive/archive_read_open_filename.c @@ -68,7 +68,7 @@ archive_read_open_file(struct archive *a, const char *filename, strcpy(mine->filename, filename); } mine->block_size = block_size; - mine->buffer = malloc(mine->block_size); + mine->buffer = NULL; mine->fd = -1; return (archive_read_open(a, mine, file_open, file_read, file_close)); } @@ -78,6 +78,7 @@ file_open(struct archive *a, void *client_data) { struct read_file_data *mine = client_data; + mine->buffer = malloc(mine->block_size); if (*mine->filename != 0) mine->fd = open(mine->filename, O_RDONLY); else @@ -108,6 +109,8 @@ file_close(struct archive *a, void *client_data) (void)a; /* UNUSED */ if (mine->fd >= 0) close(mine->fd); + if (mine->buffer != NULL) + free(mine->buffer); free(mine); return (ARCHIVE_OK); } diff --git a/lib/libarchive/archive_read_support_format_cpio.c b/lib/libarchive/archive_read_support_format_cpio.c index 5ddc4f1dd260..9abeeca077f4 100644 --- a/lib/libarchive/archive_read_support_format_cpio.c +++ b/lib/libarchive/archive_read_support_format_cpio.c @@ -83,16 +83,21 @@ int archive_read_support_format_cpio(struct archive *a) { struct cpio *cpio; + int r; cpio = malloc(sizeof(*cpio)); memset(cpio, 0, sizeof(*cpio)); cpio->magic = CPIO_MAGIC; - return (__archive_read_register_format(a, + r = __archive_read_register_format(a, cpio, archive_read_format_cpio_bid, archive_read_format_cpio_read_header, - archive_read_format_cpio_cleanup)); + archive_read_format_cpio_cleanup); + + if (r != ARCHIVE_OK) + free(cpio); + return (ARCHIVE_OK); } diff --git a/lib/libarchive/archive_read_support_format_tar.c b/lib/libarchive/archive_read_support_format_tar.c index 8f6d5210a857..b91162df7b63 100644 --- a/lib/libarchive/archive_read_support_format_tar.c +++ b/lib/libarchive/archive_read_support_format_tar.c @@ -131,15 +131,19 @@ int archive_read_support_format_tar(struct archive *a) { struct tar *tar; + int r; tar = malloc(sizeof(*tar)); memset(tar, 0, sizeof(*tar)); - return (__archive_read_register_format(a, - tar, + r = __archive_read_register_format(a, tar, archive_read_format_tar_bid, archive_read_format_tar_read_header, - archive_read_format_tar_cleanup)); + archive_read_format_tar_cleanup); + + if (r != ARCHIVE_OK) + free(tar); + return (ARCHIVE_OK); } static int @@ -148,19 +152,15 @@ archive_read_format_tar_cleanup(struct archive *a) struct tar *tar; tar = *(a->pformat_data); - if (tar->entry_name.s != NULL) - free(tar->entry_name.s); - if (tar->entry_linkname.s != NULL) - free(tar->entry_linkname.s); - if (tar->entry_uname.s != NULL) - free(tar->entry_uname.s); - if (tar->entry_gname.s != NULL) - free(tar->entry_gname.s); - if (tar->pax_header.s != NULL) - free(tar->pax_header.s); - if (tar->pax_global.s != NULL) - free(tar->pax_global.s); - + archive_string_free(&tar->acl_text); + archive_string_free(&tar->entry_name); + archive_string_free(&tar->entry_linkname); + archive_string_free(&tar->entry_uname); + archive_string_free(&tar->entry_gname); + archive_string_free(&tar->pax_global); + archive_string_free(&tar->pax_header); + if (tar->pax_entry != NULL) + free(tar->pax_entry); free(tar); *(a->pformat_data) = NULL; return (ARCHIVE_OK); @@ -822,7 +822,7 @@ pax_header(struct archive *a, struct tar *tar, struct archive_entry *entry, /* Ensure pax_entry buffer is big enough. */ if (tar->pax_entry_length <= line_length) { if (tar->pax_entry_length <= 0) - tar->pax_entry_length = 256; + tar->pax_entry_length = 1024; while (tar->pax_entry_length <= line_length + 1) tar->pax_entry_length *= 2; diff --git a/lib/libarchive/archive_write.c b/lib/libarchive/archive_write.c index 2230daed40cf..7b41e534c70d 100644 --- a/lib/libarchive/archive_write.c +++ b/lib/libarchive/archive_write.c @@ -165,8 +165,8 @@ archive_write_finish(struct archive *a) /* Release various dynamic buffers. */ free((void *)(uintptr_t)(const void *)a->nulls); - if (a->extract_mkdirpath.s != NULL) - free(a->extract_mkdirpath.s); + archive_string_free(&a->extract_mkdirpath); + archive_string_free(&a->error_string); a->magic = 0; free(a); } diff --git a/lib/libarchive/archive_write_set_format_cpio.c b/lib/libarchive/archive_write_set_format_cpio.c index 83e88abcf161..91f8283b362d 100644 --- a/lib/libarchive/archive_write_set_format_cpio.c +++ b/lib/libarchive/archive_write_set_format_cpio.c @@ -207,10 +207,12 @@ format_octal_recursive(int64_t v, char *p, int s) static int archive_write_cpio_finish(struct archive *a) { + struct cpio *cpio; struct stat st; int er; struct archive_entry *trailer; + cpio = a->format_data; trailer = archive_entry_new(); memset(&st, 0, sizeof(st)); st.st_nlink = 1; @@ -218,6 +220,9 @@ archive_write_cpio_finish(struct archive *a) archive_entry_set_pathname(trailer, "TRAILER!!!"); er = archive_write_cpio_header(a, trailer); archive_entry_free(trailer); + + free(cpio); + a->format_data = NULL; return (er); } diff --git a/lib/libarchive/archive_write_set_format_pax.c b/lib/libarchive/archive_write_set_format_pax.c index 503062c6bb8c..efa38e2deb47 100644 --- a/lib/libarchive/archive_write_set_format_pax.c +++ b/lib/libarchive/archive_write_set_format_pax.c @@ -611,7 +611,7 @@ archive_write_pax_header(struct archive *a, pax_attr_entry, 'x'); archive_entry_free(pax_attr_entry); - free(pax_entry_name.s); + archive_string_free(&pax_entry_name); /* Note that the 'x' header shouldn't ever fail to format */ if (ret != 0) { @@ -765,12 +765,16 @@ static int archive_write_pax_finish(struct archive *a) { struct pax *pax; + int r; + + r = ARCHIVE_OK; pax = a->format_data; if (pax->written && a->compression_write != NULL) - return (write_nulls(a, 512 * 2)); + r = write_nulls(a, 512 * 2); + archive_string_free(&pax->pax_header); free(pax); a->format_data = NULL; - return (ARCHIVE_OK); + return (r); } static int diff --git a/lib/libarchive/archive_write_set_format_shar.c b/lib/libarchive/archive_write_set_format_shar.c index 76fa398b0087..f063e21f93e7 100644 --- a/lib/libarchive/archive_write_set_format_shar.c +++ b/lib/libarchive/archive_write_set_format_shar.c @@ -38,16 +38,6 @@ __FBSDID("$FreeBSD$"); #include "archive_entry.h" #include "archive_private.h" -static int archive_write_shar_finish(struct archive *); -static int archive_write_shar_header(struct archive *, - struct archive_entry *); -static int archive_write_shar_data_sed(struct archive *, - const void * buff, size_t); -static int archive_write_shar_data_uuencode(struct archive *, - const void * buff, size_t); -static int archive_write_shar_finish_entry(struct archive *); -static int shar_printf(struct archive *, const char *fmt, ...); - struct shar { int dump; int end_of_line; @@ -60,19 +50,43 @@ struct shar { int uuavail; char uubuffer[3]; int wrote_header; + char *work; + size_t work_len; }; +static int archive_write_shar_finish(struct archive *); +static int archive_write_shar_header(struct archive *, + struct archive_entry *); +static int archive_write_shar_data_sed(struct archive *, + const void * buff, size_t); +static int archive_write_shar_data_uuencode(struct archive *, + const void * buff, size_t); +static int archive_write_shar_finish_entry(struct archive *); +static int shar_printf(struct archive *, const char *fmt, ...); +static void uuencode_group(struct shar *); + static int shar_printf(struct archive *a, const char *fmt, ...) { + struct shar *shar; va_list ap; - char *p; + int required; int ret; + shar = a->format_data; + if (shar->work_len <= 0) { + shar->work_len = 1024; + shar->work = malloc(shar->work_len); + } + va_start(ap, fmt); - vasprintf(&p, fmt, ap); - ret = ((a->compression_write)(a, p, strlen(p))); - free(p); + required = vsnprintf(shar->work, shar->work_len, fmt, ap); + if ((size_t)required >= shar->work_len) { + shar->work_len = required + 256; + realloc(shar->work, shar->work_len); + required = vsnprintf(shar->work, shar->work_len, fmt, ap); + } + ret = ((a->compression_write)(a, shar->work, strlen(shar->work))); va_end(ap); return (ret); } @@ -261,6 +275,7 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry) return (ARCHIVE_OK); } +/* XXX TODO: This could be more efficient XXX */ static int archive_write_shar_data_sed(struct archive *a, const void *buff, size_t length) { @@ -297,6 +312,7 @@ archive_write_shar_data_sed(struct archive *a, const void *buff, size_t length) #define UUENC(c) (((c)!=0) ? ((c) & 077) + ' ': '`') +/* XXX This could be a lot more efficient. XXX */ static void uuencode_group(struct shar *shar) { @@ -443,6 +459,8 @@ archive_write_shar_finish(struct archive *a) archive_entry_free(shar->entry); if (shar->last_dir != NULL) free(shar->last_dir); + if (shar->work != NULL) + free(shar->work); free(shar); a->format_data = NULL; return (ARCHIVE_OK); diff --git a/lib/libarchive/archive_write_set_format_ustar.c b/lib/libarchive/archive_write_set_format_ustar.c index 931f65886e7b..7d3c4a051bf2 100644 --- a/lib/libarchive/archive_write_set_format_ustar.c +++ b/lib/libarchive/archive_write_set_format_ustar.c @@ -373,19 +373,20 @@ static int archive_write_ustar_finish(struct archive *a) { struct ustar *ustar; + int r; + r = ARCHIVE_OK; ustar = a->format_data; /* * Suppress end-of-archive if nothing else was ever written. - * This fixes a problem where setting one format, then another ends up - * attempting to write a gratuitous end-of-archive marker. + * This fixes a problem where setting one format, then another + * ends up writing a gratuitous end-of-archive marker. */ if (ustar->written && a->compression_write != NULL) - if (write_nulls(a, 512*2) < 512*2) - return (ARCHIVE_FATAL); - free(a->format_data); + r = write_nulls(a, 512*2); + free(ustar); a->format_data = NULL; - return (ARCHIVE_OK); + return (r); } static int @@ -409,10 +410,11 @@ write_nulls(struct archive *a, size_t padding) while (padding > 0) { to_write = padding < a->null_length ? padding : a->null_length; ret = (a->compression_write)(a, a->nulls, to_write); - if (ret < to_write) return (-1); + if (ret < to_write) + return (ARCHIVE_FATAL); padding -= to_write; } - return (0); + return (ARCHIVE_OK); } static int |