The branch, master has been updated via f47e5a77 Mention file & line on OOM and overflow errors. via 91fff802 Check for overflow the right way. from 3c8ac20d Fix a typo.
https://git.samba.org/?p=rsync.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit f47e5a7732f9b5da71080fdc229acde4ec6da3c1 Author: Wayne Davison <wa...@opencoder.net> Date: Sun Jul 12 22:46:21 2020 -0700 Mention file & line on OOM and overflow errors. Also simplify output of src file paths in errors & warnings when built in a alternate build dir. commit 91fff802b9513cf0ed616d3aea170d561f899fae Author: Wayne Davison <wa...@opencoder.net> Date: Sun Jul 12 21:51:51 2020 -0700 Check for overflow the right way. ----------------------------------------------------------------------- Summary of changes: cleanup.c | 2 +- flist.c | 12 ++++-------- lib/pool_alloc.3 | 2 +- lib/pool_alloc.c | 6 +++--- lib/pool_alloc.h | 2 +- log.c | 4 ++-- options.c | 4 ++-- rsync.h | 7 +++++++ util.c | 25 ++++++++++++------------- util2.c | 34 +++++++++++++++++++++++++--------- xattrs.c | 7 +++---- 11 files changed, 61 insertions(+), 44 deletions(-) Changeset truncated at 500 lines: diff --git a/cleanup.c b/cleanup.c index f9a5d76b..40d26baa 100644 --- a/cleanup.c +++ b/cleanup.c @@ -137,7 +137,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line) if (DEBUG_GTE(EXIT, 2)) { rprintf(FINFO, "[%s] _exit_cleanup(code=%d, file=%s, line=%d): entered\n", - who_am_i(), code, file, line); + who_am_i(), code, src_file(file), line); } #include "case_N.h" diff --git a/flist.c b/flist.c index 39f942b0..6c2543cd 100644 --- a/flist.c +++ b/flist.c @@ -133,6 +133,7 @@ static char empty_sum[MAX_DIGEST_LEN]; static int flist_count_offset; /* for --delete --progress */ static int show_filelist_progress; +static struct file_list *flist_new(int flags, const char *msg); static void flist_sort_and_clean(struct file_list *flist, int strip_root); static void output_flist(struct file_list *flist); @@ -2797,25 +2798,20 @@ void clear_file(struct file_struct *file) } /* Allocate a new file list. */ -struct file_list *flist_new(int flags, char *msg) +static struct file_list *flist_new(int flags, const char *msg) { struct file_list *flist; flist = new0(struct file_list); if (flags & FLIST_TEMP) { - if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0, - out_of_memory, - POOL_INTERN))) + if (!(flist->file_pool = pool_create(SMALL_EXTENT, 0, _out_of_memory, POOL_INTERN))) out_of_memory(msg); } else { /* This is a doubly linked list with prev looping back to * the end of the list, but the last next pointer is NULL. */ if (!first_flist) { - flist->file_pool = pool_create(NORMAL_EXTENT, 0, - out_of_memory, - POOL_INTERN); - if (!flist->file_pool) + if (!(flist->file_pool = pool_create(NORMAL_EXTENT, 0, _out_of_memory, POOL_INTERN))) out_of_memory(msg); flist->ndx_start = flist->flist_num = inc_recurse ? 1 : 0; diff --git a/lib/pool_alloc.3 b/lib/pool_alloc.3 index 6c22b924..128c1f7f 100644 --- a/lib/pool_alloc.3 +++ b/lib/pool_alloc.3 @@ -33,7 +33,7 @@ pool_alloc, pool_free, pool_free_old, pool_talloc, pool_tfree, pool_create, pool .SH SYNOPSIS .B #include "pool_alloc.h" -\fBstruct alloc_pool *pool_create(size_t \fIsize\fB, size_t \fIquantum\fB, void (*\fIbomb\fB)(char *), int \fIflags\fB); +\fBstruct alloc_pool *pool_create(size_t \fIsize\fB, size_t \fIquantum\fB, void (*\fIbomb\fB)(char*,char*,int), int \fIflags\fB); \fBvoid pool_destroy(struct alloc_pool *\fIpool\fB); diff --git a/lib/pool_alloc.c b/lib/pool_alloc.c index a70a3f1a..f6c6faf6 100644 --- a/lib/pool_alloc.c +++ b/lib/pool_alloc.c @@ -45,13 +45,13 @@ struct align_test { #define PTR_ADD(b,o) ( (void*) ((char*)(b) + (o)) ) alloc_pool_t -pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags) +pool_create(size_t size, size_t quantum, void (*bomb)(const char*, const char*, int), int flags) { struct alloc_pool *pool; if ((MINALIGN & (MINALIGN - 1)) != 0) { if (bomb) - (*bomb)("Compiler error: MINALIGN is not a power of 2\n"); + (*bomb)("Compiler error: MINALIGN is not a power of 2", __FILE__, __LINE__); return NULL; } @@ -169,7 +169,7 @@ pool_alloc(alloc_pool_t p, size_t len, const char *bomb_msg) bomb_out: if (pool->bomb) - (*pool->bomb)(bomb_msg); + (*pool->bomb)(bomb_msg, __FILE__, __LINE__); return NULL; } diff --git a/lib/pool_alloc.h b/lib/pool_alloc.h index c7368a77..28059212 100644 --- a/lib/pool_alloc.h +++ b/lib/pool_alloc.h @@ -7,7 +7,7 @@ typedef void *alloc_pool_t; -alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags); +alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(const char*, const char*, int), int flags); void pool_destroy(alloc_pool_t pool); void *pool_alloc(alloc_pool_t pool, size_t size, const char *bomb_msg); void pool_free(alloc_pool_t pool, size_t size, void *addr); diff --git a/log.c b/log.c index 633bcdbc..85eae3d5 100644 --- a/log.c +++ b/log.c @@ -890,10 +890,10 @@ void log_exit(int code, const char *file, int line) /* VANISHED is not an error, only a warning */ if (code == RERR_VANISHED) { rprintf(FWARNING, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n", - name, code, file, line, who_am_i(), RSYNC_VERSION); + name, code, src_file(file), line, who_am_i(), RSYNC_VERSION); } else { rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n", - name, code, file, line, who_am_i(), RSYNC_VERSION); + name, code, src_file(file), line, who_am_i(), RSYNC_VERSION); } } } 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..c8715747 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 @@ -1321,6 +1325,9 @@ extern char *do_malloc; #undef strdup #define strdup(s) my_strdup(s, __FILE__, __LINE__) +#define out_of_memory(msg) _out_of_memory(msg, __FILE__, __LINE__) +#define overflow_exit(msg) _overflow_exit(msg, __FILE__, __LINE__) + /* use magic gcc attributes to catch format errors */ void rprintf(enum logcode , const char *, ...) __attribute__((format (printf, 2, 3))) 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/util2.c b/util2.c index 6ea6981d..8879c987 100644 --- a/util2.c +++ b/util2.c @@ -76,7 +76,7 @@ void *my_alloc(void *ptr, size_t num, size_t size, const char *file, int line) if (!file) return NULL; rprintf(FERROR, "[%s] exceeded --max-alloc=%s setting (file=%s, line=%d)\n", - who_am_i(), do_big_num(max_alloc, 0, NULL), file, line); + who_am_i(), do_big_num(max_alloc, 0, NULL), src_file(file), line); exit_cleanup(RERR_MALLOC); } if (!ptr) @@ -85,10 +85,8 @@ void *my_alloc(void *ptr, size_t num, size_t size, const char *file, int line) ptr = malloc(num * size); else ptr = realloc(ptr, num * size); - if (!ptr && file) { - rprintf(FERROR, "[%s] out of memory (file=%s, line=%d)\n", who_am_i(), file, line); - exit_cleanup(RERR_MALLOC); - } + if (!ptr && file) + _out_of_memory("my_alloc caller", file, line); return ptr; } @@ -119,14 +117,32 @@ const char *sum_as_hex(int csum_type, const char *sum, int flist_csum) return buf; } -NORETURN void out_of_memory(const char *str) +NORETURN void _out_of_memory(const char *msg, const char *file, int line) { - rprintf(FERROR, "ERROR: out of memory in %s [%s]\n", str, who_am_i()); + rprintf(FERROR, "[%s] out of memory: %s (file=%s, line=%d)\n", who_am_i(), msg, src_file(file), line); exit_cleanup(RERR_MALLOC); } -NORETURN void overflow_exit(const char *str) +NORETURN void _overflow_exit(const char *msg, const char *file, int line) { - rprintf(FERROR, "ERROR: buffer overflow in %s [%s]\n", str, who_am_i()); + rprintf(FERROR, "[%s] buffer overflow: %s (file=%s, line=%d)\n", who_am_i(), msg, src_file(file), line); exit_cleanup(RERR_MALLOC); } + +const char *src_file(const char *file) +{ + static const char *util2 = __FILE__; + static int prefix = -1; + + if (prefix < 0) { + const char *cp; + for (cp = util2, prefix = 0; *cp; cp++) { + if (*cp == '/') + prefix = cp - util2 + 1; + } + } + + if (prefix && strncmp(file, util2, prefix) == 0) + return file + prefix; + return file; +} 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; -- The rsync repository. _______________________________________________ rsync-cvs mailing list rsync-cvs@lists.samba.org https://lists.samba.org/mailman/listinfo/rsync-cvs