diff options
| author | Eduardo Sánchez Muñoz <eduardosm-dev@e64.io> | 2023-09-22 20:44:56 +0200 |
|---|---|---|
| committer | Eduardo Sánchez Muñoz <eduardosm-dev@e64.io> | 2023-09-23 16:27:57 +0200 |
| commit | 93863383c8240c35f6bfda97ab96fd5ce8a5783c (patch) | |
| tree | 0f34f2be5a91ac1fd6d37c5b58baa9abf482ec8a /library/std/src | |
| parent | 959b2c703d45f06962da3afa086bdda70d42efcf (diff) | |
| download | rust-93863383c8240c35f6bfda97ab96fd5ce8a5783c.tar.gz rust-93863383c8240c35f6bfda97ab96fd5ce8a5783c.zip | |
Avoid overflow in `IoSlice::advance_slices`
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/io/mod.rs | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 7582c7444f0..604b795cd52 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1236,22 +1236,22 @@ impl<'a> IoSliceMut<'a> { pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) { // Number of buffers to remove. let mut remove = 0; - // Total length of all the to be removed buffers. - let mut accumulated_len = 0; + // Remaining length before reaching n. + let mut left = n; for buf in bufs.iter() { - if accumulated_len + buf.len() > n { - break; - } else { - accumulated_len += buf.len(); + if let Some(remainder) = left.checked_sub(buf.len()) { + left = remainder; remove += 1; + } else { + break; } } *bufs = &mut take(bufs)[remove..]; if bufs.is_empty() { - assert!(n == accumulated_len, "advancing io slices beyond their length"); + assert!(left == 0, "advancing io slices beyond their length"); } else { - bufs[0].advance(n - accumulated_len) + bufs[0].advance(left); } } } @@ -1379,22 +1379,25 @@ impl<'a> IoSlice<'a> { pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) { // Number of buffers to remove. let mut remove = 0; - // Total length of all the to be removed buffers. - let mut accumulated_len = 0; + // Remaining length before reaching n. This prevents overflow + // that could happen if the length of slices in `bufs` were instead + // accumulated. Those slice may be aliased and, if they are large + // enough, their added length may overflow a `usize`. + let mut left = n; for buf in bufs.iter() { - if accumulated_len + buf.len() > n { - break; - } else { - accumulated_len += buf.len(); + if let Some(remainder) = left.checked_sub(buf.len()) { + left = remainder; remove += 1; + } else { + break; } } *bufs = &mut take(bufs)[remove..]; if bufs.is_empty() { - assert!(n == accumulated_len, "advancing io slices beyond their length"); + assert!(left == 0, "advancing io slices beyond their length"); } else { - bufs[0].advance(n - accumulated_len) + bufs[0].advance(left); } } } |
