diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 6d47c2ff28fbf..1f36bc4fbcea7 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -171,6 +171,8 @@ mod imp { #[cfg(windows)] #[allow(bad_style)] mod imp { + use core::cmp::min; + use core::ptr::copy_nonoverlapping; use MIN_ALIGN; type LPVOID = *mut u8; @@ -225,19 +227,16 @@ mod imp { allocate_with_flags(size, align, HEAP_ZERO_MEMORY) } - pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 { + pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { if align <= MIN_ALIGN { HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8 } else { - let header = get_header(ptr); - let new = HeapReAlloc(GetProcessHeap(), - 0, - header.0 as LPVOID, - (size + align) as SIZE_T) as *mut u8; - if new.is_null() { - return new; + let new = allocate(size, align); + if !new.is_null() { + copy_nonoverlapping(ptr, new, min(size, old_size)); + deallocate(ptr, old_size, align); } - align_ptr(new, align) + new } } @@ -246,15 +245,19 @@ mod imp { size: usize, align: usize) -> usize { - if align <= MIN_ALIGN { - let new = HeapReAlloc(GetProcessHeap(), - HEAP_REALLOC_IN_PLACE_ONLY, - ptr as LPVOID, - size as SIZE_T) as *mut u8; - if new.is_null() { old_size } else { size } + let new = if align <= MIN_ALIGN { + HeapReAlloc(GetProcessHeap(), + HEAP_REALLOC_IN_PLACE_ONLY, + ptr as LPVOID, + size as SIZE_T) as *mut u8 } else { - old_size - } + let header = get_header(ptr); + HeapReAlloc(GetProcessHeap(), + HEAP_REALLOC_IN_PLACE_ONLY, + header.0 as LPVOID, + size + align as SIZE_T) as *mut u8 + }; + if new.is_null() { old_size } else { size } } pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) { diff --git a/src/libcollections/tests/lib.rs b/src/libcollections/tests/lib.rs index 6ad5781c5d5fd..66918e0f5f8ae 100644 --- a/src/libcollections/tests/lib.rs +++ b/src/libcollections/tests/lib.rs @@ -10,6 +10,7 @@ #![deny(warnings)] +#![feature(attr_literals)] #![feature(box_syntax)] #![feature(inclusive_range_syntax)] #![feature(collection_placement)] @@ -19,6 +20,7 @@ #![feature(pattern)] #![feature(placement_in_syntax)] #![feature(rand)] +#![feature(repr_align)] #![feature(slice_rotate)] #![feature(splice)] #![feature(step_by)] diff --git a/src/libcollections/tests/vec.rs b/src/libcollections/tests/vec.rs index 29f18274962fe..fdf453b39cf5d 100644 --- a/src/libcollections/tests/vec.rs +++ b/src/libcollections/tests/vec.rs @@ -781,3 +781,18 @@ fn from_into_inner() { assert_eq!(vec, [2, 3]); assert!(ptr != vec.as_ptr()); } + +#[test] +fn overaligned_allocations() { + #[repr(align(256))] + struct Foo(usize); + let mut v = vec![Foo(273)]; + for i in 0..0x1000 { + v.reserve_exact(i); + assert!(v[0].0 == 273); + assert!(v.as_ptr() as usize & 0xff == 0); + v.shrink_to_fit(); + assert!(v[0].0 == 273); + assert!(v.as_ptr() as usize & 0xff == 0); + } +}