From 147c7a0d977b0a98a078369defbc618ad7387e50 Mon Sep 17 00:00:00 2001
From: Wayne Davison <wayne@opencoder.net>
Date: Tue, 29 Oct 2024 22:55:29 -0700
Subject: [PATCH 05/60] Some checksum buffer fixes.

- Put sum2_array into sum_struct to hold an array of sum2 checksums
  that are each xfer_sum_len bytes.
- Remove sum2 buf from sum_buf.
- Add macro sum2_at() to access each sum2 array element.
- Throw an error if a sums header has an s2length larger than
  xfer_sum_len.
---
 io.c     | 3 ++-
 match.c  | 8 ++++----
 rsync.c  | 5 ++++-
 rsync.h  | 4 +++-
 sender.c | 4 +++-
 5 files changed, 16 insertions(+), 8 deletions(-)

Index: rsync-3.1.3/io.c
===================================================================
--- rsync-3.1.3.orig/io.c
+++ rsync-3.1.3/io.c
@@ -53,6 +53,7 @@ extern int read_batch;
 extern int compat_flags;
 extern int protect_args;
 extern int checksum_seed;
+extern int xfer_sum_len;
 extern int protocol_version;
 extern int remove_source_files;
 extern int preserve_hard_links;
@@ -1911,7 +1912,7 @@ void read_sum_head(int f, struct sum_str
 		exit_cleanup(RERR_PROTOCOL);
 	}
 	sum->s2length = protocol_version < 27 ? csum_length : (int)read_int(f);
-	if (sum->s2length < 0 || sum->s2length > MAX_DIGEST_LEN) {
+	if (sum->s2length < 0 || sum->s2length > xfer_sum_len) {
 		rprintf(FERROR, "Invalid checksum length %d [%s]\n",
 			sum->s2length, who_am_i());
 		exit_cleanup(RERR_PROTOCOL);
Index: rsync-3.1.3/match.c
===================================================================
--- rsync-3.1.3.orig/match.c
+++ rsync-3.1.3/match.c
@@ -25,6 +25,7 @@
 extern int checksum_seed;
 extern int append_mode;
 extern int xfersum_type;
+extern int xfer_sum_len;
 
 int updating_basis_file;
 char sender_file_sum[MAX_DIGEST_LEN];
@@ -231,7 +232,7 @@ static void hash_search(int f,struct sum
 				done_csum2 = 1;
 			}
 
-			if (memcmp(sum2,s->sums[i].sum2,s->s2length) != 0) {
+			if (memcmp(sum2, sum2_at(s, i), s->s2length) != 0) {
 				false_alarms++;
 				continue;
 			}
@@ -251,7 +252,7 @@ static void hash_search(int f,struct sum
 					if (i != aligned_i) {
 						if (sum != s->sums[aligned_i].sum1
 						 || l != s->sums[aligned_i].len
-						 || memcmp(sum2, s->sums[aligned_i].sum2, s->s2length) != 0)
+						 || memcmp(sum2, sum2_at(s, aligned_i), s->s2length) != 0)
 							goto check_want_i;
 						i = aligned_i;
 					}
@@ -270,7 +271,7 @@ static void hash_search(int f,struct sum
 						if (sum != s->sums[i].sum1)
 							goto check_want_i;
 						get_checksum2((char *)map, l, sum2);
-						if (memcmp(sum2, s->sums[i].sum2, s->s2length) != 0)
+						if (memcmp(sum2, sum2_at(s, i), s->s2length) != 0)
 							goto check_want_i;
 						/* OK, we have a re-alignment match.  Bump the offset
 						 * forward to the new match point. */
@@ -289,7 +290,7 @@ static void hash_search(int f,struct sum
 			    && (!updating_basis_file || s->sums[want_i].offset >= offset
 			     || s->sums[want_i].flags & SUMFLG_SAME_OFFSET)
 			    && sum == s->sums[want_i].sum1
-			    && memcmp(sum2, s->sums[want_i].sum2, s->s2length) == 0) {
+			    && memcmp(sum2, sum2_at(s, want_i), s->s2length) == 0) {
 				/* we've found an adjacent match - the RLL coder
 				 * will be happy */
 				i = want_i;
Index: rsync-3.1.3/rsync.c
===================================================================
--- rsync-3.1.3.orig/rsync.c
+++ rsync-3.1.3/rsync.c
@@ -427,7 +427,10 @@ int read_ndx_and_attrs(int f_in, int f_o
   */
 void free_sums(struct sum_struct *s)
 {
-	if (s->sums) free(s->sums);
+	if (s->sums) {
+		free(s->sums);
+		free(s->sum2_array);
+	}
 	free(s);
 }
 
Index: rsync-3.1.3/rsync.h
===================================================================
--- rsync-3.1.3.orig/rsync.h
+++ rsync-3.1.3/rsync.h
@@ -844,12 +844,12 @@ struct sum_buf {
 	uint32 sum1;	        /**< simple checksum */
 	int32 chain;		/**< next hash-table collision */
 	short flags;		/**< flag bits */
-	char sum2[SUM_LENGTH];	/**< checksum  */
 };
 
 struct sum_struct {
 	OFF_T flength;		/**< total file length */
 	struct sum_buf *sums;	/**< points to info for each chunk */
+	char *sum2_array;	/**< checksums of length xfer_sum_len */
 	int32 count;		/**< how many chunks */
 	int32 blength;		/**< block_length */
 	int32 remainder;	/**< flength % block_length */
@@ -868,6 +868,8 @@ struct map_struct {
 	int status;		/* first errno from read errors		*/
 };
 
+#define sum2_at(s, i)	((s)->sum2_array + ((OFF_T)(i) * xfer_sum_len))
+
 #define NAME_IS_FILE		(0)    /* filter name as a file */
 #define NAME_IS_DIR		(1<<0) /* filter name as a dir */
 #define NAME_IS_XATTR		(1<<2) /* filter name as an xattr */
Index: rsync-3.1.3/sender.c
===================================================================
--- rsync-3.1.3.orig/sender.c
+++ rsync-3.1.3/sender.c
@@ -30,6 +30,7 @@ extern int log_before_transfer;
 extern int stdout_format_has_i;
 extern int logfile_format_has_i;
 extern int want_xattr_optim;
+extern int xfer_sum_len;
 extern int csum_length;
 extern int append_mode;
 extern int io_error;
@@ -87,10 +88,11 @@ static struct sum_struct *receive_sums(i
 		return(s);
 
 	s->sums = new_array(struct sum_buf, s->count);
+	s->sum2_array = new_array(char, s->count * xfer_sum_len);
 
 	for (i = 0; i < s->count; i++) {
 		s->sums[i].sum1 = read_int(f);
-		read_buf(f, s->sums[i].sum2, s->s2length);
+		read_buf(f, sum2_at(s, i), s->s2length);
 
 		s->sums[i].offset = offset;
 		s->sums[i].flags = 0;
