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