From c93760da9dbe0c3117c678c977d48cd56a356f8d Mon Sep 17 00:00:00 2001 From: bcoopers Date: Sun, 29 Mar 2015 16:07:24 -0400 Subject: [PATCH 1/5] Vector can currently panic when pushing an element or reserving space for only half of the maximum size available on the architecture. This allows vectors to keep expanding with those two methods until the amount of bytes exceeds usize. --- src/libcollections/vec.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 14bc7f65e09..51ad64331e2 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -306,9 +306,12 @@ impl Vec { pub fn reserve(&mut self, additional: usize) { if self.cap - self.len < additional { let err_msg = "Vec::reserve: `usize` overflow"; - let new_cap = self.len.checked_add(additional).expect(err_msg) - .checked_next_power_of_two().expect(err_msg); - self.grow_capacity(new_cap); + + let new_min_cap = self.len.checked_add(additional).expect(err_msg); + match new_min_cap.checked_next_power_of_two() { + None => self.grow_capacity(new_min_cap), + Some(x) => self.grow_capacity(x), + } } } @@ -639,8 +642,11 @@ impl Vec { #[inline(never)] fn resize(vec: &mut Vec) { let old_size = vec.cap * mem::size_of::(); - let size = max(old_size, 2 * mem::size_of::()) * 2; - if old_size > size { panic!("capacity overflow") } + if old_size == std::usize::MAX { panic!("capacity overflow") } + let mut size = max(old_size, 2 * mem::size_of::()) * 2; + if old_size > size { + size = std::usize::MAX; + } unsafe { let ptr = alloc_or_realloc(*vec.ptr, old_size, size); if ptr.is_null() { ::alloc::oom() } From 1caf260edb561f8fa20f5df021a4bfdf9d64195f Mon Sep 17 00:00:00 2001 From: bcoopers Date: Sun, 29 Mar 2015 16:12:01 -0400 Subject: [PATCH 2/5] change std::usize to usize --- src/libcollections/vec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 51ad64331e2..6a6d55772f7 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -642,10 +642,10 @@ impl Vec { #[inline(never)] fn resize(vec: &mut Vec) { let old_size = vec.cap * mem::size_of::(); - if old_size == std::usize::MAX { panic!("capacity overflow") } + if old_size == usize::MAX { panic!("capacity overflow") } let mut size = max(old_size, 2 * mem::size_of::()) * 2; if old_size > size { - size = std::usize::MAX; + size = usize::MAX; } unsafe { let ptr = alloc_or_realloc(*vec.ptr, old_size, size); From 4f06cedd0d83e0f6418ab681f6174c2b32e7aca0 Mon Sep 17 00:00:00 2001 From: bcoopers Date: Sun, 29 Mar 2015 19:48:58 -0400 Subject: [PATCH 3/5] If doubling the vector in reserve() brings you over usize::MAX, try to get capacity for usize::MAX --- src/libcollections/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 6a6d55772f7..aff26587de3 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -309,7 +309,7 @@ impl Vec { let new_min_cap = self.len.checked_add(additional).expect(err_msg); match new_min_cap.checked_next_power_of_two() { - None => self.grow_capacity(new_min_cap), + None => self.grow_capacity(usize::MAX), Some(x) => self.grow_capacity(x), } } From f8493d0660d5ad92a0c244cd0fed0d72b9630ebb Mon Sep 17 00:00:00 2001 From: bcoopers Date: Mon, 30 Mar 2015 10:35:04 -0400 Subject: [PATCH 4/5] Change max size to isize --- src/libcollections/vec.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index aff26587de3..0a73679a7e6 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -65,10 +65,14 @@ use core::ops; use core::ptr; use core::ptr::Unique; use core::slice; +use core::isize; use core::usize; use borrow::{Cow, IntoCow}; +// FIXME- fix places which assume the max vector allowed has memory usize::MAX. +static MAX_MEMORY_SIZE: usize = isize::MAX as usize; + /// A growable list type, written `Vec` but pronounced 'vector.' /// /// # Examples @@ -305,13 +309,15 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve(&mut self, additional: usize) { if self.cap - self.len < additional { - let err_msg = "Vec::reserve: `usize` overflow"; + let err_msg = "Vec::reserve: `isize` overflow"; let new_min_cap = self.len.checked_add(additional).expect(err_msg); - match new_min_cap.checked_next_power_of_two() { - None => self.grow_capacity(usize::MAX), - Some(x) => self.grow_capacity(x), - } + if new_min_cap > MAX_MEMORY_SIZE { panic!(err_msg) } + self.grow_capacity(match new_min_cap.checked_next_power_of_two() { + Some(x) if x > MAX_MEMORY_SIZE => MAX_MEMORY_SIZE, + None => MAX_MEMORY_SIZE, + Some(x) => x, + }); } } @@ -642,10 +648,10 @@ impl Vec { #[inline(never)] fn resize(vec: &mut Vec) { let old_size = vec.cap * mem::size_of::(); - if old_size == usize::MAX { panic!("capacity overflow") } + if old_size >= MAX_MEMORY_SIZE { panic!("capacity overflow") } let mut size = max(old_size, 2 * mem::size_of::()) * 2; - if old_size > size { - size = usize::MAX; + if old_size > size || size > MAX_MEMORY_SIZE { + size = MAX_MEMORY_SIZE; } unsafe { let ptr = alloc_or_realloc(*vec.ptr, old_size, size); From ac617b628899282f714fd6a91471d1f0b1cc3217 Mon Sep 17 00:00:00 2001 From: bcoopers Date: Sun, 12 Apr 2015 13:47:10 -0400 Subject: [PATCH 5/5] The panic! macro can't be called with a variable declared with "let" when building on stage0. So change the error message to a static const. --- src/libcollections/vec.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 0a73679a7e6..da1ff2901d0 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -309,10 +309,10 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve(&mut self, additional: usize) { if self.cap - self.len < additional { - let err_msg = "Vec::reserve: `isize` overflow"; + const ERR_MSG: &'static str = "Vec::reserve: `isize` overflow"; - let new_min_cap = self.len.checked_add(additional).expect(err_msg); - if new_min_cap > MAX_MEMORY_SIZE { panic!(err_msg) } + let new_min_cap = self.len.checked_add(additional).expect(ERR_MSG); + if new_min_cap > MAX_MEMORY_SIZE { panic!(ERR_MSG) } self.grow_capacity(match new_min_cap.checked_next_power_of_two() { Some(x) if x > MAX_MEMORY_SIZE => MAX_MEMORY_SIZE, None => MAX_MEMORY_SIZE,