@@ -329,6 +329,8 @@ struct VisitorState {
329329 persistent_flags : PersistentStateFlags ,
330330 /// Flags describing both the immediate and overall context in which the current mir::Ty is
331331 ephemeral_flags : EphemeralStateFlags ,
332+ /// Type recursion depth, to prevent infinite recursion
333+ depth : usize ,
332334}
333335
334336impl PersistentStateFlags {
@@ -383,6 +385,7 @@ impl VisitorState {
383385 Self {
384386 persistent_flags : self . persistent_flags ,
385387 ephemeral_flags : EphemeralStateFlags :: from_outer_ty ( current_ty) ,
388+ depth : self . depth + 1 ,
386389 }
387390 }
388391 fn get_next_in_fnptr < ' tcx > ( & self , current_ty : Ty < ' tcx > , is_ret : bool ) -> Self {
@@ -394,12 +397,13 @@ impl VisitorState {
394397 PersistentStateFlags :: ARGUMENT_TY_IN_FNPTR
395398 } ,
396399 ephemeral_flags : EphemeralStateFlags :: from_outer_ty ( current_ty) ,
400+ depth : self . depth + 1 ,
397401 }
398402 }
399403
400404 /// Generate the state for an "outermost" type that needs to be checked
401405 fn entry_point ( persistent_flags : PersistentStateFlags ) -> Self {
402- Self { persistent_flags, ephemeral_flags : EphemeralStateFlags :: NO_OUTER_TY }
406+ Self { persistent_flags, ephemeral_flags : EphemeralStateFlags :: NO_OUTER_TY , depth : 0 }
403407 }
404408
405409 /// Get the proper visitor state for a given function's arguments.
@@ -733,9 +737,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
733737
734738 // Protect against infinite recursion, for example
735739 // `struct S(*mut S);`.
736- // FIXME: A recursion limit is necessary as well, for irregular
737- // recursive types.
738- if !self . cache . insert ( ty) {
740+ if !( self . cache . insert ( ty) && self . cx . tcx . recursion_limit ( ) . value_within_limit ( state. depth ) )
741+ {
739742 return FfiSafe ;
740743 }
741744
@@ -956,20 +959,25 @@ impl<'tcx> ImproperCTypesLint {
956959 fn_mode : CItemKind ,
957960 ) {
958961 struct FnPtrFinder < ' tcx > {
962+ current_depth : usize ,
963+ depths : Vec < usize > ,
959964 spans : Vec < Span > ,
960965 tys : Vec < Ty < ' tcx > > ,
961966 }
962967
963968 impl < ' tcx > hir:: intravisit:: Visitor < ' _ > for FnPtrFinder < ' tcx > {
964969 fn visit_ty ( & mut self , ty : & ' _ hir:: Ty < ' _ , AmbigArg > ) {
965970 debug ! ( ?ty) ;
971+ self . current_depth += 1 ;
966972 if let hir:: TyKind :: FnPtr ( hir:: FnPtrTy { abi, .. } ) = ty. kind
967973 && !abi. is_rustic_abi ( )
968974 {
975+ self . depths . push ( self . current_depth ) ;
969976 self . spans . push ( ty. span ) ;
970977 }
971978
972979 hir:: intravisit:: walk_ty ( self , ty) ;
980+ self . current_depth -= 1 ;
973981 }
974982 }
975983
@@ -987,15 +995,24 @@ impl<'tcx> ImproperCTypesLint {
987995 }
988996 }
989997
990- let mut visitor = FnPtrFinder { spans : Vec :: new ( ) , tys : Vec :: new ( ) } ;
998+ let mut visitor = FnPtrFinder {
999+ spans : Vec :: new ( ) ,
1000+ tys : Vec :: new ( ) ,
1001+ depths : Vec :: new ( ) ,
1002+ current_depth : 0 ,
1003+ } ;
9911004 ty. visit_with ( & mut visitor) ;
9921005 visitor. visit_ty_unambig ( hir_ty) ;
9931006
994- let all_types = iter:: zip ( visitor. tys . drain ( ..) , visitor. spans . drain ( ..) ) ;
995- for ( fn_ptr_ty, span) in all_types {
1007+ let all_types = iter:: zip (
1008+ visitor. depths . drain ( ..) ,
1009+ iter:: zip ( visitor. tys . drain ( ..) , visitor. spans . drain ( ..) ) ,
1010+ ) ;
1011+ for ( depth, ( fn_ptr_ty, span) ) in all_types {
9961012 let mut visitor = ImproperCTypesVisitor :: new ( cx, fn_ptr_ty, fn_mode) ;
1013+ let bridge_state = VisitorState { depth, ..state } ;
9971014 // FIXME(ctypes): make a check_for_fnptr
998- let ffi_res = visitor. check_type ( state , fn_ptr_ty) ;
1015+ let ffi_res = visitor. check_type ( bridge_state , fn_ptr_ty) ;
9991016
10001017 self . process_ffi_result ( cx, span, ffi_res, fn_mode) ;
10011018 }
0 commit comments