Revert "Auto merge of #95295 - CAD97:layout-isize, r=scottmcm"
This reverts commit4ec97d991b, reversing changes made to95e77648e4.
This commit is contained in:
parent
1d0597c103
commit
2ae81ac79c
4 changed files with 325 additions and 150 deletions
|
|
@ -693,6 +693,12 @@ fn test_try_reserve() {
|
|||
const MAX_CAP: usize = isize::MAX as usize;
|
||||
const MAX_USIZE: usize = usize::MAX;
|
||||
|
||||
// On 16/32-bit, we check that allocations don't exceed isize::MAX,
|
||||
// on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
|
||||
// Any platform that succeeds for these requests is technically broken with
|
||||
// ptr::offset because LLVM is the worst.
|
||||
let guards_against_isize = usize::BITS < 64;
|
||||
|
||||
{
|
||||
// Note: basic stuff is checked by test_reserve
|
||||
let mut empty_string: String = String::new();
|
||||
|
|
@ -706,19 +712,35 @@ fn test_try_reserve() {
|
|||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
// Check isize::MAX + 1 does count as overflow
|
||||
assert_matches!(
|
||||
empty_string.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
if guards_against_isize {
|
||||
// Check isize::MAX + 1 does count as overflow
|
||||
assert_matches!(
|
||||
empty_string.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
// Check usize::MAX does count as overflow
|
||||
assert_matches!(
|
||||
empty_string.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
// Check usize::MAX does count as overflow
|
||||
assert_matches!(
|
||||
empty_string.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
// Check isize::MAX + 1 is an OOM
|
||||
assert_matches!(
|
||||
empty_string.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
|
||||
// Check usize::MAX is an OOM
|
||||
assert_matches!(
|
||||
empty_string.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"usize::MAX should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -731,13 +753,19 @@ fn test_try_reserve() {
|
|||
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) {
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
// Should always overflow in the add-to-len
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
|
|
@ -757,6 +785,8 @@ fn test_try_reserve_exact() {
|
|||
const MAX_CAP: usize = isize::MAX as usize;
|
||||
const MAX_USIZE: usize = usize::MAX;
|
||||
|
||||
let guards_against_isize = usize::BITS < 64;
|
||||
|
||||
{
|
||||
let mut empty_string: String = String::new();
|
||||
|
||||
|
|
@ -769,17 +799,31 @@ fn test_try_reserve_exact() {
|
|||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
empty_string.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
empty_string.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
assert_matches!(
|
||||
empty_string.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
assert_matches!(
|
||||
empty_string.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
empty_string.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
|
||||
assert_matches!(
|
||||
empty_string.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"usize::MAX should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -795,13 +839,19 @@ fn test_try_reserve_exact() {
|
|||
{
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
|
|
|
|||
|
|
@ -1527,6 +1527,12 @@ fn test_try_reserve() {
|
|||
const MAX_CAP: usize = isize::MAX as usize;
|
||||
const MAX_USIZE: usize = usize::MAX;
|
||||
|
||||
// On 16/32-bit, we check that allocations don't exceed isize::MAX,
|
||||
// on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
|
||||
// Any platform that succeeds for these requests is technically broken with
|
||||
// ptr::offset because LLVM is the worst.
|
||||
let guards_against_isize = usize::BITS < 64;
|
||||
|
||||
{
|
||||
// Note: basic stuff is checked by test_reserve
|
||||
let mut empty_bytes: Vec<u8> = Vec::new();
|
||||
|
|
@ -1540,19 +1546,35 @@ fn test_try_reserve() {
|
|||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
// Check isize::MAX + 1 does count as overflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
if guards_against_isize {
|
||||
// Check isize::MAX + 1 does count as overflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
// Check usize::MAX does count as overflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
// Check usize::MAX does count as overflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
// Check isize::MAX + 1 is an OOM
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
|
||||
// Check usize::MAX is an OOM
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"usize::MAX should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -1565,13 +1587,19 @@ fn test_try_reserve() {
|
|||
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) {
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
// Should always overflow in the add-to-len
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
|
|
@ -1592,13 +1620,19 @@ fn test_try_reserve() {
|
|||
{
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
// Should fail in the mul-by-size
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve(MAX_USIZE - 20).map_err(|e| e.kind()),
|
||||
|
|
@ -1618,6 +1652,8 @@ fn test_try_reserve_exact() {
|
|||
const MAX_CAP: usize = isize::MAX as usize;
|
||||
const MAX_USIZE: usize = usize::MAX;
|
||||
|
||||
let guards_against_isize = size_of::<usize>() < 8;
|
||||
|
||||
{
|
||||
let mut empty_bytes: Vec<u8> = Vec::new();
|
||||
|
||||
|
|
@ -1630,17 +1666,31 @@ fn test_try_reserve_exact() {
|
|||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"usize::MAX should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -1656,13 +1706,19 @@ fn test_try_reserve_exact() {
|
|||
{
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
|
|
@ -1683,13 +1739,19 @@ fn test_try_reserve_exact() {
|
|||
{
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve_exact(MAX_USIZE - 20).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use std::assert_matches::assert_matches;
|
|||
use std::collections::TryReserveErrorKind::*;
|
||||
use std::collections::{vec_deque::Drain, VecDeque};
|
||||
use std::fmt::Debug;
|
||||
use std::mem::size_of;
|
||||
use std::ops::Bound::*;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
|
||||
|
|
@ -1160,6 +1161,12 @@ fn test_try_reserve() {
|
|||
const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1;
|
||||
const MAX_USIZE: usize = usize::MAX;
|
||||
|
||||
// On 16/32-bit, we check that allocations don't exceed isize::MAX,
|
||||
// on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
|
||||
// Any platform that succeeds for these requests is technically broken with
|
||||
// ptr::offset because LLVM is the worst.
|
||||
let guards_against_isize = size_of::<usize>() < 8;
|
||||
|
||||
{
|
||||
// Note: basic stuff is checked by test_reserve
|
||||
let mut empty_bytes: VecDeque<u8> = VecDeque::new();
|
||||
|
|
@ -1173,19 +1180,31 @@ fn test_try_reserve() {
|
|||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
// Check isize::MAX + 1 does count as overflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
if guards_against_isize {
|
||||
// Check isize::MAX + 1 does count as overflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
// Check usize::MAX does count as overflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
// Check usize::MAX does count as overflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
// Check isize::MAX is an OOM
|
||||
// VecDeque starts with capacity 7, always adds 1 to the capacity
|
||||
// and also rounds the number to next power of 2 so this is the
|
||||
// furthest we can go without triggering CapacityOverflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve(MAX_CAP).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -1198,13 +1217,19 @@ fn test_try_reserve() {
|
|||
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) {
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
// Should always overflow in the add-to-len
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
|
||||
|
|
@ -1225,13 +1250,19 @@ fn test_try_reserve() {
|
|||
{
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
// Should fail in the mul-by-size
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve(MAX_USIZE - 20).map_err(|e| e.kind()),
|
||||
|
|
@ -1251,6 +1282,8 @@ fn test_try_reserve_exact() {
|
|||
const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1;
|
||||
const MAX_USIZE: usize = usize::MAX;
|
||||
|
||||
let guards_against_isize = size_of::<usize>() < 8;
|
||||
|
||||
{
|
||||
let mut empty_bytes: VecDeque<u8> = VecDeque::new();
|
||||
|
||||
|
|
@ -1263,17 +1296,29 @@ fn test_try_reserve_exact() {
|
|||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"usize::MAX should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
// Check isize::MAX is an OOM
|
||||
// VecDeque starts with capacity 7, always adds 1 to the capacity
|
||||
// and also rounds the number to next power of 2 so this is the
|
||||
// furthest we can go without triggering CapacityOverflow
|
||||
assert_matches!(
|
||||
empty_bytes.try_reserve_exact(MAX_CAP).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -1289,13 +1334,19 @@ fn test_try_reserve_exact() {
|
|||
{
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
assert_matches!(
|
||||
ten_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
|
|
@ -1316,13 +1367,19 @@ fn test_try_reserve_exact() {
|
|||
{
|
||||
panic!("isize::MAX shouldn't trigger an overflow!");
|
||||
}
|
||||
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
|
||||
if guards_against_isize {
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
"isize::MAX + 1 should trigger an overflow!"
|
||||
);
|
||||
} else {
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()),
|
||||
Err(AllocError { .. }),
|
||||
"isize::MAX + 1 should trigger an OOM!"
|
||||
);
|
||||
}
|
||||
assert_matches!(
|
||||
ten_u32s.try_reserve_exact(MAX_USIZE - 20).map_err(|e| e.kind()),
|
||||
Err(CapacityOverflow),
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ impl Layout {
|
|||
/// * `align` must be a power of two,
|
||||
///
|
||||
/// * `size`, when rounded up to the nearest multiple of `align`,
|
||||
/// must not overflow isize (i.e., the rounded value must be
|
||||
/// less than or equal to `isize::MAX`).
|
||||
/// must not overflow (i.e., the rounded value must be less than
|
||||
/// or equal to `usize::MAX`).
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
|
||||
#[inline]
|
||||
|
|
@ -76,7 +76,7 @@ impl Layout {
|
|||
//
|
||||
// Above implies that checking for summation overflow is both
|
||||
// necessary and sufficient.
|
||||
if size > isize::MAX as usize - (align - 1) {
|
||||
if size > usize::MAX - (align - 1) {
|
||||
return Err(LayoutError);
|
||||
}
|
||||
|
||||
|
|
@ -276,8 +276,8 @@ impl Layout {
|
|||
let pad = self.padding_needed_for(self.align());
|
||||
// This cannot overflow. Quoting from the invariant of Layout:
|
||||
// > `size`, when rounded up to the nearest multiple of `align`,
|
||||
// > must not overflow isize (i.e., the rounded value must be
|
||||
// > less than or equal to `isize::MAX`)
|
||||
// > must not overflow (i.e., the rounded value must be less than
|
||||
// > `usize::MAX`)
|
||||
let new_size = self.size() + pad;
|
||||
|
||||
// SAFETY: self.align is already known to be valid and new_size has been
|
||||
|
|
@ -298,13 +298,14 @@ impl Layout {
|
|||
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> {
|
||||
// This cannot overflow. Quoting from the invariant of Layout:
|
||||
// > `size`, when rounded up to the nearest multiple of `align`,
|
||||
// > must not overflow isize (i.e., the rounded value must be
|
||||
// > less than or equal to `isize::MAX`)
|
||||
// > must not overflow (i.e., the rounded value must be less than
|
||||
// > `usize::MAX`)
|
||||
let padded_size = self.size() + self.padding_needed_for(self.align());
|
||||
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError)?;
|
||||
|
||||
// The safe constructor is called here to enforce the isize size limit.
|
||||
Layout::from_size_align(alloc_size, self.align()).map(|layout| (layout, padded_size))
|
||||
// SAFETY: self.align is already known to be valid and alloc_size has been
|
||||
// padded already.
|
||||
unsafe { Ok((Layout::from_size_align_unchecked(alloc_size, self.align()), padded_size)) }
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `self` followed by
|
||||
|
|
@ -361,7 +362,6 @@ impl Layout {
|
|||
let offset = self.size().checked_add(pad).ok_or(LayoutError)?;
|
||||
let new_size = offset.checked_add(next.size()).ok_or(LayoutError)?;
|
||||
|
||||
// The safe constructor is called here to enforce the isize size limit.
|
||||
let layout = Layout::from_size_align(new_size, new_align)?;
|
||||
Ok((layout, offset))
|
||||
}
|
||||
|
|
@ -382,7 +382,6 @@ impl Layout {
|
|||
#[inline]
|
||||
pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> {
|
||||
let size = self.size().checked_mul(n).ok_or(LayoutError)?;
|
||||
// The safe constructor is called here to enforce the isize size limit.
|
||||
Layout::from_size_align(size, self.align())
|
||||
}
|
||||
|
||||
|
|
@ -396,7 +395,6 @@ impl Layout {
|
|||
#[inline]
|
||||
pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
|
||||
let new_size = self.size().checked_add(next.size()).ok_or(LayoutError)?;
|
||||
// The safe constructor is called here to enforce the isize size limit.
|
||||
Layout::from_size_align(new_size, self.align())
|
||||
}
|
||||
|
||||
|
|
@ -407,8 +405,16 @@ impl Layout {
|
|||
#[inline]
|
||||
pub fn array<T>(n: usize) -> Result<Self, LayoutError> {
|
||||
let array_size = mem::size_of::<T>().checked_mul(n).ok_or(LayoutError)?;
|
||||
// The safe constructor is called here to enforce the isize size limit.
|
||||
Layout::from_size_align(array_size, mem::align_of::<T>())
|
||||
|
||||
// SAFETY:
|
||||
// - Size: `array_size` cannot be too big because `size_of::<T>()` must
|
||||
// be a multiple of `align_of::<T>()`. Therefore, `array_size`
|
||||
// rounded up to the nearest multiple of `align_of::<T>()` is just
|
||||
// `array_size`. And `array_size` cannot be too big because it was
|
||||
// just checked by the `checked_mul()`.
|
||||
// - Alignment: `align_of::<T>()` will always give an acceptable
|
||||
// (non-zero, power of two) alignment.
|
||||
Ok(unsafe { Layout::from_size_align_unchecked(array_size, mem::align_of::<T>()) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue