@@ -348,6 +348,8 @@ struct VisitorState {
348348 /// Flags describing both the immediate context in which the current mir::Ty is,
349349 /// linked to how it relates to its parent mir::Ty (or lack thereof).
350350 outer_ty_kind : OuterTyKind ,
351+ /// Type recursion depth, to prevent infinite recursion
352+ depth : usize ,
351353}
352354
353355impl RootUseFlags {
@@ -375,6 +377,7 @@ impl VisitorState {
375377 Self {
376378 root_use_flags : self . root_use_flags ,
377379 outer_ty_kind : OuterTyKind :: from_outer_ty ( current_ty) ,
380+ depth : self . depth + 1 ,
378381 }
379382 }
380383 /// From an existing state, compute the state of any subtype of the current type.
@@ -388,12 +391,13 @@ impl VisitorState {
388391 FnPos :: Arg => RootUseFlags :: ARGUMENT_TY_IN_FNPTR ,
389392 } ,
390393 outer_ty_kind : OuterTyKind :: from_outer_ty ( current_ty) ,
394+ depth : self . depth + 1 ,
391395 }
392396 }
393397
394398 /// Generate the state for an "outermost" type that needs to be checked
395399 fn entry_point ( root_use_flags : RootUseFlags ) -> Self {
396- Self { root_use_flags, outer_ty_kind : OuterTyKind :: None }
400+ Self { root_use_flags, outer_ty_kind : OuterTyKind :: None , depth : 0 }
397401 }
398402
399403 /// Get the proper visitor state for a given function's arguments or return type.
@@ -719,9 +723,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
719723
720724 // Protect against infinite recursion, for example
721725 // `struct S(*mut S);`.
722- // FIXME: A recursion limit is necessary as well, for irregular
723- // recursive types.
724- if !self . cache . insert ( ty) {
726+ if !( self . cache . insert ( ty) && self . cx . tcx . recursion_limit ( ) . value_within_limit ( state. depth ) )
727+ {
725728 return FfiSafe ;
726729 }
727730
@@ -938,20 +941,25 @@ impl<'tcx> ImproperCTypesLint {
938941 fn_mode : CItemKind ,
939942 ) {
940943 struct FnPtrFinder < ' tcx > {
944+ current_depth : usize ,
945+ depths : Vec < usize > ,
941946 spans : Vec < Span > ,
942947 tys : Vec < Ty < ' tcx > > ,
943948 }
944949
945950 impl < ' tcx > hir:: intravisit:: Visitor < ' _ > for FnPtrFinder < ' tcx > {
946951 fn visit_ty ( & mut self , ty : & ' _ hir:: Ty < ' _ , AmbigArg > ) {
947952 debug ! ( ?ty) ;
953+ self . current_depth += 1 ;
948954 if let hir:: TyKind :: FnPtr ( hir:: FnPtrTy { abi, .. } ) = ty. kind
949955 && !abi. is_rustic_abi ( )
950956 {
957+ self . depths . push ( self . current_depth ) ;
951958 self . spans . push ( ty. span ) ;
952959 }
953960
954961 hir:: intravisit:: walk_ty ( self , ty) ;
962+ self . current_depth -= 1 ;
955963 }
956964 }
957965
@@ -969,15 +977,24 @@ impl<'tcx> ImproperCTypesLint {
969977 }
970978 }
971979
972- let mut visitor = FnPtrFinder { spans : Vec :: new ( ) , tys : Vec :: new ( ) } ;
980+ let mut visitor = FnPtrFinder {
981+ spans : Vec :: new ( ) ,
982+ tys : Vec :: new ( ) ,
983+ depths : Vec :: new ( ) ,
984+ current_depth : 0 ,
985+ } ;
973986 ty. visit_with ( & mut visitor) ;
974987 visitor. visit_ty_unambig ( hir_ty) ;
975988
976- let all_types = iter:: zip ( visitor. tys . drain ( ..) , visitor. spans . drain ( ..) ) ;
977- for ( fn_ptr_ty, span) in all_types {
989+ let all_types = iter:: zip (
990+ visitor. depths . drain ( ..) ,
991+ iter:: zip ( visitor. tys . drain ( ..) , visitor. spans . drain ( ..) ) ,
992+ ) ;
993+ for ( depth, ( fn_ptr_ty, span) ) in all_types {
978994 let mut visitor = ImproperCTypesVisitor :: new ( cx, fn_ptr_ty, fn_mode) ;
995+ let bridge_state = VisitorState { depth, ..state } ;
979996 // FIXME(ctypes): make a check_for_fnptr
980- let ffi_res = visitor. check_type ( state , fn_ptr_ty) ;
997+ let ffi_res = visitor. check_type ( bridge_state , fn_ptr_ty) ;
981998
982999 self . process_ffi_result ( cx, span, ffi_res, fn_mode) ;
9831000 }
0 commit comments