Merge pull request #3265 from stoeckmann/ckd_alloc
Check size arithmetic before memory allocations
This commit is contained in:
11 files changed
+92
-61
No files matched your search
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_integer.h"
|
||||
|
||||
/*
|
||||
* This is mostly a pretty straightforward hash table implementation.
|
||||
@@ -387,7 +388,7 @@ insert_entry(struct archive_entry_linkresolver *res,
|
||||
}
|
||||
|
||||
/* If the links cache is getting too full, enlarge the hash table. */
|
||||
if (res->number_entries > res->number_buckets * 2)
|
||||
if (res->number_entries / 2 > res->number_buckets)
|
||||
grow_hash(res);
|
||||
|
||||
hash = (size_t)(archive_entry_dev(entry) ^ archive_entry_ino64(entry));
|
||||
@@ -413,8 +414,7 @@ grow_hash(struct archive_entry_linkresolver *res)
|
||||
size_t i, bucket;
|
||||
|
||||
/* Try to enlarge the bucket list. */
|
||||
new_size = res->number_buckets * 2;
|
||||
if (new_size < res->number_buckets)
|
||||
if (archive_ckd_mul_size(&new_size, res->number_buckets, 2))
|
||||
return;
|
||||
new_buckets = calloc(new_size, sizeof(struct links_entry *));
|
||||
|
||||
|
||||
@@ -1490,16 +1490,16 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
|
||||
|
||||
/* Ensure the buffer is big enough. */
|
||||
if (min > filter->buffer_size) {
|
||||
size_t s, t;
|
||||
size_t s;
|
||||
char *p;
|
||||
|
||||
/* Double the buffer; watch for overflow. */
|
||||
s = t = filter->buffer_size;
|
||||
s = filter->buffer_size;
|
||||
if (s == 0)
|
||||
s = min;
|
||||
while (s < min) {
|
||||
t *= 2;
|
||||
if (t <= s) { /* Integer overflow! */
|
||||
if (archive_ckd_mul_size(&s, s, 2)) {
|
||||
/* Integer overflow! */
|
||||
archive_set_error(
|
||||
&filter->archive->archive,
|
||||
ENOMEM,
|
||||
@@ -1510,7 +1510,6 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
|
||||
*avail = ARCHIVE_FATAL;
|
||||
return (NULL);
|
||||
}
|
||||
s = t;
|
||||
}
|
||||
/* Now s >= min, so allocate a new buffer. */
|
||||
p = malloc(s);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_integer.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
int
|
||||
@@ -209,7 +210,8 @@ lookup_uname_helper(struct name_cache *cache, id_t id)
|
||||
* we just double it and try again. Because the buffer
|
||||
* is kept around in the cache object, we shouldn't
|
||||
* have to do this very often. */
|
||||
nbuff_size = cache->buff_size * 2;
|
||||
if (archive_ckd_mul_size(&nbuff_size, cache->buff_size, 2))
|
||||
break;
|
||||
nbuff = realloc(cache->buff, nbuff_size);
|
||||
if (nbuff == NULL)
|
||||
break;
|
||||
@@ -276,7 +278,8 @@ lookup_gname_helper(struct name_cache *cache, id_t id)
|
||||
/* ERANGE means our buffer was too small, but POSIX
|
||||
* doesn't tell us how big the buffer should be, so
|
||||
* we just double it and try again. */
|
||||
nbuff_size = cache->buff_size * 2;
|
||||
if (archive_ckd_mul_size(&nbuff_size, cache->buff_size, 2))
|
||||
break;
|
||||
nbuff = realloc(cache->buff, nbuff_size);
|
||||
if (nbuff == NULL)
|
||||
break;
|
||||
|
||||
@@ -37,10 +37,11 @@
|
||||
#include <winioctl.h>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_disk_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_time_private.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
@@ -2540,7 +2541,12 @@ setup_sparse_from_disk(struct archive_read_disk *a,
|
||||
(DWORD)outranges_size, &retbytes, NULL);
|
||||
if (ret == 0 && GetLastError() == ERROR_MORE_DATA) {
|
||||
free(outranges);
|
||||
outranges_size *= 2;
|
||||
if (archive_ckd_mul_size(&outranges_size, outranges_size, 2)) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Couldn't allocate memory");
|
||||
exit_sts = ARCHIVE_FATAL;
|
||||
goto exit_setup_sparse;
|
||||
}
|
||||
outranges = (FILE_ALLOCATED_RANGE_BUFFER *)
|
||||
malloc(outranges_size);
|
||||
if (outranges == NULL) {
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "archive_endian.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_entry_locale.h"
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_string.h"
|
||||
@@ -314,8 +315,8 @@ struct file_info {
|
||||
|
||||
struct heap_queue {
|
||||
struct file_info **files;
|
||||
int allocated;
|
||||
int used;
|
||||
size_t allocated;
|
||||
size_t used;
|
||||
};
|
||||
|
||||
struct iso9660 {
|
||||
@@ -337,8 +338,8 @@ struct iso9660 {
|
||||
uint64_t offset;/* Offset of CE on disk. */
|
||||
struct file_info *file;
|
||||
} *reqs;
|
||||
int cnt;
|
||||
int allocated;
|
||||
size_t cnt;
|
||||
size_t allocated;
|
||||
} read_ce_req;
|
||||
|
||||
int64_t previous_number;
|
||||
@@ -2368,9 +2369,8 @@ register_CE(struct archive_read *a, int32_t location,
|
||||
{
|
||||
struct iso9660 *iso9660;
|
||||
struct read_ce_queue *heap;
|
||||
struct read_ce_req *p;
|
||||
uint64_t offset, parent_offset;
|
||||
int hole, parent;
|
||||
size_t hole, parent;
|
||||
|
||||
iso9660 = (struct iso9660 *)(a->format->data);
|
||||
offset = ((uint64_t)location) * (uint64_t)iso9660->logical_block_size;
|
||||
@@ -2389,14 +2389,13 @@ register_CE(struct archive_read *a, int32_t location,
|
||||
/* Expand our CE list as necessary. */
|
||||
heap = &(iso9660->read_ce_req);
|
||||
if (heap->cnt >= heap->allocated) {
|
||||
int new_size;
|
||||
struct read_ce_req *p;
|
||||
size_t new_size;
|
||||
|
||||
if (heap->allocated < 16)
|
||||
new_size = 16;
|
||||
else
|
||||
new_size = heap->allocated * 2;
|
||||
/* Overflow might keep us from growing the list. */
|
||||
if (new_size <= heap->allocated) {
|
||||
else if (archive_ckd_mul_size(&new_size, heap->allocated, 2)) {
|
||||
/* Overflow keeps us from growing the list. */
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@@ -2438,7 +2437,7 @@ static void
|
||||
next_CE(struct read_ce_queue *heap)
|
||||
{
|
||||
uint64_t a_offset, b_offset, c_offset;
|
||||
int a, b, c;
|
||||
size_t a, b, c;
|
||||
struct read_ce_req tmp;
|
||||
|
||||
if (heap->cnt < 1)
|
||||
@@ -3144,7 +3143,7 @@ heap_add_entry(struct archive_read *a, struct heap_queue *heap,
|
||||
struct file_info *file, uint64_t key)
|
||||
{
|
||||
uint64_t file_key, parent_key;
|
||||
int hole, parent;
|
||||
size_t hole, parent;
|
||||
|
||||
/* Reserve 16 bits for possible key collisions (needed for linked items) */
|
||||
/* For ISO files with more than 65535 entries, reordering will still occur */
|
||||
@@ -3154,12 +3153,12 @@ heap_add_entry(struct archive_read *a, struct heap_queue *heap,
|
||||
/* Expand our pending files list as necessary. */
|
||||
if (heap->used >= heap->allocated) {
|
||||
struct file_info **new_pending_files;
|
||||
int new_size = heap->allocated * 2;
|
||||
size_t new_size;
|
||||
|
||||
if (heap->allocated < 1024)
|
||||
new_size = 1024;
|
||||
/* Overflow might keep us from growing the list. */
|
||||
if (new_size <= heap->allocated) {
|
||||
else if (archive_ckd_mul_size(&new_size, heap->allocated, 2)) {
|
||||
/* Overflow keeps us from growing the list. */
|
||||
archive_set_error(&a->archive,
|
||||
ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -3186,7 +3185,7 @@ heap_add_entry(struct archive_read *a, struct heap_queue *heap,
|
||||
*/
|
||||
hole = heap->used++;
|
||||
while (hole > 0) {
|
||||
parent = (hole - 1)/2;
|
||||
parent = (hole - 1) / 2;
|
||||
parent_key = heap->files[parent]->key;
|
||||
if (file_key >= parent_key) {
|
||||
heap->files[hole] = file;
|
||||
@@ -3205,7 +3204,7 @@ static struct file_info *
|
||||
heap_get_entry(struct heap_queue *heap)
|
||||
{
|
||||
uint64_t a_key, b_key, c_key;
|
||||
int a, b, c;
|
||||
size_t a, b, c;
|
||||
struct file_info *r, *tmp;
|
||||
|
||||
if (heap->used < 1)
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "archive_endian.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_entry_locale.h"
|
||||
#include "archive_integer.h"
|
||||
#include "archive_ppmd7_private.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
@@ -201,8 +202,8 @@ struct huffman_table_entry
|
||||
struct huffman_code
|
||||
{
|
||||
struct huffman_tree_node *tree;
|
||||
int numentries;
|
||||
int numallocatedentries;
|
||||
size_t numentries;
|
||||
size_t numallocatedentries;
|
||||
int minlength;
|
||||
int maxlength;
|
||||
int tablesize;
|
||||
@@ -2823,11 +2824,16 @@ new_node(struct huffman_code *code)
|
||||
{
|
||||
void *new_tree;
|
||||
if (code->numallocatedentries == code->numentries) {
|
||||
int new_num_entries = 256;
|
||||
if (code->numentries > 0) {
|
||||
new_num_entries = code->numentries * 2;
|
||||
}
|
||||
new_tree = realloc(code->tree, new_num_entries * sizeof(*code->tree));
|
||||
size_t size, new_num_entries;
|
||||
|
||||
if (code->numentries == 0)
|
||||
new_num_entries = 256;
|
||||
else if (archive_ckd_mul_size(&new_num_entries, code->numentries, 2)
|
||||
|| new_num_entries > INT_MAX)
|
||||
return -1;
|
||||
if (archive_ckd_mul_size(&size, new_num_entries, sizeof(*code->tree)))
|
||||
return -1;
|
||||
new_tree = realloc(code->tree, size);
|
||||
if (new_tree == NULL)
|
||||
return (-1);
|
||||
code->tree = (struct huffman_tree_node *)new_tree;
|
||||
@@ -2868,7 +2874,7 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node,
|
||||
"Huffman tree was not created");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
if (node < 0 || node >= code->numentries)
|
||||
if (node < 0 || (size_t)node >= code->numentries)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid location to Huffman tree specified");
|
||||
|
||||
@@ -214,8 +214,8 @@ struct hdlink {
|
||||
|
||||
struct heap_queue {
|
||||
struct xar_file **files;
|
||||
int allocated;
|
||||
int used;
|
||||
size_t allocated;
|
||||
size_t used;
|
||||
};
|
||||
|
||||
enum xmlstatus {
|
||||
@@ -957,7 +957,7 @@ xar_cleanup(struct archive_read *a)
|
||||
{
|
||||
struct xar *xar;
|
||||
struct hdlink *hdlink;
|
||||
int i;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
xar = (struct xar *)(a->format->data);
|
||||
@@ -1207,19 +1207,17 @@ heap_add_entry(struct archive_read *a,
|
||||
struct heap_queue *heap, struct xar_file *file)
|
||||
{
|
||||
uint64_t file_id, parent_id;
|
||||
int hole, parent;
|
||||
size_t hole, parent;
|
||||
|
||||
/* Expand our pending files list as necessary. */
|
||||
if (heap->used >= heap->allocated) {
|
||||
struct xar_file **new_pending_files;
|
||||
int new_size;
|
||||
size_t new_size;
|
||||
|
||||
if (heap->allocated < 1024)
|
||||
new_size = 1024;
|
||||
else
|
||||
new_size = heap->allocated * 2;
|
||||
/* Overflow might keep us from growing the list. */
|
||||
if (new_size <= heap->allocated) {
|
||||
else if (archive_ckd_mul_size(&new_size, heap->allocated, 2)) {
|
||||
/* Overflow keeps us from growing the list. */
|
||||
archive_set_error(&a->archive,
|
||||
ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1247,7 +1245,7 @@ heap_add_entry(struct archive_read *a,
|
||||
*/
|
||||
hole = heap->used++;
|
||||
while (hole > 0) {
|
||||
parent = (hole - 1)/2;
|
||||
parent = (hole - 1) / 2;
|
||||
parent_id = heap->files[parent]->id;
|
||||
if (file_id >= parent_id) {
|
||||
heap->files[hole] = file;
|
||||
@@ -1266,7 +1264,7 @@ static struct xar_file *
|
||||
heap_get_entry(struct heap_queue *heap)
|
||||
{
|
||||
uint64_t a_id, b_id, c_id;
|
||||
int a, b, c;
|
||||
size_t a, b, c;
|
||||
struct xar_file *r, *tmp;
|
||||
|
||||
if (heap->used < 1)
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_write_disk_private.h"
|
||||
@@ -134,7 +135,8 @@ lookup_gid(void *private_data, const char *gname, int64_t gid)
|
||||
break;
|
||||
if (r != ERANGE)
|
||||
break;
|
||||
bufsize *= 2;
|
||||
if (archive_ckd_mul_size(&bufsize, bufsize, 2))
|
||||
break;
|
||||
free(allocated);
|
||||
allocated = malloc(bufsize);
|
||||
if (allocated == NULL)
|
||||
@@ -203,7 +205,8 @@ lookup_uid(void *private_data, const char *uname, int64_t uid)
|
||||
break;
|
||||
if (r != ERANGE)
|
||||
break;
|
||||
bufsize *= 2;
|
||||
if (archive_ckd_mul_size(&bufsize, bufsize, 2))
|
||||
break;
|
||||
free(allocated);
|
||||
allocated = malloc(bufsize);
|
||||
if (allocated == NULL)
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_entry_locale.h"
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_private.h"
|
||||
#include "archive_write_set_format_private.h"
|
||||
@@ -307,10 +308,16 @@ synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
|
||||
|
||||
/* Ensure space for the new mapping. */
|
||||
if (cpio->ino_list_size <= cpio->ino_list_next) {
|
||||
size_t newsize = cpio->ino_list_size < 512
|
||||
? 512 : cpio->ino_list_size * 2;
|
||||
void *newlist = realloc(cpio->ino_list,
|
||||
sizeof(cpio->ino_list[0]) * newsize);
|
||||
size_t newsize, size;
|
||||
if (cpio->ino_list_size < 512)
|
||||
newsize = 512;
|
||||
else if (archive_ckd_mul_size(&newsize,
|
||||
cpio->ino_list_size, 2))
|
||||
return (-1);
|
||||
if (archive_ckd_mul_size(&size,
|
||||
newsize, sizeof(cpio->ino_list[0])))
|
||||
return (-1);
|
||||
void *newlist = realloc(cpio->ino_list, size);
|
||||
if (newlist == NULL)
|
||||
return (-1);
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_entry_locale.h"
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_write_private.h"
|
||||
#include "archive_write_set_format_private.h"
|
||||
@@ -204,10 +205,16 @@ synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
|
||||
|
||||
/* Ensure space for the new mapping. */
|
||||
if (cpio->ino_list_size <= cpio->ino_list_next) {
|
||||
size_t newsize = cpio->ino_list_size < 512
|
||||
? 512 : cpio->ino_list_size * 2;
|
||||
void *newlist = realloc(cpio->ino_list,
|
||||
sizeof(cpio->ino_list[0]) * newsize);
|
||||
size_t newsize, size;
|
||||
if (cpio->ino_list_size < 512)
|
||||
newsize = 512;
|
||||
else if (archive_ckd_mul_size(&newsize,
|
||||
cpio->ino_list_size, 2))
|
||||
return (-1);
|
||||
if (archive_ckd_mul_size(&size,
|
||||
newsize, sizeof(cpio->ino_list[0])))
|
||||
return (-1);
|
||||
void *newlist = realloc(cpio->ino_list, size);
|
||||
if (newlist == NULL)
|
||||
return (-1);
|
||||
|
||||
|
||||
+5
-2
@@ -450,8 +450,11 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
|
||||
|
||||
/* Choose a suitable copy buffer size */
|
||||
bsdtar->buff_size = 64 * 1024;
|
||||
while (bsdtar->buff_size < (size_t)bsdtar->bytes_per_block)
|
||||
bsdtar->buff_size *= 2;
|
||||
while (bsdtar->buff_size < (size_t)bsdtar->bytes_per_block) {
|
||||
bsdtar->buff_size *= 2;
|
||||
if (bsdtar->buff_size < 64 * 1024)
|
||||
lafe_errc(1, 0, "cannot allocate memory");
|
||||
}
|
||||
/* Try to compensate for space we'll lose to alignment. */
|
||||
bsdtar->buff_size += 16 * 1024;
|
||||
|
||||
|
||||
Reference in new issue
Block a user