* 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:
parent
2d52f8e62f
commit
5c2c79eafd
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user