Skip to content

Commit 59bf09d

Browse files
committed
Auto merge of #46117 - SimonSapin:min-align, r=alexcrichton
allocators: don’t assume MIN_ALIGN for small sizes See individual commit messages.
2 parents ca8ef26 + 43e32b5 commit 59bf09d

File tree

4 files changed

+65
-18
lines changed

4 files changed

+65
-18
lines changed

src/liballoc/tests/heap.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use alloc_system::System;
12+
use std::heap::{Heap, Alloc, Layout};
13+
14+
/// https://github.com/rust-lang/rust/issues/45955
15+
///
16+
/// Note that `#[global_allocator]` is not used,
17+
/// so `liballoc_jemalloc` is linked (on some platforms).
18+
#[test]
19+
fn alloc_system_overaligned_request() {
20+
check_overalign_requests(System)
21+
}
22+
23+
#[test]
24+
fn std_heap_overaligned_request() {
25+
check_overalign_requests(Heap)
26+
}
27+
28+
fn check_overalign_requests<T: Alloc>(mut allocator: T) {
29+
let size = 8;
30+
let align = 16; // greater than size
31+
let iterations = 100;
32+
unsafe {
33+
let pointers: Vec<_> = (0..iterations).map(|_| {
34+
allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
35+
}).collect();
36+
for &ptr in &pointers {
37+
assert_eq!((ptr as usize) % align, 0, "Got a pointer less aligned than requested")
38+
}
39+
40+
// Clean up
41+
for &ptr in &pointers {
42+
allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap())
43+
}
44+
}
45+
}

src/liballoc/tests/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#![deny(warnings)]
1212

13+
#![feature(allocator_api)]
14+
#![feature(alloc_system)]
1315
#![feature(attr_literals)]
1416
#![feature(box_syntax)]
1517
#![feature(inclusive_range_syntax)]
@@ -29,6 +31,7 @@
2931
#![feature(unboxed_closures)]
3032
#![feature(unicode)]
3133

34+
extern crate alloc_system;
3235
extern crate std_unicode;
3336
extern crate rand;
3437

@@ -39,6 +42,7 @@ mod binary_heap;
3942
mod btree;
4043
mod cow_str;
4144
mod fmt;
45+
mod heap;
4246
mod linked_list;
4347
mod slice;
4448
mod str;

src/liballoc_jemalloc/lib.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ mod contents {
7272
const MALLOCX_ZERO: c_int = 0x40;
7373

7474
// The minimum alignment guaranteed by the architecture. This value is used to
75-
// add fast paths for low alignment values. In practice, the alignment is a
76-
// constant at the call site and the branch will be optimized out.
75+
// add fast paths for low alignment values.
7776
#[cfg(all(any(target_arch = "arm",
7877
target_arch = "mips",
7978
target_arch = "powerpc")))]
@@ -92,8 +91,8 @@ mod contents {
9291
a.trailing_zeros() as c_int
9392
}
9493

