@@ -18,6 +18,7 @@ use rustc_target::spec::abi::Abi as SpecAbi;
1818use tracing:: debug;
1919use { rustc_ast as ast, rustc_attr as attr, rustc_hir as hir} ;
2020
21+ use crate :: errors:: RecursionLimitReached ;
2122use crate :: lints:: {
2223 AmbiguousWidePointerComparisons , AmbiguousWidePointerComparisonsAddrMetadataSuggestion ,
2324 AmbiguousWidePointerComparisonsAddrSuggestion , AtomicOrderingFence , AtomicOrderingLoad ,
@@ -991,12 +992,15 @@ struct CTypesVisitorState<'tcx> {
991992 /// The original type being checked, before we recursed
992993 /// to any other types it contains.
993994 base_ty : Ty < ' tcx > ,
995+ /// Number of times we recursed while checking the type
996+ recursion_depth : usize ,
994997}
995998
996999enum FfiResult < ' tcx > {
9971000 FfiSafe ,
9981001 FfiPhantom ( Ty < ' tcx > ) ,
9991002 FfiUnsafe { ty : Ty < ' tcx > , reason : DiagMessage , help : Option < DiagMessage > } ,
1003+ RecursionLimitReached ,
10001004}
10011005
10021006pub ( crate ) fn nonnull_optimization_guaranteed < ' tcx > (
@@ -1270,7 +1274,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12701274 // `()` fields are FFI-safe!
12711275 FfiUnsafe { ty, .. } if ty. is_unit ( ) => false ,
12721276 FfiPhantom ( ..) => true ,
1273- r @ FfiUnsafe { .. } => return r,
1277+ r => return r,
12741278 }
12751279 }
12761280
@@ -1296,12 +1300,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12961300
12971301 // Protect against infinite recursion, for example
12981302 // `struct S(*mut S);`.
1299- // FIXME: A recursion limit is necessary as well, for irregular
1300- // recursive types.
13011303 if !acc. cache . insert ( ty) {
13021304 return FfiSafe ;
13031305 }
13041306
1307+ // Additional recursion check for more complex types like
1308+ // `struct A<T> { v: *const A<A<T>>, ... }` for which the
1309+ // cache check above won't be enough (fixes #130310)
1310+ if !tcx. recursion_limit ( ) . value_within_limit ( acc. recursion_depth ) {
1311+ return RecursionLimitReached ;
1312+ }
1313+
1314+ acc. recursion_depth += 1 ;
1315+
13051316 match * ty. kind ( ) {
13061317 ty:: Adt ( def, args) => {
13071318 if let Some ( boxed) = ty. boxed_ty ( )
@@ -1644,7 +1655,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
16441655 return ;
16451656 }
16461657
1647- let mut acc = CTypesVisitorState { cache : FxHashSet :: default ( ) , base_ty : ty } ;
1658+ let mut acc =
1659+ CTypesVisitorState { cache : FxHashSet :: default ( ) , base_ty : ty, recursion_depth : 0 } ;
16481660 match self . check_type_for_ffi ( & mut acc, ty) {
16491661 FfiResult :: FfiSafe => { }
16501662 FfiResult :: FfiPhantom ( ty) => {
@@ -1658,6 +1670,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
16581670 FfiResult :: FfiUnsafe { ty, reason, help } => {
16591671 self . emit_ffi_unsafe_type_lint ( ty, sp, reason, help) ;
16601672 }
1673+ FfiResult :: RecursionLimitReached => {
1674+ self . cx . tcx . dcx ( ) . emit_err ( RecursionLimitReached { ty, span : sp } ) ;
1675+ }
16611676 }
16621677 }
16631678
0 commit comments