Skip to content

Commit a2fb0c2

Browse files
committed
Auto merge of #69241 - shahn:checked_add_revert, r=Mark-Simulacrum,lqd
Revert "Remove `checked_add` in `Layout::repeat`" This fixes a a segfault in safe code, a stable regression. Reported in #69225. This reverts commit a983e05.
2 parents e0e5d82 + 3e17d19 commit a2fb0c2

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

src/libcore/alloc.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,13 @@ impl Layout {
241241
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
242242
#[inline]
243243
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
244-
// This cannot overflow. Quoting from the invariant of Layout:
245-
// > `size`, when rounded up to the nearest multiple of `align`,
246-
// > must not overflow (i.e., the rounded value must be less than
247-
// > `usize::MAX`)
248-
let padded_size = self.size() + self.padding_needed_for(self.align());
244+
// Warning, removing the checked_add here led to segfaults in #67174. Further
245+
// analysis in #69225 seems to indicate that this is an LTO-related
246+
// miscompilation, so #67174 might be able to be reapplied in the future.
247+
let padded_size = self
248+
.size()
249+
.checked_add(self.padding_needed_for(self.align()))
250+
.ok_or(LayoutErr { private: () })?;
249251
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
250252

251253
unsafe {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Ensure we appropriately error instead of overflowing a calculation when creating a new Alloc
2+
// Layout
3+
4+
// run-fail
5+
// compile-flags: -C opt-level=3
6+
// error-pattern: index out of bounds: the len is 0 but the index is 16777216
7+
// ignore-wasm no panic or subprocess support
8+
// ignore-emscripten no panic or subprocess support
9+
10+
fn do_test(x: usize) {
11+
let arr = vec![vec![0u8; 3]];
12+
13+
let mut z = Vec::new();
14+
for arr_ref in arr {
15+
for y in 0..x {
16+
for _ in 0..1 {
17+
z.extend(std::iter::repeat(0).take(x));
18+
let a = y * x;
19+
let b = (y + 1) * x - 1;
20+
let slice = &arr_ref[a..b];
21+
eprintln!("{} {} {} {}", a, b, arr_ref.len(), slice.len());
22+
eprintln!("{:?}", slice[1 << 24]);
23+
}
24+
}
25+
}
26+
}
27+
28+
fn main() {
29+
do_test(1);
30+
do_test(2);
31+
}

0 commit comments

Comments
 (0)