Skip to content

Commit fd99aee

Browse files
committed
Don’t assume MIN_ALIGN for small sizes
Same as rust-lang/rust#46117 See also discussion of jemalloc’s behavior at jemalloc/jemalloc#1072
1 parent 5043bb2 commit fd99aee

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

src/lib.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ fn mallocx_align(a: usize) -> c_int {
4747
a.trailing_zeros() as c_int
4848
}
4949

50-
fn align_to_flags(align: usize) -> c_int {
51-
if align <= MIN_ALIGN {
50+
fn align_to_flags(align: usize, size: usize) -> c_int {
51+
if align <= MIN_ALIGN && align <= size {
5252
0
5353
} else {
5454
mallocx_align(align)
@@ -131,7 +131,7 @@ unsafe impl Alloc for Jemalloc {
131131
unsafe impl<'a> Alloc for &'a Jemalloc {
132132
#[inline]
133133
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
134-
let flags = align_to_flags(layout.align());
134+
let flags = align_to_flags(layout.align(), layout.size());
135135
let ptr = ffi::mallocx(layout.size(), flags);
136136
if ptr.is_null() {
137137
Err(AllocErr::Exhausted { request: layout })
@@ -144,10 +144,10 @@ unsafe impl<'a> Alloc for &'a Jemalloc {
144144
unsafe fn alloc_zeroed(&mut self, layout: Layout)
145145
-> Result<*mut u8, AllocErr>
146146
{
147-
let ptr = if layout.align() <= MIN_ALIGN {
147+
let ptr = if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
148148
ffi::calloc(1, layout.size())
149149
} else {
150-
let flags = align_to_flags(layout.align()) | ffi::MALLOCX_ZERO;
150+
let flags = align_to_flags(layout.align(), layout.size()) | ffi::MALLOCX_ZERO;
151151
ffi::mallocx(layout.size(), flags)
152152
};
153153
if ptr.is_null() {
@@ -159,7 +159,7 @@ unsafe impl<'a> Alloc for &'a Jemalloc {
159159

160160
#[inline]
161161
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
162-
let flags = align_to_flags(layout.align());
162+
let flags = align_to_flags(layout.align(), layout.size());
163163
ffi::sdallocx(ptr as *mut c_void, layout.size(), flags)
164164
}
165165

@@ -171,7 +171,7 @@ unsafe impl<'a> Alloc for &'a Jemalloc {
171171
if old_layout.align() != new_layout.align() {
172172
return Err(AllocErr::Unsupported { details: "cannot change align" })
173173
}
174-
let flags = align_to_flags(new_layout.align());
174+
let flags = align_to_flags(new_layout.align(), new_layout.size());
175175
let ptr = ffi::rallocx(ptr as *mut c_void, new_layout.size(), flags);
176176
if ptr.is_null() {
177177
Err(AllocErr::Exhausted { request: new_layout })
@@ -186,7 +186,7 @@ unsafe impl<'a> Alloc for &'a Jemalloc {
186186

187187
#[inline]
188188
fn usable_size(&self, layout: &Layout) -> (usize, usize) {
189-
let flags = align_to_flags(layout.align());
189+
let flags = align_to_flags(layout.align(), layout.size());
190190
unsafe {
191191
let max = ffi::nallocx(layout.size(), flags);
192192
(layout.size(), max)
@@ -209,7 +209,7 @@ unsafe impl<'a> Alloc for &'a Jemalloc {
209209
if old_layout.align() != new_layout.align() {
210210
return Err(CannotReallocInPlace)
211211
}
212-
let flags = align_to_flags(new_layout.align());
212+
let flags = align_to_flags(new_layout.align(), new_layout.size());
213213
let size = ffi::xallocx(ptr as *mut c_void, new_layout.size(), 0, flags);
214214
if size >= new_layout.size() {
215215
Err(CannotReallocInPlace)

tests/smoke.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
#![feature(global_allocator)]
1+
#![feature(global_allocator, allocator_api)]
22

33
extern crate jemallocator;
44

55
use jemallocator::Jemalloc;
6+
use std::heap::{Alloc, Layout};
67

78
#[global_allocator]
89
static A: Jemalloc = Jemalloc;
@@ -12,3 +13,24 @@ fn smoke() {
1213
let mut a = Vec::new();
1314
a.push(3);
1415
}
16+
17+
/// https://github.com/rust-lang/rust/issues/45955
18+
#[test]
19+
fn overaligned() {
20+
let size = 8;
21+
let align = 16; // greater than size
22+
let iterations = 100;
23+
unsafe {
24+
let pointers: Vec<_> = (0..iterations).map(|_| {
25+
Jemalloc.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
26+
}).collect();
27+
for &ptr in &pointers {
28+
assert_eq!((ptr as usize) % align, 0, "Got a pointer less aligned than requested")
29+
}
30+
31+
// Clean up
32+
for &ptr in &pointers {
33+
Jemalloc.dealloc(ptr, Layout::from_size_align(size, align).unwrap())
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)