]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Check for overflow the right way.
authorWayne Davison <wayne@opencoder.net>
Mon, 13 Jul 2020 04:51:51 +0000 (21:51 -0700)
committerWayne Davison <wayne@opencoder.net>
Mon, 13 Jul 2020 05:45:01 +0000 (22:45 -0700)
options.c
rsync.h
util.c
xattrs.c

index 9ed164058f797a690955098bb643e624dce10b12..0ecabe8d6dcdd4c54915139a188a4b2dd9200113 100644 (file)
--- 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 be4d85505fd74d819257924574ee756825b0aa49..9942a7054b8c1f1c7d9b7447da865fba3825d9c3 100644 (file)
--- 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 3a50e44f59a1a2d326bad9c66088472f5e823b7b..f5588324ee703564f064ff0c0ed83dc84302485e 100644 (file)
--- 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);
 }
index b10c256766859628f9341919ca28a94bf45536a7..bcb4bcacf31d73ff14d1f37b14c554cea435bdb4 100644 (file)
--- 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;