From cc911409d6561d66094c2303e9a79b41ea4f2ef5 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sat, 31 May 2008 09:08:13 -0700 Subject: [PATCH] Make sure the generator doesn't try to send a negative checksum count to the sender (which would cause it to die with a cryptic error). Instead, warn the user when the file's size is too large for checksum processing. --- NEWS | 6 ++++++ generator.c | 25 ++++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 147ed7ec..c77da63b 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,8 @@ Changes since 3.0.2: - Fixed several places in the code that were not returning the right errno when a function failed. + - Fixed the backing up of a device or special file into a backup dir. + - Moved the setting of the socket options prior to the connect(). - If rsync exits in the middle of a --progress output, it now outputs a @@ -27,6 +29,10 @@ Changes since 3.0.2: - Fixed a problem with how a destination path with a trailing slash was compared against the daemon excludes. + - If a file's length is so huge that we overflow a checksum buffer count + (i.e. several hundred TB), warn the user and avoid sending an invalid + checksum struct over the wire. + - Use the overflow_exit() function for overflows, not out_of_memory(). ENHANCEMENTS: diff --git a/generator.c b/generator.c index 858305e7..0ac86426 100644 --- a/generator.c +++ b/generator.c @@ -753,6 +753,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) { int32 blength; int s2length; + int64 l; if (block_size) blength = block_size; @@ -760,7 +761,6 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) blength = BLOCK_SIZE; else { int32 c; - int64 l; int cnt; for (c = 1, l = len, cnt = 0; l >>= 2; c <<= 1, cnt++) {} if (cnt >= 31 || c >= MAX_BLOCK_SIZE) @@ -783,7 +783,6 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) s2length = SUM_LENGTH; } else { int32 c; - int64 l; int b = BLOCKSUM_BIAS; for (l = len; l >>= 1; b += 2) {} for (c = blength; (c >>= 1) && b; b--) {} @@ -797,7 +796,10 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) sum->blength = blength; sum->s2length = s2length; sum->remainder = (int32)(len % blength); - sum->count = (int32)(len / blength) + (sum->remainder != 0); + sum->count = (int32)(l = (len / blength) + (sum->remainder != 0)); + + if ((int64)sum->count != l) + sum->count = -1; if (sum->count && verbose > 2) { rprintf(FINFO, @@ -813,7 +815,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) * * Generate approximately one checksum every block_len bytes. */ -static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy) +static int generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy) { int32 i; struct map_struct *mapbuf; @@ -821,10 +823,12 @@ static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy) OFF_T offset = 0; sum_sizes_sqroot(&sum, len); + if (sum.count < 0) + return -1; write_sum_head(f_out, &sum); if (append_mode > 0 && f_copy < 0) - return; + return 0; if (len > 0) mapbuf = map_file(fd, len, MAX_MAP_SIZE, sum.blength); @@ -861,6 +865,8 @@ static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy) if (mapbuf) unmap_file(mapbuf); + + return 0; } @@ -1938,10 +1944,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (read_batch) goto cleanup; - if (statret != 0 || whole_file) + if (statret != 0 || whole_file || sx.st.st_size <= 0) write_sum_head(f_out, NULL); else { - generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy); + if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) { + rprintf(FWARNING, + "WARNING: file is too large for checksum sending: %s\n", + fnamecmp); + write_sum_head(f_out, NULL); + } close(fd); } -- 2.34.1