* 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.
This commit is contained in:
kientzle 2004-04-13 23:45:37 +00:00
parent 2d52f8e62f
commit 5c2c79eafd
12 changed files with 99 additions and 51 deletions

View File

@ -480,6 +480,12 @@ archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
aes_set_mbs(&entry->ae_hardlink, 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)
{
@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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