@@ -3,6 +3,7 @@ use std::str;
33
44use rustc_middle:: ty:: layout:: LayoutOf ;
55use rustc_span:: Symbol ;
6+ use rustc_target:: abi:: Size ;
67use rustc_target:: spec:: abi:: Abi ;
78
89use crate :: shims:: alloc:: EvalContextExt as _;
@@ -303,36 +304,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
303304 let align = this. read_target_usize ( align) ?;
304305 let size = this. read_target_usize ( size) ?;
305306
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 .
311312 //
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.
312319 // http://en.cppreference.com/w/cpp/memory/c/aligned_alloc
313320 // Linux: https://linux.die.net/man/3/aligned_alloc
314321 // FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=aligned_alloc&apropos=0&sektion=3&manpath=FreeBSD+9-current&format=html
315322 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) ;
326325 let ptr = this. allocate_ptr (
327326 Size :: from_bytes ( size) ,
328327 align,
329328 MiriMemoryKind :: C . into ( ) ,
330329 ) ?;
331330 this. write_pointer ( ptr, dest) ?;
332- }
333331 } ,
334332 _ => {
335- let _ = this. set_last_error ( this. eval_libc ( "EINVAL" ) ) ;
336333 this. write_null ( dest) ?;
337334 }
338335 }
0 commit comments