| ... | ... | @@ -358,6 +358,8 @@ struct VisitorState { |
| 358 | 358 | /// Flags describing both the immediate context in which the current Ty is, |
| 359 | 359 | /// linked to how it relates to its parent Ty (or lack thereof). |
| 360 | 360 | outer_ty_kind: OuterTyKind, |
| 361 | /// Type recursion depth, to prevent infinite recursion |
| 362 | depth: usize, |
| 361 | 363 | } |
| 362 | 364 | |
| 363 | 365 | impl RootUseFlags { |
| ... | ... | @@ -385,6 +387,7 @@ impl VisitorState { |
| 385 | 387 | VisitorState { |
| 386 | 388 | root_use_flags: self.root_use_flags, |
| 387 | 389 | outer_ty_kind: OuterTyKind::from_ty(current_ty), |
| 390 | depth: self.depth + 1, |
| 388 | 391 | } |
| 389 | 392 | } |
| 390 | 393 | |
| ... | ... | @@ -399,6 +402,7 @@ impl VisitorState { |
| 399 | 402 | FnPos::Arg => RootUseFlags::ARGUMENT_TY_IN_FNPTR, |
| 400 | 403 | }, |
| 401 | 404 | outer_ty_kind: OuterTyKind::from_ty(current_ty), |
| 405 | depth: self.depth + 1, |
| 402 | 406 | } |
| 403 | 407 | } |
| 404 | 408 | |
| ... | ... | @@ -410,12 +414,16 @@ impl VisitorState { |
| 410 | 414 | (CItemKind::Definition, FnPos::Arg) => RootUseFlags::ARGUMENT_TY_IN_DEFINITION, |
| 411 | 415 | (CItemKind::Declaration, FnPos::Arg) => RootUseFlags::ARGUMENT_TY_IN_DECLARATION, |
| 412 | 416 | }; |
| 413 | | VisitorState { root_use_flags: p_flags, outer_ty_kind: OuterTyKind::None } |
| 417 | VisitorState { root_use_flags: p_flags, outer_ty_kind: OuterTyKind::None, depth: 0 } |
| 414 | 418 | } |
| 415 | 419 | |
| 416 | 420 | /// Get the proper visitor state for a static variable's type |
| 417 | 421 | fn static_entry_point() -> Self { |
| 418 | | VisitorState { root_use_flags: RootUseFlags::STATIC_TY, outer_ty_kind: OuterTyKind::None } |
| 422 | VisitorState { |
| 423 | root_use_flags: RootUseFlags::STATIC_TY, |
| 424 | outer_ty_kind: OuterTyKind::None, |
| 425 | depth: 0, |
| 426 | } |
| 419 | 427 | } |
| 420 | 428 | |
| 421 | 429 | /// Whether the type is used in a function. |
| ... | ... | @@ -737,9 +745,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { |
| 737 | 745 | |
| 738 | 746 | // Protect against infinite recursion, for example |
| 739 | 747 | // `struct S(*mut S);`. |
| 740 | | // FIXME: A recursion limit is necessary as well, for irregular |
| 741 | | // recursive types. |
| 742 | | if !self.cache.insert(ty) { |
| 748 | if !(self.cache.insert(ty) && self.cx.tcx.recursion_limit().value_within_limit(state.depth)) |
| 749 | { |
| 743 | 750 | return FfiSafe; |
| 744 | 751 | } |
| 745 | 752 | |
| ... | ... | @@ -994,6 +1001,8 @@ impl<'tcx> ImproperCTypesLint { |
| 994 | 1001 | fn_mode: CItemKind, |
| 995 | 1002 | ) { |
| 996 | 1003 | struct FnPtrFinder<'tcx> { |
| 1004 | current_depth: usize, |
| 1005 | depths: Vec<usize>, |
| 997 | 1006 | spans: Vec<Span>, |
| 998 | 1007 | tys: Vec<Ty<'tcx>>, |
| 999 | 1008 | } |
| ... | ... | @@ -1001,13 +1010,16 @@ impl<'tcx> ImproperCTypesLint { |
| 1001 | 1010 | impl<'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'tcx> { |
| 1002 | 1011 | fn visit_ty(&mut self, ty: &'_ hir::Ty<'_, AmbigArg>) { |
| 1003 | 1012 | debug!(?ty); |
| 1013 | self.current_depth += 1; |
| 1004 | 1014 | if let hir::TyKind::FnPtr(hir::FnPtrTy { abi, .. }) = ty.kind |
| 1005 | 1015 | && !abi.is_rustic_abi() |
| 1006 | 1016 | { |
| 1017 | self.depths.push(self.current_depth); |
| 1007 | 1018 | self.spans.push(ty.span); |
| 1008 | 1019 | } |
| 1009 | 1020 | |
| 1010 | 1021 | hir::intravisit::walk_ty(self, ty); |
| 1022 | self.current_depth -= 1; |
| 1011 | 1023 | } |
| 1012 | 1024 | } |
| 1013 | 1025 | |
| ... | ... | @@ -1025,16 +1037,25 @@ impl<'tcx> ImproperCTypesLint { |
| 1025 | 1037 | } |
| 1026 | 1038 | } |
| 1027 | 1039 | |
| 1028 | | let mut visitor = FnPtrFinder { spans: Vec::new(), tys: Vec::new() }; |
| 1040 | let mut visitor = FnPtrFinder { |
| 1041 | spans: Vec::new(), |
| 1042 | tys: Vec::new(), |
| 1043 | depths: Vec::new(), |
| 1044 | current_depth: 0, |
| 1045 | }; |
| 1029 | 1046 | ty.visit_with(&mut visitor); |
| 1030 | 1047 | visitor.visit_ty_unambig(hir_ty); |
| 1031 | 1048 | |
| 1032 | | let all_types = iter::zip(visitor.tys.drain(..), visitor.spans.drain(..)); |
| 1033 | | for (fn_ptr_ty, span) in all_types { |
| 1049 | let all_types = iter::zip( |
| 1050 | visitor.depths.drain(..), |
| 1051 | iter::zip(visitor.tys.drain(..), visitor.spans.drain(..)), |
| 1052 | ); |
| 1053 | for (depth, (fn_ptr_ty, span)) in all_types { |
| 1034 | 1054 | let fn_ptr_ty = Unnormalized::new_wip(fn_ptr_ty); |
| 1035 | 1055 | let mut visitor = ImproperCTypesVisitor::new(cx, fn_ptr_ty, fn_mode); |
| 1056 | let bridge_state = VisitorState { depth, ..state }; |
| 1036 | 1057 | // FIXME(ctypes): make a check_for_fnptr |
| 1037 | | let ffi_res = visitor.check_type(state, fn_ptr_ty); |
| 1058 | let ffi_res = visitor.check_type(bridge_state, fn_ptr_ty); |
| 1038 | 1059 | |
| 1039 | 1060 | self.process_ffi_result(cx, span, ffi_res, fn_mode); |
| 1040 | 1061 | } |