@@ -329,6 +329,8 @@ struct VisitorState {
329329persistant_flags :  PersistantStateFlags , 
330330 /// Flags describing both the immediate and overall context in which the current mir::Ty is 
331331ephemeral_flags :  EphemeralStateFlags , 
332+  /// Type recursion depth, to prevent infinite recursion 
333+ depth :  usize , 
332334} 
333335
334336impl  PersistantStateFlags  { 
@@ -383,6 +385,7 @@ impl VisitorState {
383385 Self  { 
384386 persistant_flags :  self . persistant_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 PersistantStateFlags :: 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 
401405fn  entry_point ( persistant_flags :  PersistantStateFlags )  -> Self  { 
402-  Self  {  persistant_flags,  ephemeral_flags :  EphemeralStateFlags :: NO_OUTER_TY  } 
406+  Self  {  persistant_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