1919use std:: collections:: VecDeque ;
2020use std:: ptr;
2121
22- use rustc:: ty:: { self , Instance , query:: TyCtxtAt } ;
22+ use rustc:: ty:: { self , Instance , ParamEnv , query:: TyCtxtAt } ;
2323use rustc:: ty:: layout:: { self , Align , TargetDataLayout , Size , HasDataLayout } ;
2424use rustc:: mir:: interpret:: { Pointer , AllocId , Allocation , ConstValue , GlobalId ,
2525 EvalResult , Scalar , EvalErrorKind , AllocType , PointerArithmetic ,
@@ -235,7 +235,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
235235 // Check non-NULL/Undef, extract offset
236236 let ( offset, alloc_align) = match ptr {
237237 Scalar :: Ptr ( ptr) => {
238- let ( size, align) = self . get_size_and_align ( ptr. alloc_id ) ? ;
238+ let ( size, align) = self . get_size_and_align ( ptr. alloc_id ) ;
239239 // check this is not NULL -- which we can ensure only if this is in-bounds
240240 // of some (potentially dead) allocation.
241241 if ptr. offset > size {
@@ -284,7 +284,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
284284 /// If you want to check bounds before doing a memory access, be sure to
285285 /// check the pointer one past the end of your access, then everything will
286286 /// work out exactly.
287- pub fn check_bounds ( & self , ptr : Pointer , access : bool ) -> EvalResult < ' tcx > {
287+ pub fn check_bounds_ptr ( & self , ptr : Pointer , access : bool ) -> EvalResult < ' tcx > {
288288 let alloc = self . get ( ptr. alloc_id ) ?;
289289 let allocation_size = alloc. bytes . len ( ) as u64 ;
290290 if ptr. offset . bytes ( ) > allocation_size {
@@ -296,6 +296,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
296296 }
297297 Ok ( ( ) )
298298 }
299+
300+ /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
301+ #[ inline( always) ]
302+ pub fn check_bounds ( & self , ptr : Pointer , size : Size , access : bool ) -> EvalResult < ' tcx > {
303+ // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
304+ self . check_bounds_ptr ( ptr. offset ( size, & * self ) ?, access)
305+ }
299306}
300307
301308/// Allocation accessors
@@ -352,19 +359,28 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
352359 }
353360 }
354361
355- pub fn get_size_and_align ( & self , id : AllocId ) -> EvalResult < ' tcx , ( Size , Align ) > {
356- Ok ( match self . get ( id) {
357- Ok ( alloc) => ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ,
358- Err ( err) => match err. kind {
359- EvalErrorKind :: DanglingPointerDeref =>
360- // This should be in the dead allocation map
361- * self . dead_alloc_map . get ( & id) . expect (
362- "allocation missing in dead_alloc_map"
363- ) ,
364- // E.g. a function ptr allocation
365- _ => return Err ( err)
362+ pub fn get_size_and_align ( & self , id : AllocId ) -> ( Size , Align ) {
363+ if let Ok ( alloc) = self . get ( id) {
364+ return ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ;
365+ }
366+ // Could also be a fn ptr or extern static
367+ match self . tcx . alloc_map . lock ( ) . get ( id) {
368+ Some ( AllocType :: Function ( ..) ) => ( Size :: ZERO , Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ) ,
369+ Some ( AllocType :: Static ( did) ) => {
370+ // The only way `get` couldnÄt have worked here is if this is an extern static
371+ assert ! ( self . tcx. is_foreign_item( did) ) ;
372+ // Use size and align of the type
373+ let ty = self . tcx . type_of ( did) ;
374+ let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
375+ ( layout. size , layout. align )
366376 }
367- } )
377+ _ => {
378+ // Must be a deallocated pointer
379+ * self . dead_alloc_map . get ( & id) . expect (
380+ "allocation missing in dead_alloc_map"
381+ )
382+ }
383+ }
368384 }
369385
370386 pub fn get_mut (
@@ -524,8 +540,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
524540 ) -> EvalResult < ' tcx , & [ u8 ] > {
525541 assert_ne ! ( size. bytes( ) , 0 , "0-sized accesses should never even get a `Pointer`" ) ;
526542 self . check_align ( ptr. into ( ) , align) ?;
527- // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
528- self . check_bounds ( ptr. offset ( size, & * self ) ?, true ) ?;
543+ self . check_bounds ( ptr, size, true ) ?;
529544
530545 if check_defined_and_ptr {
531546 self . check_defined ( ptr, size) ?;
@@ -569,8 +584,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
569584 ) -> EvalResult < ' tcx , & mut [ u8 ] > {
570585 assert_ne ! ( size. bytes( ) , 0 , "0-sized accesses should never even get a `Pointer`" ) ;
571586 self . check_align ( ptr. into ( ) , align) ?;
572- // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
573- self . check_bounds ( ptr. offset ( size, & self ) ?, true ) ?;
587+ self . check_bounds ( ptr, size, true ) ?;
574588
575589 self . mark_definedness ( ptr, size, true ) ?;
576590 self . clear_relocations ( ptr, size) ?;
0 commit comments