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.
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;
{
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) {
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;
/* 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;