about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorblake2-ppc <blake2-ppc>2013-09-12 05:00:25 +0200
committerblake2-ppc <blake2-ppc>2013-09-17 02:48:00 +0200
commite211888407db32fcec53f4fa9eb84acdbdf59f87 (patch)
tree74b7b8aae3027586895cb1717c9a93eb751fbcd0 /src/libstd
parent6e538edea2557018c3c8eae41aacf6cdf6370a4d (diff)
downloadrust-e211888407db32fcec53f4fa9eb84acdbdf59f87.tar.gz
rust-e211888407db32fcec53f4fa9eb84acdbdf59f87.zip
std::at_vec: Fix segfault on overflow when resizing ~[@T]
Easy to reproduce:

    let mut v = ~[@1];
    v.resize(-1);  // success a.k.a silent failure
    v.push(@2); // segfault
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/at_vec.rs13
-rw-r--r--src/libstd/vec.rs8
2 files changed, 16 insertions, 5 deletions
diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs
index ce8e90e1a43..42f511f722d 100644
--- a/src/libstd/at_vec.rs
+++ b/src/libstd/at_vec.rs
@@ -230,13 +230,16 @@ pub mod raw {
     // Implementation detail. Shouldn't be public
     #[allow(missing_doc)]
     pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut Box<Vec<()>>, n: uint) {
-
+        // check for `uint` overflow
         unsafe {
-            let size_in_bytes = n * (*ty).size;
-            if size_in_bytes > (**ptr).data.alloc {
-                let total_size = size_in_bytes + sys::size_of::<Vec<()>>();
+            if n > (**ptr).data.alloc / (*ty).size {
+                let alloc = n * (*ty).size;
+                let total_size = alloc + sys::size_of::<Vec<()>>();
+                if alloc / (*ty).size != n || total_size < alloc {
+                    fail!("vector size is too large: %u", n);
+                }
                 (*ptr) = local_realloc(*ptr as *(), total_size) as *mut Box<Vec<()>>;
-                (**ptr).data.alloc = size_in_bytes;
+                (**ptr).data.alloc = alloc;
             }
         }
 
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index b7274d58e1b..9fc0eaf72b1 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -3660,6 +3660,14 @@ mod tests {
     }
 
     #[test]
+    #[should_fail]
+    fn test_overflow_does_not_cause_segfault_managed() {
+        let mut v = ~[@1];
+        v.reserve(-1);
+        v.push(@2);
+    }
+
+    #[test]
     fn test_mut_split() {
         let mut values = [1u8,2,3,4,5];
         {