From d3bb69751364bfe5fe7ad915646d5b327df9cb8b Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sun, 15 Jul 2007 19:13:59 +0000 Subject: [PATCH] archive_string_ensure() used to call exit(3) if it couldn't allocate more memory for a string. Change this so it returns NULL in that case, and update all of its callers to handle the error. Some of those callers can now return errors back to the client instead of calling exit(3). Approved by: re (bmah) --- lib/libarchive/archive_read_support_format_tar.c | 14 ++++++++++++-- lib/libarchive/archive_read_support_format_zip.c | 3 ++- lib/libarchive/archive_string.c | 11 ++++++----- lib/libarchive/archive_string_sprintf.c | 4 +++- lib/libarchive/archive_write_disk.c | 5 ++++- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/libarchive/archive_read_support_format_tar.c b/lib/libarchive/archive_read_support_format_tar.c index c5d33f88959..4559412400c 100644 --- a/lib/libarchive/archive_read_support_format_tar.c +++ b/lib/libarchive/archive_read_support_format_tar.c @@ -895,8 +895,14 @@ read_body_to_string(struct archive_read *a, struct tar *tar, return (ARCHIVE_FATAL); } + /* Fail if we can't make our buffer big enough. */ + if (archive_string_ensure(as, size+1) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory"); + return (ARCHIVE_FATAL); + } + /* Read the body into the string. */ - archive_string_ensure(as, size+1); padded_size = (size + 511) & ~ 511; dest = as->s; while (padded_size > 0) { @@ -2020,7 +2026,11 @@ readline(struct archive_read *a, struct tar *tar, const char **start) } /* Otherwise, we need to accumulate in a line buffer. */ for (;;) { - archive_string_ensure(&tar->line, total_size + bytes_read); + if (archive_string_ensure(&tar->line, total_size + bytes_read) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate working buffer"); + return (ARCHIVE_FATAL); + } memcpy(tar->line.s + total_size, t, bytes_read); (a->decompressor->consume)(a, bytes_read); total_size += bytes_read; diff --git a/lib/libarchive/archive_read_support_format_zip.c b/lib/libarchive/archive_read_support_format_zip.c index a3e85732bef..80507bb4a47 100644 --- a/lib/libarchive/archive_read_support_format_zip.c +++ b/lib/libarchive/archive_read_support_format_zip.c @@ -302,7 +302,8 @@ zip_read_file_header(struct archive_read *a, struct archive_entry *entry, "Truncated ZIP file header"); return (ARCHIVE_FATAL); } - archive_string_ensure(&zip->pathname, zip->filename_length); + if (archive_string_ensure(&zip->pathname, zip->filename_length) == NULL) + __archive_errx(1, "Out of memory"); archive_strncpy(&zip->pathname, (const char *)h, zip->filename_length); (a->decompressor->consume)(a, zip->filename_length); archive_entry_set_pathname(entry, zip->pathname.s); diff --git a/lib/libarchive/archive_string.c b/lib/libarchive/archive_string.c index b79c6637ab1..8e1d11cb818 100644 --- a/lib/libarchive/archive_string.c +++ b/lib/libarchive/archive_string.c @@ -44,7 +44,8 @@ __FBSDID("$FreeBSD$"); struct archive_string * __archive_string_append(struct archive_string *as, const char *p, size_t s) { - __archive_string_ensure(as, as->length + s + 1); + if (__archive_string_ensure(as, as->length + s + 1) == NULL) + __archive_errx(1, "Out of memory"); memcpy(as->s + as->length, p, s); as->s[as->length + s] = 0; as->length += s; @@ -54,7 +55,8 @@ __archive_string_append(struct archive_string *as, const char *p, size_t s) void __archive_string_copy(struct archive_string *dest, struct archive_string *src) { - __archive_string_ensure(dest, src->length + 1); + if (__archive_string_ensure(dest, src->length + 1) == NULL) + __archive_errx(1, "Out of memory"); memcpy(dest->s, src->s, src->length); dest->length = src->length; dest->s[dest->length] = 0; @@ -69,6 +71,7 @@ __archive_string_free(struct archive_string *as) free(as->s); } +/* Returns NULL on any allocation failure. */ struct archive_string * __archive_string_ensure(struct archive_string *as, size_t s) { @@ -80,10 +83,8 @@ __archive_string_ensure(struct archive_string *as, size_t s) while (as->buffer_length < s) as->buffer_length *= 2; as->s = (char *)realloc(as->s, as->buffer_length); - /* TODO: Return null instead and fix up all of our callers to - * handle this correctly. */ if (as->s == NULL) - __archive_errx(1, "Out of memory"); + return (NULL); return (as); } diff --git a/lib/libarchive/archive_string_sprintf.c b/lib/libarchive/archive_string_sprintf.c index 66d6cb85e7f..4401e9a1277 100644 --- a/lib/libarchive/archive_string_sprintf.c +++ b/lib/libarchive/archive_string_sprintf.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include "archive_string.h" +#include "archive_private.h" /* * Like 'vsprintf', but ensures the target is big enough, resizing if @@ -56,7 +57,8 @@ __archive_string_vsprintf(struct archive_string *as, const char *fmt, uintmax_t u; /* Unsigned integer temp. */ const char *p, *p2; - __archive_string_ensure(as, 64); + if (__archive_string_ensure(as, 64) == NULL) + __archive_errx(1, "Out of memory"); if (fmt == NULL) { as->s[0] = 0; diff --git a/lib/libarchive/archive_write_disk.c b/lib/libarchive/archive_write_disk.c index 9bf7d33e9b0..158f757bc0c 100644 --- a/lib/libarchive/archive_write_disk.c +++ b/lib/libarchive/archive_write_disk.c @@ -610,7 +610,10 @@ archive_write_disk_new(void) a->lookup_uid = trivial_lookup_uid; a->lookup_gid = trivial_lookup_gid; a->user_uid = geteuid(); - archive_string_ensure(&a->path_safe, 64); + if (archive_string_ensure(&a->path_safe, 512) == NULL) { + free(a); + return (NULL); + } return (&a->archive); }