From: Wayne Davison Date: Mon, 13 Jul 2020 04:51:51 +0000 (-0700) Subject: Check for overflow the right way. X-Git-Tag: v3.2.3pre1~93 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=91fff802b9513cf0ed616d3aea170d561f899fae;p=thirdparty%2Frsync.git Check for overflow the right way. --- diff --git a/options.c b/options.c index 9ed16405..0ecabe8d 100644 --- a/options.c +++ b/options.c @@ -119,7 +119,6 @@ size_t bwlimit_writemax = 0; int ignore_existing = 0; int ignore_non_existing = 0; int need_messages_from_generator = 0; -time_t stop_at_utime = 0; int max_delete = INT_MIN; OFF_T max_size = -1; OFF_T min_size = -1; @@ -130,6 +129,7 @@ int checksum_seed = 0; int inplace = 0; int delay_updates = 0; int32 block_size = 0; +time_t stop_at_utime = 0; char *skip_compress = NULL; char *copy_as = NULL; item_list dparam_list = EMPTY_ITEM_LIST; @@ -2051,7 +2051,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) long val; arg = poptGetOptArg(pc); stop_at_utime = time(NULL); - if ((val = atol(arg) * 60) <= 0 || val + (long)stop_at_utime < 0) { + if ((val = atol(arg) * 60) <= 0 || LONG_MAX - val < stop_at_utime || (long)(time_t)val != val) { snprintf(err_buf, sizeof err_buf, "invalid --stop-after value: %s\n", arg); return 0; } diff --git a/rsync.h b/rsync.h index be4d8550..9942a705 100644 --- a/rsync.h +++ b/rsync.h @@ -711,6 +711,10 @@ struct ht_int64_node { #define NAME_MAX 255 #endif +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t)-1) +#endif + #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif diff --git a/util.c b/util.c index 3a50e44f..f5588324 100644 --- a/util.c +++ b/util.c @@ -1632,28 +1632,27 @@ void *expand_item_list(item_list *lp, size_t item_size, const char *desc, int in /* First time through, 0 <= 0, so list is expanded. */ if (lp->malloced <= lp->count) { void *new_ptr; - size_t new_size = lp->malloced; + size_t expand_size; if (incr < 0) - new_size += -incr; /* increase slowly */ - else if (new_size < (size_t)incr) - new_size = incr; - else if (new_size) - new_size *= 2; + expand_size = -incr; /* increase slowly */ + else if (lp->malloced < (size_t)incr) + expand_size = incr - lp->malloced; + else if (lp->malloced) + expand_size = lp->malloced; /* double in size */ else - new_size = 1; - if (new_size <= lp->malloced) + expand_size = 1; + if (SIZE_MAX/item_size - expand_size < lp->malloced) overflow_exit("expand_item_list"); - new_ptr = realloc_buf(lp->items, new_size * item_size); + expand_size += lp->malloced; + new_ptr = realloc_buf(lp->items, expand_size * item_size); if (DEBUG_GTE(FLIST, 3)) { rprintf(FINFO, "[%s] expand %s to %s bytes, did%s move\n", - who_am_i(), desc, big_num(new_size * item_size), + who_am_i(), desc, big_num(expand_size * item_size), new_ptr == lp->items ? " not" : ""); } - if (!new_ptr) - out_of_memory("expand_item_list"); lp->items = new_ptr; - lp->malloced = new_size; + lp->malloced = expand_size; } return (char*)lp->items + (lp->count++ * item_size); } diff --git a/xattrs.c b/xattrs.c index b10c2567..bcb4bcac 100644 --- a/xattrs.c +++ b/xattrs.c @@ -199,7 +199,7 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr if (!datum_len && !extra_len) extra_len = 1; /* request non-zero amount of memory */ - if (datum_len + extra_len < datum_len) + if (SIZE_MAX - datum_len < extra_len) overflow_exit("get_xattr_data"); ptr = new_array(char, datum_len + extra_len); @@ -748,7 +748,7 @@ int recv_xattr_request(struct file_struct *file, int f_in) old_datum = rxa->datum; rxa->datum_len = read_varint(f_in); - if (rxa->name_len + rxa->datum_len < rxa->name_len) + if (SIZE_MAX - rxa->name_len < rxa->datum_len) overflow_exit("recv_xattr_request"); rxa->datum = new_array(char, rxa->datum_len + rxa->name_len); name = rxa->datum + rxa->datum_len; @@ -799,8 +799,7 @@ void receive_xattr(int f, struct file_struct *file) size_t datum_len = read_varint(f); size_t dget_len = datum_len > MAX_FULL_DATUM ? 1 + MAX_DIGEST_LEN : datum_len; size_t extra_len = MIGHT_NEED_RPRE ? RPRE_LEN : 0; - if ((dget_len + extra_len < dget_len) - || (dget_len + extra_len + name_len < dget_len + extra_len)) + if (SIZE_MAX - dget_len < extra_len || SIZE_MAX - dget_len - extra_len < name_len) overflow_exit("receive_xattr"); ptr = new_array(char, dget_len + extra_len + name_len); name = ptr + dget_len + extra_len;