summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2004-04-13 23:45:37 +0000
committerkientzle <kientzle@FreeBSD.org>2004-04-13 23:45:37 +0000
commit5c2c79eafdaffd172c20dd2cebc96f3dea266b96 (patch)
tree6b324c0c8fe5322b967c90baad9fbf3b820f985f
parent2d52f8e62f64e1c72b250c97a58a6e324d6b62d4 (diff)
downloadFreeBSD-src-5c2c79eafdaffd172c20dd2cebc96f3dea266b96.zip
FreeBSD-src-5c2c79eafdaffd172c20dd2cebc96f3dea266b96.tar.gz
* 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.
-rw-r--r--lib/libarchive/archive_entry.c7
-rw-r--r--lib/libarchive/archive_entry.h1
-rw-r--r--lib/libarchive/archive_read.c6
-rw-r--r--lib/libarchive/archive_read_open_file.c5
-rw-r--r--lib/libarchive/archive_read_open_filename.c5
-rw-r--r--lib/libarchive/archive_read_support_format_cpio.c9
-rw-r--r--lib/libarchive/archive_read_support_format_tar.c34
-rw-r--r--lib/libarchive/archive_write.c4
-rw-r--r--lib/libarchive/archive_write_set_format_cpio.c5
-rw-r--r--lib/libarchive/archive_write_set_format_pax.c10
-rw-r--r--lib/libarchive/archive_write_set_format_shar.c46
-rw-r--r--lib/libarchive/archive_write_set_format_ustar.c18
12 files changed, 99 insertions, 51 deletions
diff --git a/lib/libarchive/archive_entry.c b/lib/libarchive/archive_entry.c
index be261f5..7ea63fc 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 385850b..733a60d 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 ae2c8d8..7af242a 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 f26a362..fa30bbb 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 f26a362..fa30bbb 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 5ddc4f1..9abeeca 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 8f6d521..b91162d 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 2230dae..7b41e53 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 83e88ab..91f8283 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 503062c..efa38e2 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 76fa398..f063e21 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 931f658..7d3c4a0 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
OpenPOWER on IntegriCloud