95-
fn align_to_flags(align: usize) -> c_int {
96-
if align <= MIN_ALIGN {
94+
fn align_to_flags(align: usize, size: usize) -> c_int {
95+
if align <= MIN_ALIGN && align <= size {
9796
0
9897
} else {
9998
mallocx_align(align)
@@ -111,7 +110,7 @@ mod contents {
111110
pub unsafe extern fn __rde_alloc(size: usize,
112111
align: usize,
113112
err: *mut u8) -> *mut u8 {
114-
let flags = align_to_flags(align);
113+
let flags = align_to_flags(align, size);
115114
let ptr = mallocx(size as size_t, flags) as *mut u8;
116115
if ptr.is_null() {
117116
let layout = Layout::from_size_align_unchecked(size, align);
@@ -132,7 +131,7 @@ mod contents {
132131
pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
133132
size: usize,
134133
align: usize) {
135-
let flags = align_to_flags(align);
134+
let flags = align_to_flags(align, size);
136135
sdallocx(ptr as *mut c_void, size, flags);
137136
}
138137

@@ -142,7 +141,7 @@ mod contents {
142141
min: *mut usize,
143142
max: *mut usize) {
144143
let layout = &*(layout as *const Layout);
145-
let flags = align_to_flags(layout.align());
144+
let flags = align_to_flags(layout.align(), layout.size());
146145
let size = nallocx(layout.size(), flags) as usize;
147146
*min = layout.size();
148147
if size > 0 {
@@ -166,7 +165,7 @@ mod contents {
166165
return 0 as *mut u8
167166
}
168167

169-
let flags = align_to_flags(new_align);
168+
let flags = align_to_flags(new_align, new_size);
170169
let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
171170
if ptr.is_null() {
172171
let layout = Layout::from_size_align_unchecked(new_size, new_align);
@@ -181,10 +180,10 @@ mod contents {
181180
pub unsafe extern fn __rde_alloc_zeroed(size: usize,
182181
align: usize,
183182
err: *mut u8) -> *mut u8 {
184-
let ptr = if align <= MIN_ALIGN {
183+
let ptr = if align <= MIN_ALIGN && align <= size {
185184
calloc(size as size_t, 1) as *mut u8
186185
} else {
187-
let flags = align_to_flags(align) | MALLOCX_ZERO;
186+
let flags = align_to_flags(align, size) | MALLOCX_ZERO;
188187
mallocx(size as size_t, flags) as *mut u8
189188
};
190189
if ptr.is_null() {
@@ -203,7 +202,7 @@ mod contents {
203202
err: *mut u8) -> *mut u8 {
204203
let p = __rde_alloc(size, align, err);
205204
if !p.is_null() {
206-
let flags = align_to_flags(align);
205+
let flags = align_to_flags(align, size);
207206
*excess = nallocx(size, flags) as usize;
208207
}
209208
return p
@@ -220,7 +219,7 @@ mod contents {
220219
err: *mut u8) -> *mut u8 {
221220
let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err);
222221
if !p.is_null() {
223-
let flags = align_to_flags(new_align);
222+
let flags = align_to_flags(new_align, new_size);
224223
*excess = nallocx(new_size, flags) as usize;
225224
}
226225
p
@@ -244,7 +243,7 @@ mod contents {
244243
new_size: usize,
245244
new_align: usize) -> u8 {
246245
if old_align == new_align {
247-
let flags = align_to_flags(new_align);
246+
let flags = align_to_flags(new_align, new_size);
248247
(xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8
249248
} else {
250249
0

src/liballoc_system/lib.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@
2525
#![rustc_alloc_kind = "lib"]
2626

2727
// The minimum alignment guaranteed by the architecture. This value is used to
28-
// add fast paths for low alignment values. In practice, the alignment is a
29-
// constant at the call site and the branch will be optimized out.
28+
// add fast paths for low alignment values.
3029
#[cfg(all(any(target_arch = "x86",
3130
target_arch = "arm",
3231
target_arch = "mips",
@@ -132,7 +131,7 @@ mod platform {
132131
unsafe impl<'a> Alloc for &'a System {
133132
#[inline]
134133
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
135-
let ptr = if layout.align() <= MIN_ALIGN {
134+
let ptr = if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
136135
libc::malloc(layout.size()) as *mut u8
137136
} else {
138137
aligned_malloc(&layout)
@@ -148,7 +147,7 @@ mod platform {
148147
unsafe fn alloc_zeroed(&mut self, layout: Layout)
149148
-> Result<*mut u8, AllocErr>
150149
{
151-
if layout.align() <= MIN_ALIGN {
150+
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
152151
let ptr = libc::calloc(layout.size(), 1) as *mut u8;
153152
if !ptr.is_null() {
154153
Ok(ptr)
@@ -180,7 +179,7 @@ mod platform {
180179
})
181180
}
182181

183-
if new_layout.align() <= MIN_ALIGN {
182+
if new_layout.align() <= MIN_ALIGN && new_layout.align() <= new_layout.size(){
184183
let ptr = libc::realloc(ptr as *mut libc::c_void, new_layout.size());
185184
if !ptr.is_null() {
186185
Ok(ptr as *mut u8)

0 commit comments

Comments
 (0)