@@ -329,6 +329,8 @@ struct VisitorState {
329
329
persistant_flags : PersistantStateFlags ,
330
330
/// Flags describing both the immediate and overall context in which the current mir::Ty is
331
331
ephemeral_flags : EphemeralStateFlags ,
332
+ /// Type recursion depth, to prevent infinite recursion
333
+ depth : usize ,
332
334
}
333
335
334
336
impl PersistantStateFlags {
@@ -383,6 +385,7 @@ impl VisitorState {
383
385
Self {
384
386
persistant_flags : self . persistant_flags ,
385
387
ephemeral_flags : EphemeralStateFlags :: from_outer_ty ( current_ty) ,
388
+ depth : self . depth + 1 ,
386
389
}
387
390
}
388
391
fn get_next_in_fnptr < ' tcx > ( & self , current_ty : Ty < ' tcx > , is_ret : bool ) -> Self {
@@ -394,12 +397,13 @@ impl VisitorState {
394
397
PersistantStateFlags :: ARGUMENT_TY_IN_FNPTR
395
398
} ,
396
399
ephemeral_flags : EphemeralStateFlags :: from_outer_ty ( current_ty) ,
400
+ depth : self . depth + 1 ,
397
401
}
398
402
}
399
403
400
404
/// Generate the state for an "outermost" type that needs to be checked
401
405
fn 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 }
403
407
}
404
408
405
409
/// Get the proper visitor state for a given function's arguments.
@@ -733,9 +737,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
733
737
734
738
// Protect against infinite recursion, for example
735
739
// `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
+ {
739
742
return FfiSafe ;
740
743
}
741
744
@@ -956,20 +959,25 @@ impl<'tcx> ImproperCTypesLint {
956
959
fn_mode : CItemKind ,
957
960
) {
958
961
struct FnPtrFinder < ' tcx > {
962
+ current_depth : usize ,
963
+ depths : Vec < usize > ,
959
964
spans : Vec < Span > ,
960
965
tys : Vec < Ty < ' tcx > > ,
961
966
}
962
967
963
968
impl < ' tcx > hir:: intravisit:: Visitor < ' _ > for FnPtrFinder < ' tcx > {
964
969
fn visit_ty ( & mut self , ty : & ' _ hir:: Ty < ' _ , AmbigArg > ) {
965
970
debug ! ( ?ty) ;
971
+ self . current_depth += 1 ;
966
972
if let hir:: TyKind :: FnPtr ( hir:: FnPtrTy { abi, .. } ) = ty. kind
967
973
&& !abi. is_rustic_abi ( )
968
974
{
975
+ self . depths . push ( self . current_depth ) ;
969
976
self . spans . push ( ty. span ) ;
970
977
}
971
978
972
979
hir:: intravisit:: walk_ty ( self , ty) ;
980
+ self . current_depth -= 1 ;
973
981
}
974
982
}
975
983
@@ -987,15 +995,24 @@ impl<'tcx> ImproperCTypesLint {
987
995
}
988
996
}
989
997
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
+ } ;
991
1004
ty. visit_with ( & mut visitor) ;
992
1005
visitor. visit_ty_unambig ( hir_ty) ;
993
1006
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 {
996
1012
let mut visitor = ImproperCTypesVisitor :: new ( cx, fn_ptr_ty, fn_mode) ;
1013
+ let bridge_state = VisitorState { depth, ..state } ;
997
1014
// 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) ;
999
1016
1000
1017
self . process_ffi_result ( cx, span, ffi_res, fn_mode) ;
1001
1018
}
0 commit comments