From bdd24617a48eb3860609a8590a05793ad1f2a312 Mon Sep 17 00:00:00 2001 From: JustForFun88 Date: Sun, 18 Sep 2022 10:35:23 +0500 Subject: [PATCH 1/4] Check that layout size fits in isize in Layout --- src/map.rs | 17 +++++++++++------ src/raw/mod.rs | 15 ++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/map.rs b/src/map.rs index edda9b7a50..42d15508e7 100644 --- a/src/map.rs +++ b/src/map.rs @@ -8044,25 +8044,30 @@ mod test_map { fn test_try_reserve() { use crate::TryReserveError::{AllocError, CapacityOverflow}; - const MAX_USIZE: usize = usize::MAX; + const MAX_ISIZE: usize = isize::MAX as usize; let mut empty_bytes: HashMap = HashMap::new(); - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { + if let Err(CapacityOverflow) = empty_bytes.try_reserve(usize::MAX) { } else { panic!("usize::MAX should trigger an overflow!"); } - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE / 16) { + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_ISIZE) { + } else { + panic!("usize::MAX should trigger an overflow!"); + } + + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 16) { } else { // This may succeed if there is enough free memory. Attempt to // allocate a few more hashmaps to ensure the allocation will fail. let mut empty_bytes2: HashMap = HashMap::new(); - let _ = empty_bytes2.try_reserve(MAX_USIZE / 16); + let _ = empty_bytes2.try_reserve(MAX_ISIZE / 16); let mut empty_bytes3: HashMap = HashMap::new(); - let _ = empty_bytes3.try_reserve(MAX_USIZE / 16); + let _ = empty_bytes3.try_reserve(MAX_ISIZE / 16); let mut empty_bytes4: HashMap = HashMap::new(); - if let Err(AllocError { .. }) = empty_bytes4.try_reserve(MAX_USIZE / 16) { + if let Err(AllocError { .. }) = empty_bytes4.try_reserve(MAX_ISIZE / 16) { } else { panic!("usize::MAX / 8 should trigger an OOM!"); } diff --git a/src/raw/mod.rs b/src/raw/mod.rs index 2f3249e25d..daba4f8c85 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -248,6 +248,12 @@ impl TableLayout { size.checked_mul(buckets)?.checked_add(ctrl_align - 1)? & !(ctrl_align - 1); let len = ctrl_offset.checked_add(buckets + Group::WIDTH)?; + // We need an additional check to ensure that the allocation doesn't + // exceed `isize::MAX` (https://github.com/rust-lang/rust/pull/95295). + if len > isize::MAX as usize - (ctrl_align - 1) { + return None; + } + Some(( unsafe { Layout::from_size_align_unchecked(len, ctrl_align) }, ctrl_offset, @@ -1078,15 +1084,6 @@ impl RawTableInner { None => return Err(fallibility.capacity_overflow()), }; - // We need an additional check to ensure that the allocation doesn't - // exceed `isize::MAX`. We can skip this check on 64-bit systems since - // such allocations will never succeed anyways. - // - // This mirrors what Vec does in the standard library. - if mem::size_of::() < 8 && layout.size() > isize::MAX as usize { - return Err(fallibility.capacity_overflow()); - } - let ptr: NonNull = match do_alloc(&alloc, layout) { Ok(block) => block.cast(), Err(_) => return Err(fallibility.alloc_err(layout)), From cd4c8379add5c0d1b49a026428073d6b08924228 Mon Sep 17 00:00:00 2001 From: JustForFun88 Date: Sun, 18 Sep 2022 10:56:21 +0500 Subject: [PATCH 2/4] make corrections to the test --- src/map.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/map.rs b/src/map.rs index 42d15508e7..5cf8f3e3b2 100644 --- a/src/map.rs +++ b/src/map.rs @@ -8045,31 +8045,35 @@ mod test_map { use crate::TryReserveError::{AllocError, CapacityOverflow}; const MAX_ISIZE: usize = isize::MAX as usize; + const GROUP_WIDTH: usize = 128; let mut empty_bytes: HashMap = HashMap::new(); if let Err(CapacityOverflow) = empty_bytes.try_reserve(usize::MAX) { } else { - panic!("usize::MAX should trigger an overflow!"); + panic!("isize::MAX should trigger an overflow!"); } if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_ISIZE) { } else { - panic!("usize::MAX should trigger an overflow!"); + panic!("isize::MAX should trigger an overflow!"); } - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 16) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 24 - (GROUP_WIDTH + 1)) + { } else { // This may succeed if there is enough free memory. Attempt to // allocate a few more hashmaps to ensure the allocation will fail. let mut empty_bytes2: HashMap = HashMap::new(); - let _ = empty_bytes2.try_reserve(MAX_ISIZE / 16); + let _ = empty_bytes2.try_reserve(MAX_ISIZE / 24 - (GROUP_WIDTH + 1)); let mut empty_bytes3: HashMap = HashMap::new(); - let _ = empty_bytes3.try_reserve(MAX_ISIZE / 16); + let _ = empty_bytes3.try_reserve(MAX_ISIZE / 24 - (GROUP_WIDTH + 1)); let mut empty_bytes4: HashMap = HashMap::new(); - if let Err(AllocError { .. }) = empty_bytes4.try_reserve(MAX_ISIZE / 16) { + if let Err(AllocError { .. }) = + empty_bytes4.try_reserve(MAX_ISIZE / 24 - (GROUP_WIDTH + 1)) + { } else { - panic!("usize::MAX / 8 should trigger an OOM!"); + panic!("isize::MAX / 24 should trigger an OOM!"); } } } From 3514c060162ba81a4aa6cf5411b9fb45adaef4ed Mon Sep 17 00:00:00 2001 From: JustForFun88 Date: Sun, 18 Sep 2022 13:25:29 +0500 Subject: [PATCH 3/4] third attempt --- src/map.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/map.rs b/src/map.rs index 5cf8f3e3b2..d6c42ecaa7 100644 --- a/src/map.rs +++ b/src/map.rs @@ -8045,13 +8045,12 @@ mod test_map { use crate::TryReserveError::{AllocError, CapacityOverflow}; const MAX_ISIZE: usize = isize::MAX as usize; - const GROUP_WIDTH: usize = 128; let mut empty_bytes: HashMap = HashMap::new(); if let Err(CapacityOverflow) = empty_bytes.try_reserve(usize::MAX) { } else { - panic!("isize::MAX should trigger an overflow!"); + panic!("usize::MAX should trigger an overflow!"); } if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_ISIZE) { @@ -8059,21 +8058,21 @@ mod test_map { panic!("isize::MAX should trigger an overflow!"); } - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 24 - (GROUP_WIDTH + 1)) + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 5) { } else { // This may succeed if there is enough free memory. Attempt to // allocate a few more hashmaps to ensure the allocation will fail. let mut empty_bytes2: HashMap = HashMap::new(); - let _ = empty_bytes2.try_reserve(MAX_ISIZE / 24 - (GROUP_WIDTH + 1)); + let _ = empty_bytes2.try_reserve(MAX_ISIZE / 5); let mut empty_bytes3: HashMap = HashMap::new(); - let _ = empty_bytes3.try_reserve(MAX_ISIZE / 24 - (GROUP_WIDTH + 1)); + let _ = empty_bytes3.try_reserve(MAX_ISIZE / 5); let mut empty_bytes4: HashMap = HashMap::new(); if let Err(AllocError { .. }) = - empty_bytes4.try_reserve(MAX_ISIZE / 24 - (GROUP_WIDTH + 1)) + empty_bytes4.try_reserve(MAX_ISIZE / 5) { } else { - panic!("isize::MAX / 24 should trigger an OOM!"); + panic!("isize::MAX / 5 should trigger an OOM!"); } } } From ec164bf1dda7287864a84dca797122cc91dbb5c5 Mon Sep 17 00:00:00 2001 From: JustForFun88 Date: Sun, 18 Sep 2022 13:27:10 +0500 Subject: [PATCH 4/4] run fmt --- src/map.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/map.rs b/src/map.rs index d6c42ecaa7..5e039e2392 100644 --- a/src/map.rs +++ b/src/map.rs @@ -8058,8 +8058,7 @@ mod test_map { panic!("isize::MAX should trigger an overflow!"); } - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 5) - { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 5) { } else { // This may succeed if there is enough free memory. Attempt to // allocate a few more hashmaps to ensure the allocation will fail. @@ -8068,9 +8067,7 @@ mod test_map { let mut empty_bytes3: HashMap = HashMap::new(); let _ = empty_bytes3.try_reserve(MAX_ISIZE / 5); let mut empty_bytes4: HashMap = HashMap::new(); - if let Err(AllocError { .. }) = - empty_bytes4.try_reserve(MAX_ISIZE / 5) - { + if let Err(AllocError { .. }) = empty_bytes4.try_reserve(MAX_ISIZE / 5) { } else { panic!("isize::MAX / 5 should trigger an OOM!"); }