diff options
| author | Gurinder Singh <frederick.the.fool@gmail.com> | 2024-09-20 18:57:59 +0530 |
|---|---|---|
| committer | Gurinder Singh <frederick.the.fool@gmail.com> | 2024-09-20 18:57:59 +0530 |
| commit | 716044751b7a36c634be709e37923e3dbdf53888 (patch) | |
| tree | ca74a4c27182f43712955c03c425cde89de59860 /compiler/rustc_lint | |
| parent | e2dc1a1c0f97a90319181a721ab317210307617a (diff) | |
| download | rust-716044751b7a36c634be709e37923e3dbdf53888.tar.gz rust-716044751b7a36c634be709e37923e3dbdf53888.zip | |
Add recursion limit to FFI safety lint
Fixes stack overflow in the case of recursive types
Diffstat (limited to 'compiler/rustc_lint')
| -rw-r--r-- | compiler/rustc_lint/messages.ftl | 2 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/types.rs | 20 |
2 files changed, 19 insertions, 3 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 4aa86944a0b..bffff1bf1e3 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -395,6 +395,8 @@ lint_improper_ctypes_opaque = opaque types have no C equivalent lint_improper_ctypes_pat_help = consider using the base type instead lint_improper_ctypes_pat_reason = pattern types have no C equivalent + +lint_improper_ctypes_recursion_limit_reached = type is infinitely recursive lint_improper_ctypes_slice_help = consider using a raw pointer instead lint_improper_ctypes_slice_reason = slices have no C equivalent diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 900c496e033..aa2a6c9ab62 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -991,6 +991,8 @@ struct CTypesVisitorState<'tcx> { /// The original type being checked, before we recursed /// to any other types it contains. base_ty: Ty<'tcx>, + /// Number of times we recursed while checking the type + recursion_depth: usize, } enum FfiResult<'tcx> { @@ -1296,12 +1298,23 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Protect against infinite recursion, for example // `struct S(*mut S);`. - // FIXME: A recursion limit is necessary as well, for irregular - // recursive types. if !acc.cache.insert(ty) { return FfiSafe; } + // Additional recursion check for more complex types like + // `struct A<T> { v: *const A<A<T>>, ... }` for which the + // cache check above won't be enough (fixes #130310) + if !tcx.recursion_limit().value_within_limit(acc.recursion_depth) { + return FfiUnsafe { + ty: acc.base_ty, + reason: fluent::lint_improper_ctypes_recursion_limit_reached, + help: None, + }; + } + + acc.recursion_depth += 1; + match *ty.kind() { ty::Adt(def, args) => { if let Some(boxed) = ty.boxed_ty() @@ -1644,7 +1657,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return; } - let mut acc = CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty }; + let mut acc = + CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty, recursion_depth: 0 }; match self.check_type_for_ffi(&mut acc, ty) { FfiResult::FfiSafe => {} FfiResult::FfiPhantom(ty) => { |
