From: Andrew Tridgell Date: Thu, 4 Jun 2026 04:04:47 +0000 (+1000) Subject: generator: cap block s2length at the negotiated checksum length X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fe946581ba432ade46d548b3a37517417f4ae8cf;p=thirdparty%2Frsync.git generator: cap block s2length at the negotiated checksum length sum_sizes_sqroot() capped the strong-sum length at SUM_LENGTH (16), the legacy MD4/MD5 digest size. Since 0902b52f the sum2 array elements are xfer_sum_len bytes and the sender rejects a sums header whose s2length exceeds xfer_sum_len. When the negotiated transfer checksum is shorter than 16 bytes -- xxh64 (8), used when the build's libxxhash lacks xxh128/xxh3 (e.g. Ubuntu 20.04) -- the generator still emitted s2length up to 16, so --append-verify and other full-checksum (redo) transfers died with "Invalid checksum length 16 [sender]" (protocol incompatibility). Cap s2length at MIN(SUM_LENGTH, xfer_sum_len): unchanged for any checksum >= 16 bytes (md5/xxh128/sha1), corrected for short ones. Also closes a latent over-read of the xfer_sum_len-sized digest buffer. --- diff --git a/generator.c b/generator.c index 4d4ae72e..83c4c128 100644 --- a/generator.c +++ b/generator.c @@ -66,6 +66,7 @@ extern int inplace; extern int append_mode; extern int make_backups; extern int csum_length; +extern int xfer_sum_len; extern int ignore_times; extern int size_only; extern OFF_T max_size; @@ -697,6 +698,11 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) { int32 blength; int s2length; + /* The strong sum can be no longer than the negotiated checksum digest: + * a short checksum (e.g. xxh64 = 8 bytes, when xxh128/xxh3 are absent) + * makes xfer_sum_len < SUM_LENGTH, and the sender rejects an s2length + * larger than xfer_sum_len (io.c). */ + int max_s2length = MIN(SUM_LENGTH, xfer_sum_len); int64 l; if (len < 0) { @@ -731,7 +737,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) if (protocol_version < 27) { s2length = csum_length; } else if (csum_length == SUM_LENGTH) { - s2length = SUM_LENGTH; + s2length = max_s2length; } else { int32 c; int b = BLOCKSUM_BIAS; @@ -740,7 +746,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) /* add a bit, subtract rollsum, round up. */ s2length = (b + 1 - 32 + 7) / 8; /* --optimize in compiler-- */ s2length = MAX(s2length, csum_length); - s2length = MIN(s2length, SUM_LENGTH); + s2length = MIN(s2length, max_s2length); } sum->flength = len;