diff --git a/Cargo.toml b/Cargo.toml index e8a58b3a65..83a7270c5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,7 +113,6 @@ restriction = { level = "warn", priority = -2 } # lints to decide on -arithmetic_side_effects = "allow" # TODO: consider as_conversions = "allow" # TODO: tricky cast_possible_truncation = "allow" # TODO: consider cast_precision_loss = "allow" # TODO: consider diff --git a/src/body/length.rs b/src/body/length.rs index 0a782b033f..3cc396134d 100644 --- a/src/body/length.rs +++ b/src/body/length.rs @@ -70,7 +70,7 @@ impl DecodedLength { match *self { DecodedLength::CHUNKED | DecodedLength::CLOSE_DELIMITED => (), DecodedLength(ref mut known) => { - *known -= amt; + *known = known.saturating_sub(amt); } } } diff --git a/src/common/buf.rs b/src/common/buf.rs index d00071551b..031119861d 100644 --- a/src/common/buf.rs +++ b/src/common/buf.rs @@ -38,6 +38,7 @@ impl Buf for BufList { } #[inline] + #[allow(clippy::arithmetic_side_effects)] fn advance(&mut self, mut cnt: usize) { while cnt > 0 { { @@ -56,6 +57,7 @@ impl Buf for BufList { } #[inline] + #[allow(clippy::arithmetic_side_effects)] fn chunks_vectored<'t>(&'t self, dst: &mut [IoSlice<'t>]) -> usize { if dst.is_empty() { return 0; diff --git a/src/common/date.rs b/src/common/date.rs index d348ff7bc7..559f919f55 100644 --- a/src/common/date.rs +++ b/src/common/date.rs @@ -67,6 +67,7 @@ impl CachedDate { } } + #[allow(clippy::arithmetic_side_effects)] fn update(&mut self, now: SystemTime) { let nanos = now .duration_since(UNIX_EPOCH) @@ -95,6 +96,7 @@ impl CachedDate { } impl fmt::Write for CachedDate { + #[allow(clippy::arithmetic_side_effects)] fn write_str(&mut self, s: &str) -> fmt::Result { let len = s.len(); self.bytes[self.pos..self.pos + len].copy_from_slice(s.as_bytes()); diff --git a/src/common/io/compat.rs b/src/common/io/compat.rs index c390b130c1..4cb5354ba5 100644 --- a/src/common/io/compat.rs +++ b/src/common/io/compat.rs @@ -24,6 +24,7 @@ where T: crate::rt::Read, { /// `poll_read` fn implementation for `Compat`. + #[allow(clippy::arithmetic_side_effects)] fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/src/ext/h1_reason_phrase.rs b/src/ext/h1_reason_phrase.rs index c4c615bc20..9cc1b8a9a1 100644 --- a/src/ext/h1_reason_phrase.rs +++ b/src/ext/h1_reason_phrase.rs @@ -157,6 +157,7 @@ const fn is_valid_byte(b: u8) -> bool { b == b'\t' || b == b' ' || is_vchar(b) || is_obs_text(b) } +#[allow(clippy::arithmetic_side_effects)] const fn find_invalid_byte(bytes: &[u8]) -> Option { let mut i = 0; while i < bytes.len() { diff --git a/src/headers.rs b/src/headers.rs index 0b36e060f0..f1c5afaa1b 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -67,6 +67,7 @@ pub(super) fn content_length_parse_all_values(values: ValueIter<'_, HeaderValue> content_length } +#[allow(clippy::arithmetic_side_effects)] fn from_digits(bytes: &[u8]) -> Option { // cannot use FromStr for u64, since it allows a signed prefix let mut result = 0u64; @@ -137,6 +138,7 @@ pub(super) fn is_chunked_(value: &HeaderValue) -> bool { } #[cfg(all(feature = "client", feature = "http1"))] +#[allow(clippy::arithmetic_side_effects)] pub(super) fn add_chunked(mut entry: http::header::OccupiedEntry<'_, HeaderValue>) { const CHUNKED: &str = "chunked"; diff --git a/src/proto/h1/conn.rs b/src/proto/h1/conn.rs index dfcadcee56..c0f816a8c0 100644 --- a/src/proto/h1/conn.rs +++ b/src/proto/h1/conn.rs @@ -208,6 +208,7 @@ where read_buf.len() >= 24 && read_buf[..24] == *H2_PREFACE } + #[allow(clippy::arithmetic_side_effects)] pub(super) fn poll_read_head( &mut self, cx: &mut Context<'_>, diff --git a/src/proto/h1/decode.rs b/src/proto/h1/decode.rs index 0a95dd58d3..46e6abf8d9 100644 --- a/src/proto/h1/decode.rs +++ b/src/proto/h1/decode.rs @@ -141,6 +141,7 @@ impl Decoder { ) } + #[allow(clippy::arithmetic_side_effects)] pub(crate) fn decode( &mut self, cx: &mut Context<'_>, @@ -339,6 +340,7 @@ impl ChunkedState { } } + #[allow(clippy::arithmetic_side_effects)] fn read_start( cx: &mut Context<'_>, rdr: &mut R, @@ -371,6 +373,7 @@ impl ChunkedState { Poll::Ready(Ok(ChunkedState::Size)) } + #[allow(clippy::arithmetic_side_effects)] fn read_size( cx: &mut Context<'_>, rdr: &mut R, @@ -420,6 +423,7 @@ impl ChunkedState { ))), } } + #[allow(clippy::arithmetic_side_effects)] fn read_extension( cx: &mut Context<'_>, rdr: &mut R, @@ -473,6 +477,7 @@ impl ChunkedState { } } + #[allow(clippy::arithmetic_side_effects)] fn read_body( cx: &mut Context<'_>, rdr: &mut R, @@ -548,6 +553,7 @@ impl ChunkedState { } } + #[allow(clippy::arithmetic_side_effects)] fn read_trailer_lf( cx: &mut Context<'_>, rdr: &mut R, diff --git a/src/proto/h1/encode.rs b/src/proto/h1/encode.rs index fcf7940b16..a9d204eead 100644 --- a/src/proto/h1/encode.rs +++ b/src/proto/h1/encode.rs @@ -125,6 +125,7 @@ impl Encoder { } } + #[allow(clippy::arithmetic_side_effects)] pub(crate) fn encode(&mut self, msg: B) -> EncodedBuf where B: Buf, @@ -359,6 +360,7 @@ impl ChunkSize { impl Buf for ChunkSize { #[inline] + #[allow(clippy::arithmetic_side_effects)] fn remaining(&self) -> usize { (self.len - self.pos).into() } @@ -369,6 +371,7 @@ impl Buf for ChunkSize { } #[inline] + #[allow(clippy::arithmetic_side_effects)] fn advance(&mut self, cnt: usize) { assert!(cnt <= self.remaining()); self.pos += cnt as u8; // just asserted cnt fits in u8 @@ -385,6 +388,7 @@ impl fmt::Debug for ChunkSize { } impl fmt::Write for ChunkSize { + #[allow(clippy::arithmetic_side_effects)] fn write_str(&mut self, num: &str) -> fmt::Result { use std::io::Write; (&mut self.bytes[self.len.into()..]) diff --git a/src/proto/h1/io.rs b/src/proto/h1/io.rs index 2aeabc7c60..a0b769bfc0 100644 --- a/src/proto/h1/io.rs +++ b/src/proto/h1/io.rs @@ -123,6 +123,7 @@ where /// Return the "allocated" available space, not the potential space /// that could be allocated in the future. + #[allow(clippy::arithmetic_side_effects)] fn read_buf_remaining_mut(&self) -> usize { self.read_buf.capacity() - self.read_buf.len() } @@ -153,6 +154,7 @@ where self.flush_pipeline || self.write_buf.can_buffer() } + #[allow(clippy::arithmetic_side_effects)] pub(crate) fn consume_leading_lines(&mut self) { if !self.read_buf.is_empty() { let mut i = 0; @@ -432,6 +434,7 @@ fn incr_power_of_two(n: usize) -> usize { n.saturating_mul(2) } +#[allow(clippy::arithmetic_side_effects)] fn prev_power_of_two(n: usize) -> usize { // Only way this shift can underflow is if n is less than 4. // (Which would means `usize::MAX >> 64` and underflowed!) @@ -462,6 +465,7 @@ impl Cursor> { /// If we've advanced the position a bit in this cursor, and wish to /// extend the underlying vector, we may wish to unshift the "read" bytes /// off, and move everything else over. + #[allow(clippy::arithmetic_side_effects)] fn maybe_unshift(&mut self, additional: usize) { if self.pos == 0 { // nothing to do @@ -494,6 +498,7 @@ impl> fmt::Debug for Cursor { impl> Buf for Cursor { #[inline] + #[allow(clippy::arithmetic_side_effects)] fn remaining(&self) -> usize { self.bytes.as_ref().len() - self.pos } @@ -504,6 +509,7 @@ impl> Buf for Cursor { } #[inline] + #[allow(clippy::arithmetic_side_effects)] fn advance(&mut self, cnt: usize) { debug_assert!(self.pos + cnt <= self.bytes.as_ref().len()); self.pos += cnt; @@ -602,6 +608,7 @@ impl fmt::Debug for WriteBuf { impl Buf for WriteBuf { #[inline] + #[allow(clippy::arithmetic_side_effects)] fn remaining(&self) -> usize { self.headers.remaining() + self.queue.remaining() } @@ -617,6 +624,7 @@ impl Buf for WriteBuf { } #[inline] + #[allow(clippy::arithmetic_side_effects)] fn advance(&mut self, cnt: usize) { let hrem = self.headers.remaining(); @@ -632,6 +640,7 @@ impl Buf for WriteBuf { } #[inline] + #[allow(clippy::arithmetic_side_effects)] fn chunks_vectored<'t>(&'t self, dst: &mut [IoSlice<'t>]) -> usize { let n = self.headers.chunks_vectored(dst); self.queue.chunks_vectored(&mut dst[n..]) + n diff --git a/src/proto/h1/role.rs b/src/proto/h1/role.rs index 740c8e1d56..0d42336082 100644 --- a/src/proto/h1/role.rs +++ b/src/proto/h1/role.rs @@ -97,6 +97,7 @@ where /// A fast scan for the end of a message. /// Used when there was a partial read, to skip full parsing on a /// a slow connection. +#[allow(clippy::arithmetic_side_effects)] fn is_complete_fast(bytes: &[u8], prev_len: usize) -> bool { let start = prev_len.saturating_sub(3); let bytes = &bytes[start..]; @@ -367,6 +368,7 @@ impl Http1Transaction for Server { })) } + #[allow(clippy::arithmetic_side_effects)] fn encode(mut msg: Encode<'_, Self::Outgoing>, dst: &mut Vec) -> crate::Result { trace!( "Server::encode status={:?}, body={:?}, req_method={:?}", @@ -669,7 +671,7 @@ impl Server { if is_name_written { // we need to clean up and write the newline debug_assert_ne!( - &dst[dst.len() - 2..], + &dst[dst.len().saturating_sub(2)..], b"\r\n", "previous header wrote newline but set is_name_written" ); @@ -981,6 +983,7 @@ impl Server { /// Helper for zero-copy parsing of request path URI. #[inline] + #[allow(clippy::arithmetic_side_effects)] fn record_path_range(bytes: &[u8], req_path: &str) -> std::ops::Range { let bytes_ptr = bytes.as_ptr() as usize; let start = req_path.as_ptr() as usize - bytes_ptr; @@ -1183,6 +1186,7 @@ impl Http1Transaction for Client { } } + #[allow(clippy::arithmetic_side_effects)] fn encode(msg: Encode<'_, Self::Outgoing>, dst: &mut Vec) -> crate::Result { trace!( "Client::encode method={:?}, body={:?}", @@ -1443,6 +1447,7 @@ impl Client { set_content_length(headers, len) } + #[allow(clippy::arithmetic_side_effects)] fn obs_fold_line(all: &mut [u8], idx: &mut HeaderIndices) { // If the value has obs-folded text, then in-place shift the bytes out // of here. @@ -1543,6 +1548,7 @@ struct HeaderIndices { value: (usize, usize), } +#[allow(clippy::arithmetic_side_effects)] fn record_header_indices( bytes: &[u8], headers: &[httparse::Header<'_>], diff --git a/src/proto/h2/ping.rs b/src/proto/h2/ping.rs index f4caae148e..bc185e1080 100644 --- a/src/proto/h2/ping.rs +++ b/src/proto/h2/ping.rs @@ -213,7 +213,7 @@ impl Recorder { } if let Some(ref mut bytes) = locked.bytes { - *bytes += len; + *bytes = bytes.saturating_add(len); } else { // no need to send bdp ping if bdp is disabled return; @@ -284,7 +284,8 @@ impl Ponger { .ping_sent_at .expect("pong received implies ping_sent_at"); locked.ping_sent_at = None; - let rtt = now - start; + + let rtt = now.saturating_duration_since(start); trace!("recv pong"); if let Some(ref mut ka) = self.keep_alive { @@ -299,7 +300,8 @@ impl Ponger { trace!("received BDP ack; bytes = {}, rtt = {:?}", bytes, rtt); let update = bdp.calculate(bytes, rtt); - locked.next_bdp_at = Some(now + bdp.ping_delay); + // if we saturate, we don't have any Instant to check for next BDP + locked.next_bdp_at = now.checked_add(bdp.ping_delay); if let Some(update) = update { return Poll::Ready(Ponged::SizeUpdate(update)); } @@ -395,12 +397,12 @@ impl Bdp { // if the current `bytes` sample is at least 2/3 the previous // bdp, increase to double the current sample. - if bytes >= self.bdp as usize * 2 / 3 { - self.bdp = (bytes * 2).min(BDP_LIMIT) as WindowSize; + if bytes >= (self.bdp as usize).saturating_mul(2) / 3 { + self.bdp = (bytes.saturating_mul(2)).min(BDP_LIMIT) as WindowSize; trace!("BDP increased to {}", self.bdp); self.stable_count = 0; - self.ping_delay /= 2; + self.reduce_ping_delay(); Some(self.bdp) } else { self.stabilize_delay(); @@ -408,12 +410,18 @@ impl Bdp { } } + #[allow(clippy::arithmetic_side_effects)] + #[inline] + fn reduce_ping_delay(&mut self) { + self.ping_delay /= 2; + } + fn stabilize_delay(&mut self) { if self.ping_delay < Duration::from_secs(10) { - self.stable_count += 1; + self.stable_count = self.stable_count.saturating_add(1); if self.stable_count >= 2 { - self.ping_delay *= 4; + self.ping_delay = self.ping_delay.saturating_mul(4); self.stable_count = 0; } } @@ -448,12 +456,14 @@ impl KeepAlive { } } + #[allow(clippy::arithmetic_side_effects)] fn schedule(&mut self, shared: &Shared) { let interval = shared.last_read_at() + self.interval; self.state = KeepAliveState::Scheduled(interval); self.timer.reset(&mut self.sleep, interval); } + #[allow(clippy::arithmetic_side_effects)] fn maybe_ping(&mut self, cx: &mut task::Context<'_>, is_idle: bool, shared: &mut Shared) { match self.state { KeepAliveState::Scheduled(at) => { diff --git a/src/rt/io.rs b/src/rt/io.rs index 21c8ed9c7c..928ef43d8c 100644 --- a/src/rt/io.rs +++ b/src/rt/io.rs @@ -300,7 +300,13 @@ impl<'data> ReadBuf<'data> { } #[inline] + #[allow(clippy::arithmetic_side_effects)] fn remaining(&self) -> usize { + debug_assert!( + self.capacity() >= self.filled, + "filled must fit in capacity()" + ); + // Cannot overflow, asserted above self.capacity() - self.filled } @@ -359,6 +365,7 @@ impl ReadBufCursor<'_> { /// /// `self` must have enough remaining capacity to contain all of `src`. #[inline] + #[allow(clippy::arithmetic_side_effects)] pub fn put_slice(&mut self, src: &[u8]) { assert!( self.buf.remaining() >= src.len(),