From: Andrew Tridgell Date: Tue, 30 Dec 2025 07:49:34 +0000 (+1100) Subject: reject negative token values in compressed stream receivers X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=359e539a72526ed27fc412df65752d4eb9ea380e;p=thirdparty%2Frsync.git reject negative token values in compressed stream receivers Validate that token numbers read from compressed streams are non-negative. A negative token value would cause the return value of recv_*_token() to become positive, which callers interpret as literal data length, but no data pointer is set on this code path. While this only causes the receiver to crash (which is process-isolated and only affects the attacker's own connection), it's still undefined behavior. Reported-by: Will Sergeant --- diff --git a/token.c b/token.c index 91091be1..773f14a2 100644 --- a/token.c +++ b/token.c @@ -590,8 +590,13 @@ static int32 recv_deflated_token(int f, char **data) if (flag & TOKEN_REL) { rx_token += flag & 0x3f; flag >>= 6; - } else + } else { rx_token = read_int(f); + if (rx_token < 0) { + rprintf(FERROR, "invalid token number in compressed stream\n"); + exit_cleanup(RERR_PROTOCOL); + } + } if (flag & 1) { rx_run = read_byte(f); rx_run += read_byte(f) << 8; @@ -834,8 +839,13 @@ static int32 recv_zstd_token(int f, char **data) if (flag & TOKEN_REL) { rx_token += flag & 0x3f; flag >>= 6; - } else + } else { rx_token = read_int(f); + if (rx_token < 0) { + rprintf(FERROR, "invalid token number in compressed stream\n"); + exit_cleanup(RERR_PROTOCOL); + } + } if (flag & 1) { rx_run = read_byte(f); rx_run += read_byte(f) << 8; @@ -998,8 +1008,13 @@ static int32 recv_compressed_token(int f, char **data) if (flag & TOKEN_REL) { rx_token += flag & 0x3f; flag >>= 6; - } else + } else { rx_token = read_int(f); + if (rx_token < 0) { + rprintf(FERROR, "invalid token number in compressed stream\n"); + exit_cleanup(RERR_PROTOCOL); + } + } if (flag & 1) { rx_run = read_byte(f); rx_run += read_byte(f) << 8;