@@ -347,6 +347,8 @@ struct VisitorState {
347347 /// Flags describing both the immediate context in which the current mir::Ty is,
348348 /// linked to how it relates to its parent mir::Ty (or lack thereof).
349349 outer_ty_kind : OuterTyKind ,
350+ /// Type recursion depth, to prevent infinite recursion
351+ depth : usize ,
350352}
351353
352354impl RootUseFlags {
@@ -374,6 +376,7 @@ impl VisitorState {
374376 Self {
375377 root_use_flags : self . root_use_flags ,
376378 outer_ty_kind : OuterTyKind :: from_outer_ty ( current_ty) ,
379+ depth : self . depth + 1 ,
377380 }
378381 }
379382 /// From an existing state, compute the state of any subtype of the current type.
@@ -387,12 +390,13 @@ impl VisitorState {
387390 FnPos :: Arg => RootUseFlags :: ARGUMENT_TY_IN_FNPTR ,
388391 } ,
389392 outer_ty_kind : OuterTyKind :: from_outer_ty ( current_ty) ,
393+ depth : self . depth + 1 ,
390394 }
391395 }
392396
393397 /// Generate the state for an "outermost" type that needs to be checked
394398 fn entry_point ( root_use_flags : RootUseFlags ) -> Self {
395- Self { root_use_flags, outer_ty_kind : OuterTyKind :: None }
399+ Self { root_use_flags, outer_ty_kind : OuterTyKind :: None , depth : 0 }
396400 }
397401
398402 /// Get the proper visitor state for a given function's arguments or return type.
@@ -718,9 +722,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
718722
719723 // Protect against infinite recursion, for example
720724 // `struct S(*mut S);`.
721- // FIXME: A recursion limit is necessary as well, for irregular
722- // recursive types.
723- if !self . cache . insert ( ty) {
725+ if !( self . cache . insert ( ty) && self . cx . tcx . recursion_limit ( ) . value_within_limit ( state. depth ) )
726+ {
724727 return FfiSafe ;
725728 }
726729
@@ -935,20 +938,25 @@ impl<'tcx> ImproperCTypesLint {
935938 fn_mode : CItemKind ,
936939 ) {
937940 struct FnPtrFinder < ' tcx > {
941+ current_depth : usize ,
942+ depths : Vec < usize > ,
938943 spans : Vec < Span > ,
939944 tys : Vec < Ty < ' tcx > > ,
940945 }
941946
942947 impl < ' tcx > hir:: intravisit:: Visitor < ' _ > for FnPtrFinder < ' tcx > {
943948 fn visit_ty ( & mut self , ty : & ' _ hir:: Ty < ' _ , AmbigArg > ) {
944949 debug ! ( ?ty) ;
950+ self . current_depth += 1 ;
945951 if let hir:: TyKind :: FnPtr ( hir:: FnPtrTy { abi, .. } ) = ty. kind
946952 && !abi. is_rustic_abi ( )
947953 {
954+ self . depths . push ( self . current_depth ) ;
948955 self . spans . push ( ty. span ) ;
949956 }
950957
951958 hir:: intravisit:: walk_ty ( self , ty) ;
959+ self . current_depth -= 1 ;
952960 }
953961 }
954962
@@ -966,15 +974,24 @@ impl<'tcx> ImproperCTypesLint {
966974 }
967975 }
968976
969- let mut visitor = FnPtrFinder { spans : Vec :: new ( ) , tys : Vec :: new ( ) } ;
977+ let mut visitor = FnPtrFinder {
978+ spans : Vec :: new ( ) ,
979+ tys : Vec :: new ( ) ,
980+ depths : Vec :: new ( ) ,
981+ current_depth : 0 ,
982+ } ;
970983 ty. visit_with ( & mut visitor) ;
971984 visitor. visit_ty_unambig ( hir_ty) ;
972985
973- let all_types = iter:: zip ( visitor. tys . drain ( ..) , visitor. spans . drain ( ..) ) ;
974- for ( fn_ptr_ty, span) in all_types {
986+ let all_types = iter:: zip (
987+ visitor. depths . drain ( ..) ,
988+ iter:: zip ( visitor. tys . drain ( ..) , visitor. spans . drain ( ..) ) ,
989+ ) ;
990+ for ( depth, ( fn_ptr_ty, span) ) in all_types {
975991 let mut visitor = ImproperCTypesVisitor :: new ( cx, fn_ptr_ty, fn_mode) ;
992+ let bridge_state = VisitorState { depth, ..state } ;
976993 // FIXME(ctypes): make a check_for_fnptr
977- let ffi_res = visitor. check_type ( state , fn_ptr_ty) ;
994+ let ffi_res = visitor. check_type ( bridge_state , fn_ptr_ty) ;
978995
979996 self . process_ffi_result ( cx, span, ffi_res, fn_mode) ;
980997 }
0 commit comments