@@ -3,6 +3,7 @@ use std::str;
3
3
4
4
use rustc_middle:: ty:: layout:: LayoutOf ;
5
5
use rustc_span:: Symbol ;
6
+ use rustc_target:: abi:: Size ;
6
7
use rustc_target:: spec:: abi:: Abi ;
7
8
8
9
use crate :: shims:: alloc:: EvalContextExt as _;
@@ -303,36 +304,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
303
304
let align = this. read_target_usize ( align) ?;
304
305
let size = this. read_target_usize ( size) ?;
305
306
306
- // The size must be a power of the alignment.
307
- // The specs says nothing about error handling other than null
308
- // pointer but aligned_alloc Linux/macOs implementations set EINVAL. Note that
309
- // on FreeBSD setting a size not being a power of alignment is UB but we do not
310
- // want it .
307
+ // The size must be a multiple of the alignment.
308
+ // Alignment must be a power of 2, and "supported by the implementation".
309
+ // If any of these are violated, we have to return NULL.
310
+ // All fundamental alignments must be supported.
311
+ // We decide that our implementation supports all alignments .
311
312
//
313
+ // macOS and Illumos are buggy in that they require the alignment
314
+ // to be at least the size of a pointer. We do not emulate those platform bugs.
315
+ //
316
+ // Linux also sets errno to EINVAL, but that's non-standard behavior that we do not
317
+ // emulate/
318
+ // FreeBSD says some of these cases are UB but that's violating the C standard.
312
319
// http://en.cppreference.com/w/cpp/memory/c/aligned_alloc
313
320
// Linux: https://linux.die.net/man/3/aligned_alloc
314
321
// FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=aligned_alloc&apropos=0&sektion=3&manpath=FreeBSD+9-current&format=html
315
322
match size. checked_rem ( align) {
316
- Some ( 0 ) => {
317
- if !align. is_power_of_two ( ) {
318
- let _ = this. set_last_error ( this. eval_libc ( "EINVAL" ) ) ;
319
- this. write_null ( dest) ?;
320
- } else {
321
- let mut align = Align :: from_bytes ( align) . unwrap ( ) ;
322
- let min_align = this. malloc_align ( size) ;
323
- if align < min_align {
324
- align = min_align;
325
- }
323
+ Some ( 0 ) if align. is_power_of_two ( ) => {
324
+ let align = this. min_align ( align, size) ;
326
325
let ptr = this. allocate_ptr (
327
326
Size :: from_bytes ( size) ,
328
327
align,
329
328
MiriMemoryKind :: C . into ( ) ,
330
329
) ?;
331
330
this. write_pointer ( ptr, dest) ?;
332
- }
333
331
} ,
334
332
_ => {
335
- let _ = this. set_last_error ( this. eval_libc ( "EINVAL" ) ) ;
336
333
this. write_null ( dest) ?;
337
334
}
338
335
}
0 commit comments