From e91e6383bf287cd522466cd06096865950048f15 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Tue, 17 Aug 2021 13:21:43 +0200 Subject: [PATCH] Drop assert in zmalloc and raise runtime error Most assert in code are useful because they signal a real bug. However, if allocation on the heap fails, it is a runtime error because system gets rid of memory. This is more important on embedded systems, and the caller process cannot exit but it should be informed with return code and it will decide how to work on. This drop the assert clause and add error code handling when zmalloc is called. Signed-off-by: Stefano Babic --- src/lib/comp/comp.c | 8 ++++++++ src/lib/comp/nocomp/nocomp.c | 4 ++++ src/lib/comp/zstd/zstd.c | 8 ++++++++ src/lib/dl/dl.c | 4 ++++ src/lib/dl/multipart.c | 21 +++++++++++++++++---- src/lib/dl/range.c | 12 ++++++++++++ src/lib/error.c | 4 ++++ src/lib/hash/hash.c | 28 ++++++++++++++++++++++++++++ src/lib/header.c | 29 +++++++++++++++++++++++++++++ src/lib/index/index_create.c | 22 ++++++++++++++++++++++ src/lib/index/index_read.c | 15 +++++++++++++++ src/lib/io.c | 4 ++++ src/lib/zck.c | 22 ++++++++++++++++++++-- 13 files changed, 175 insertions(+), 6 deletions(-) diff --git a/src/lib/comp/comp.c b/src/lib/comp/comp.c index dbbbefe..e80e613 100644 --- a/src/lib/comp/comp.c +++ b/src/lib/comp/comp.c @@ -394,6 +394,10 @@ bool comp_add_to_dc(zckCtx *zck, zckComp *comp, const char *src, /* Get rid of any already read data and allocate space for new data */ char *temp = zmalloc(comp->dc_data_size - comp->dc_data_loc + src_size); + if (!temp) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } if(comp->dc_data_loc != 0) zck_log(ZCK_LOG_DEBUG, "Freeing %lu bytes from decompressed buffer", comp->dc_data_loc); @@ -430,6 +434,10 @@ ssize_t comp_read(zckCtx *zck, char *dst, size_t dst_size, bool use_dict) { size_t dc = 0; char *src = zmalloc(dst_size - dc); + if (!src) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } bool finished_rd = false; bool finished_dc = false; zck_log(ZCK_LOG_DEBUG, "Trying to read %lu bytes", dst_size); diff --git a/src/lib/comp/nocomp/nocomp.c b/src/lib/comp/nocomp/nocomp.c index 0b9f85a..c6e80ba 100644 --- a/src/lib/comp/nocomp/nocomp.c +++ b/src/lib/comp/nocomp/nocomp.c @@ -49,6 +49,10 @@ static ssize_t compress(zckCtx *zck, zckComp *comp, const char *src, ALLOCD_INT(zck, comp); *dst = zmalloc(src_size); + if (!dst) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return 0; + } memcpy(*dst, src, src_size); *dst_size = src_size; diff --git a/src/lib/comp/zstd/zstd.c b/src/lib/comp/zstd/zstd.c index 921426f..acf6582 100644 --- a/src/lib/comp/zstd/zstd.c +++ b/src/lib/comp/zstd/zstd.c @@ -140,6 +140,10 @@ static bool end_cchunk(zckCtx *zck, zckComp *comp, char **dst, size_t *dst_size, } *dst = zmalloc(max_size); + if (!dst) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } #ifdef OLD_ZSTD /* Currently, compression isn't deterministic when using contexts in * zstd 1.3.5, so this works around it */ @@ -205,6 +209,10 @@ static bool end_dchunk(zckCtx *zck, zckComp *comp, const bool use_dict, comp->data_size = 0; char *dst = zmalloc(fd_size); + if (!dst) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } size_t retval = 0; zck_log(ZCK_LOG_DEBUG, "Decompressing %lu bytes to %lu bytes", src_size, fd_size); diff --git a/src/lib/dl/dl.c b/src/lib/dl/dl.c index c66de7a..1242669 100644 --- a/src/lib/dl/dl.c +++ b/src/lib/dl/dl.c @@ -271,6 +271,10 @@ ssize_t PUBLIC zck_dl_get_bytes_uploaded(zckDL *dl) { /* Initialize zckDL. When finished, zckDL *must* be freed by zck_dl_free() */ zckDL PUBLIC *zck_dl_init(zckCtx *zck) { zckDL *dl = zmalloc(sizeof(zckDL)); + if (!dl) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return NULL; + } dl->mp = zmalloc(sizeof(zckMP)); dl->zck = zck; return dl; diff --git a/src/lib/dl/multipart.c b/src/lib/dl/multipart.c index f8c11df..3e05e94 100644 --- a/src/lib/dl/multipart.c +++ b/src/lib/dl/multipart.c @@ -41,7 +41,7 @@ static char *add_boundary_to_regex(zckCtx *zck, const char *regex, if(regex == NULL || boundary == NULL) return NULL; char *regex_b = zmalloc(strlen(regex) + strlen(boundary) + 1); - if(snprintf(regex_b, strlen(regex) + strlen(boundary), regex, + if(!regex_b || snprintf(regex_b, strlen(regex) + strlen(boundary), regex, boundary) != strlen(regex) + strlen(boundary) - 2) { free(regex_b); set_error(zck, "Unable to build regular expression"); @@ -81,7 +81,7 @@ static bool gen_regex(zckDL *dl) { if(regex_n == NULL) return false; dl->dl_regex = zmalloc(sizeof(regex_t)); - if(!create_regex(dl->zck, dl->dl_regex, regex_n)) { + if(!dl->dl_regex || !create_regex(dl->zck, dl->dl_regex, regex_n)) { free(regex_n); return false; } @@ -90,7 +90,7 @@ static bool gen_regex(zckDL *dl) { if(regex_e == NULL) return false; dl->end_regex = zmalloc(sizeof(regex_t)); - if(!create_regex(dl->zck, dl->end_regex, regex_e)) { + if(!dl->end_regex || !create_regex(dl->zck, dl->end_regex, regex_e)) { free(regex_e); return false; } @@ -164,6 +164,10 @@ size_t multipart_extract(zckDL *dl, char *b, size_t l) { size_t size = buf + l - header_start; if(size > 0) { mp->buffer = zmalloc(size); + if (!mp->buffer) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return 0; + } memcpy(mp->buffer, header_start, size); mp->buffer_len = size; } @@ -226,13 +230,17 @@ size_t multipart_get_boundary(zckDL *dl, char *b, size_t size) { if(dl->hdr_regex == NULL) { char *regex = "boundary *= *(.*?) *\r"; dl->hdr_regex = zmalloc(sizeof(regex_t)); - if(!create_regex(dl->zck, dl->hdr_regex, regex)) + if(!dl->hdr_regex || !create_regex(dl->zck, dl->hdr_regex, regex)) return 0; } /* Copy buffer to null-terminated string because POSIX regex requires null- * terminated string */ char *buf = zmalloc(size+1); + if (!buf) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return 0; + } buf[size] = '\0'; memcpy(buf, b, size); @@ -249,6 +257,11 @@ size_t multipart_get_boundary(zckDL *dl, char *b, size_t size) { boundary_length -= 2; } char *boundary = zmalloc(boundary_length + 1); + if (!boundary) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + free(buf); + return 0; + } memcpy(boundary, boundary_start, boundary_length); zck_log(ZCK_LOG_DEBUG, "Multipart boundary: %s", boundary); dl->boundary = boundary; diff --git a/src/lib/dl/range.c b/src/lib/dl/range.c index a366f9b..3a565d7 100644 --- a/src/lib/dl/range.c +++ b/src/lib/dl/range.c @@ -42,6 +42,10 @@ static zckRangeItem *range_insert_new(zckCtx *zck, zckRangeItem *prev, VALIDATE_PTR(zck); zckRangeItem *new = zmalloc(sizeof(zckRangeItem)); + if (!new) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return NULL; + } new->start = start; new->end = end; if(prev) { @@ -151,6 +155,10 @@ void PUBLIC zck_range_free(zckRange **info) { char PUBLIC *zck_get_range_char(zckCtx *zck, zckRange *range) { int buf_size = BUF_SIZE; char *output = zmalloc(buf_size); + if (!output) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return NULL; + } int loc = 0; int count = 0; zckRangeItem *ri = range->first; @@ -181,6 +189,10 @@ zckRange PUBLIC *zck_get_missing_range(zckCtx *zck, int max_ranges) { VALIDATE_PTR(zck); zckRange *range = zmalloc(sizeof(zckRange)); + if (!range) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return NULL; + } for(zckChunk *chk = zck->index.first; chk; chk = chk->next) { if(chk->valid) continue; diff --git a/src/lib/error.c b/src/lib/error.c index b04d61f..bd3ce9e 100644 --- a/src/lib/error.c +++ b/src/lib/error.c @@ -65,6 +65,10 @@ void set_error_wf(zckCtx *zck, int fatal, const char *function, zck->msg = zmalloc(size + old_size + 3); else zck->msg = zmalloc(size + 2); + if (!zck->msg) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return; + } va_start(args, format); vsnprintf(zck->msg, size + 1, format, args); va_end(args); diff --git a/src/lib/hash/hash.c b/src/lib/hash/hash.c index 25768ae..b4e6c2c 100644 --- a/src/lib/hash/hash.c +++ b/src/lib/hash/hash.c @@ -146,6 +146,10 @@ static int validate_checksums(zckCtx *zck, zck_log_type bad_checksums) { char *get_digest_string(const char *digest, int size) { char *str = zmalloc(size*2+1); + if (!str) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return NULL; + } for(int i=0; itype == ZCK_HASH_SHA1) { zck_log(ZCK_LOG_DDEBUG, "Initializing SHA-1 hash"); hash->ctx = zmalloc(sizeof(SHA_CTX)); + if (!hash->ctx) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } hash->type = hash_type; SHA1_Init((SHA_CTX *) hash->ctx); return true; } else if(hash_type->type == ZCK_HASH_SHA256) { zck_log(ZCK_LOG_DDEBUG, "Initializing SHA-256 hash"); hash->ctx = zmalloc(sizeof(SHA256_CTX)); + if (!hash->ctx) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } hash->type = hash_type; SHA256_Init((SHA256_CTX *) hash->ctx); return true; @@ -225,6 +237,10 @@ bool hash_init(zckCtx *zck, zckHash *hash, zckHashType *hash_type) { hash_type->type <= ZCK_HASH_SHA512_128) { zck_log(ZCK_LOG_DDEBUG, "Initializing SHA-512 hash"); hash->ctx = zmalloc(sizeof(SHA512_CTX)); + if (!hash->ctx) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } hash->type = hash_type; SHA512_Init((SHA512_CTX *) hash->ctx); return true; @@ -279,17 +295,29 @@ char *hash_finalize(zckCtx *zck, zckHash *hash) { } if(hash->type->type == ZCK_HASH_SHA1) { unsigned char *digest = zmalloc(SHA1_DIGEST_LENGTH); + if (!digest) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } SHA1_Final((sha1_byte*)digest, (SHA_CTX *)hash->ctx); hash_close(hash); return (char *)digest; } else if(hash->type->type == ZCK_HASH_SHA256) { unsigned char *digest = zmalloc(SHA256_DIGEST_SIZE); + if (!digest) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } SHA256_Final(digest, (SHA256_CTX *)hash->ctx); hash_close(hash); return (char *)digest; } else if(hash->type->type >= ZCK_HASH_SHA512 && hash->type->type <= ZCK_HASH_SHA512_128) { unsigned char *digest = zmalloc(SHA512_DIGEST_SIZE); + if (!digest) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } SHA512_Final(digest, (SHA512_CTX *)hash->ctx); hash_close(hash); return (char *)digest; diff --git a/src/lib/header.c b/src/lib/header.c index 0d276f8..46f21d3 100644 --- a/src/lib/header.c +++ b/src/lib/header.c @@ -120,6 +120,10 @@ static bool read_preface(zckCtx *zck) { return false; } zck->full_hash_digest = zmalloc(zck->hash_type.digest_size); + if (!zck->full_hash_digest) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } memcpy(zck->full_hash_digest, header+length, zck->hash_type.digest_size); length += zck->hash_type.digest_size; @@ -238,6 +242,10 @@ static bool preface_create(zckCtx *zck) { int header_malloc = zck->hash_type.digest_size + 4 + 2*MAX_COMP_SIZE; char *header = zmalloc(header_malloc); + if (!header) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } size_t length = 0; /* Write out the full data digest */ @@ -272,6 +280,10 @@ static bool sig_create(zckCtx *zck) { char *header = zmalloc(MAX_COMP_SIZE); size_t length = 0; + if (!header) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } zck_log(ZCK_LOG_DEBUG, "Calculating %i signatures", zck->sigs.count); /* Write out signature count and signatures */ @@ -295,6 +307,10 @@ static bool lead_create(zckCtx *zck) { memcpy(header, "\0ZCK1", 5); length += 5; + if (!header) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } /* Write out full data and header hash type */ compint_from_size(header + length, zck->hash_type.type, &length); /* Write out header length */ @@ -345,6 +361,10 @@ bool header_create(zckCtx *zck) { zck_log(ZCK_LOG_DEBUG, "Merging into header: %lu bytes", zck->data_offset); zck->header = zmalloc(zck->data_offset); + if (!zck->header) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } size_t offs = 0; memcpy(zck->header + offs, zck->lead_string, zck->lead_size); free(zck->lead_string); @@ -404,6 +424,10 @@ static bool read_lead(zckCtx *zck) { int lead = 5 + 2*MAX_COMP_SIZE; char *header = zmalloc(lead); + if (!header) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } size_t length = 0; if(read_data(zck, header, lead) < lead) { @@ -481,6 +505,11 @@ static bool read_lead(zckCtx *zck) { return false; } zck->header_digest = zmalloc(zck->hash_type.digest_size); + if (!zck->header_digest) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + free(header); + return false; + } memcpy(zck->header_digest, header + length, zck->hash_type.digest_size); length += zck->hash_type.digest_size; diff --git a/src/lib/index/index_create.c b/src/lib/index/index_create.c index a035c84..c4c08c7 100644 --- a/src/lib/index/index_create.c +++ b/src/lib/index/index_create.c @@ -37,6 +37,10 @@ static bool create_chunk(zckCtx *zck) { clear_work_index(zck); zck->work_index_item = zmalloc(sizeof(zckChunk)); + if (!zck->work_index_item) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } if(!hash_init(zck, &(zck->work_index_hash), &(zck->chunk_hash_type)) || (!hash_init(zck, &(zck->work_index_hash_uncomp), &(zck->chunk_hash_type)))) return false; @@ -51,6 +55,11 @@ static bool finish_chunk(zckIndex *index, zckChunk *item, char *digest, item->digest = zmalloc(index->digest_size); item->digest_uncompressed = zmalloc(index->digest_size); + if (!item->digest || !item->digest_uncompressed) { + free(item->digest); + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } if(digest) { memcpy(item->digest, digest, index->digest_size); item->digest_size = index->digest_size; @@ -111,6 +120,10 @@ bool index_create(zckCtx *zck) { /* Write index */ index = zmalloc(index_malloc); + if (!index) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } compint_from_size(index+index_size, zck->index.hash_type, &index_size); compint_from_size(index+index_size, zck->index.count, &index_size); if(zck->index.first) { @@ -155,6 +168,10 @@ bool index_new_chunk(zckCtx *zck, zckIndex *index, char *digest, return false; } zckChunk *chk = zmalloc(sizeof(zckChunk)); + if (!chk) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } index->digest_size = digest_size; chk->comp_length = comp_size; chk->length = orig_size; @@ -209,6 +226,11 @@ bool index_finish_chunk(zckCtx *zck) { } else { digest = zmalloc(zck->chunk_hash_type.digest_size); digest_uncompressed = zmalloc(zck->chunk_hash_type.digest_size); + if (!digest || !digest_uncompressed) { + free(digest); + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } } if(!finish_chunk(&(zck->index), zck->work_index_item, digest, digest_uncompressed, true, zck)) { free(digest); diff --git a/src/lib/index/index_read.c b/src/lib/index/index_read.c index 42b4efe..ea0ecbe 100644 --- a/src/lib/index/index_read.c +++ b/src/lib/index/index_read.c @@ -74,9 +74,18 @@ bool index_read(zckCtx *zck, char *data, size_t size, size_t max_length) { zckChunk *tmp = NULL; zckChunk *new = zmalloc(sizeof(zckChunk)); + if (!new) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } /* Read index entry digest */ new->digest = zmalloc(zck->index.digest_size); + if (!new->digest) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + free(new); + return false; + } memcpy(new->digest, data+length, zck->index.digest_size); new->digest_size = zck->index.digest_size; HASH_FIND(hh, zck->index.ht, new->digest, new->digest_size, tmp); @@ -89,6 +98,12 @@ bool index_read(zckCtx *zck, char *data, size_t size, size_t max_length) { if (zck->has_uncompressed_source) { /* same size for digest as compressed */ new->digest_uncompressed = zmalloc(zck->index.digest_size); + if (!new->digest_uncompressed) { + free(new->digest); + free(new); + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } memcpy(new->digest_uncompressed, data+length, zck->index.digest_size); new->digest_size_uncompressed = zck->index.digest_size; length += zck->index.digest_size; diff --git a/src/lib/io.c b/src/lib/io.c index b91b7ca..6e5ebc7 100644 --- a/src/lib/io.c +++ b/src/lib/io.c @@ -113,6 +113,10 @@ int chunks_from_temp(zckCtx *zck) { return false; char *data = zmalloc(BUF_SIZE); + if (!data) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return false; + } while((read_count = read(zck->temp_fd, data, BUF_SIZE)) > 0) { if(!write_data(zck, zck->fd, data, read_count)) { diff --git a/src/lib/zck.c b/src/lib/zck.c index d563350..9a81142 100644 --- a/src/lib/zck.c +++ b/src/lib/zck.c @@ -102,6 +102,10 @@ static char *ascii_checksum_to_bin (zckCtx *zck, char *checksum, char *raw_checksum = zmalloc(checksum_length/2); char *rp = raw_checksum; int buf = 0; + if (!raw_checksum) { + zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__); + return NULL; + } for (int i=0; iprep_hash_type = -1; zck->prep_hdr_size = -1; -- 2.30.2