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 <wlsergeant@gmail.com>
This commit is contained in:
Andrew Tridgell
2025-12-30 18:49:34 +11:00
parent 9e0898460d
commit 359e539a72

21
token.c
View File

@@ -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;