@@ -172,4 +172,42 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
172172 }
173173 }
174174 }
175+
176+ fn aligned_alloc (
177+ & mut self ,
178+ align : u64 ,
179+ size : u64 ,
180+ ) -> InterpResult < ' tcx , Pointer < Option < Provenance > > > {
181+ let this = self . eval_context_mut ( ) ;
182+ // Alignment must be a power of 2, and "supported by the implementation".
183+ // We decide that "supported by the implementation" means that the
184+ // size must be a multiple of the alignment. (This restriction seems common
185+ // enough that it is stated on <https://en.cppreference.com/w/c/memory/aligned_alloc>
186+ // as a general rule, but the actual standard has no such rule.)
187+ // If any of these are violated, we have to return NULL.
188+ // All fundamental alignments must be supported.
189+ //
190+ // macOS and Illumos are buggy in that they require the alignment
191+ // to be at least the size of a pointer, so they do not support all fundamental
192+ // alignments. We do not emulate those platform bugs.
193+ //
194+ // Linux also sets errno to EINVAL, but that's non-standard behavior that we do not
195+ // emulate.
196+ // FreeBSD says some of these cases are UB but that's violating the C standard.
197+ // http://en.cppreference.com/w/cpp/memory/c/aligned_alloc
198+ // Linux: https://linux.die.net/man/3/aligned_alloc
199+ // FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=aligned_alloc&apropos=0&sektion=3&manpath=FreeBSD+9-current&format=html
200+ match size. checked_rem ( align) {
201+ Some ( 0 ) if align. is_power_of_two ( ) => {
202+ let align = align. max ( this. malloc_align ( size) . bytes ( ) ) ;
203+ let ptr = this. allocate_ptr (
204+ Size :: from_bytes ( size) ,
205+ Align :: from_bytes ( align) . unwrap ( ) ,
206+ MiriMemoryKind :: C . into ( ) ,
207+ ) ?;
208+ Ok ( ptr. into ( ) )
209+ }
210+ _ => Ok ( Pointer :: null ( ) ) ,
211+ }
212+ }
175213}
0 commit comments