Skip to content

Commit 7bf47a4

Browse files
committed
Auto merge of #116070 - eduardosm:IoSlice-advance_slices-checked_add, r=Mark-Simulacrum
Avoid overflow in `IoSlice::advance_slices` Noticed in #62726 (comment).
2 parents 1cbfeab + 9386338 commit 7bf47a4

File tree

1 file changed

+19
-16
lines changed

1 file changed

+19
-16
lines changed

library/std/src/io/mod.rs

+19-16
Original file line numberDiff line numberDiff line change
@@ -1236,22 +1236,22 @@ impl<'a> IoSliceMut<'a> {
12361236
pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
12371237
// Number of buffers to remove.
12381238
let mut remove = 0;
1239-
// Total length of all the to be removed buffers.
1240-
let mut accumulated_len = 0;
1239+
// Remaining length before reaching n.
1240+
let mut left = n;
12411241
for buf in bufs.iter() {
1242-
if accumulated_len + buf.len() > n {
1243-
break;
1244-
} else {
1245-
accumulated_len += buf.len();
1242+
if let Some(remainder) = left.checked_sub(buf.len()) {
1243+
left = remainder;
12461244
remove += 1;
1245+
} else {
1246+
break;
12471247
}
12481248
}
12491249

12501250
*bufs = &mut take(bufs)[remove..];
12511251
if bufs.is_empty() {
1252-
assert!(n == accumulated_len, "advancing io slices beyond their length");
1252+
assert!(left == 0, "advancing io slices beyond their length");
12531253
} else {
1254-
bufs[0].advance(n - accumulated_len)
1254+
bufs[0].advance(left);
12551255
}
12561256
}
12571257
}
@@ -1379,22 +1379,25 @@ impl<'a> IoSlice<'a> {
13791379
pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
13801380
// Number of buffers to remove.
13811381
let mut remove = 0;
1382-
// Total length of all the to be removed buffers.
1383-
let mut accumulated_len = 0;
1382+
// Remaining length before reaching n. This prevents overflow
1383+
// that could happen if the length of slices in `bufs` were instead
1384+
// accumulated. Those slice may be aliased and, if they are large
1385+
// enough, their added length may overflow a `usize`.
1386+
let mut left = n;
13841387
for buf in bufs.iter() {
1385-
if accumulated_len + buf.len() > n {
1386-
break;
1387-
} else {
1388-
accumulated_len += buf.len();
1388+
if let Some(remainder) = left.checked_sub(buf.len()) {
1389+
left = remainder;
13891390
remove += 1;
1391+
} else {
1392+
break;
13901393
}
13911394
}
13921395

13931396
*bufs = &mut take(bufs)[remove..];
13941397
if bufs.is_empty() {
1395-
assert!(n == accumulated_len, "advancing io slices beyond their length");
1398+
assert!(left == 0, "advancing io slices beyond their length");
13961399
} else {
1397-
bufs[0].advance(n - accumulated_len)
1400+
bufs[0].advance(left);
13981401
}
13991402
}
14001403
}

0 commit comments

Comments
 (0)