rapx/check/safedrop/
mod.rs

1pub mod alias;
2pub mod bug_records;
3pub mod corner_case;
4pub mod drop;
5pub mod graph;
6pub mod safedrop;
7
8use rustc_hir::def_id::DefId;
9use rustc_middle::ty::TyCtxt;
10
11use crate::{
12    analysis::{
13        alias_analysis::default::{AliasAnalyzer, MopFnAliasMap},
14        ownedheap_analysis::{OHAResultMap, OwnedHeapAnalysis, default::OwnedHeapAnalyzer},
15        path_analysis::default::PathAnalyzer,
16    },
17    utils::source::get_fn_name,
18};
19use graph::SafeDropGraph;
20use safedrop::*;
21
22use crate::analysis::Analysis;
23
24pub struct SafeDrop<'tcx> {
25    pub tcx: TyCtxt<'tcx>,
26}
27
28impl<'tcx> SafeDrop<'tcx> {
29    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
30        Self { tcx }
31    }
32    pub fn start(&self) {
33        let mut mop = AliasAnalyzer::new(self.tcx);
34        mop.run();
35        let fn_map = mop.get_all_fn_alias_raw();
36        let path_analyzer = mop.take_path_analyzer();
37        rap_info!("================================");
38        rap_debug!("Aliases found: {:?}", fn_map);
39
40        let mut heap = OwnedHeapAnalyzer::new(self.tcx);
41        heap.run();
42        let adt_owner = heap.get_all_items();
43
44        let mir_keys = self.tcx.mir_keys(());
45        for local_def_id in mir_keys {
46            query_safedrop(
47                self.tcx,
48                &fn_map,
49                local_def_id.to_def_id(),
50                adt_owner.clone(),
51                &path_analyzer,
52            );
53        }
54    }
55}
56
57pub fn query_safedrop<'tcx>(
58    tcx: TyCtxt<'tcx>,
59    fn_map: &MopFnAliasMap,
60    def_id: DefId,
61    adt_owner: OHAResultMap,
62    path_analyzer: &PathAnalyzer<'tcx>,
63) {
64    let fn_name = get_fn_name(tcx, def_id);
65    if fn_name
66        .as_ref()
67        .map_or(false, |s| s.contains("__raw_ptr_deref_dummy"))
68    {
69        return;
70    }
71    rap_trace!("query_safedrop: {:?}", fn_name);
72    /* filter const mir */
73    if let Some(_other) = tcx.hir_body_const_context(def_id.expect_local()) {
74        return;
75    }
76    if tcx.is_mir_available(def_id) {
77        let paths = path_analyzer.get_fn_paths(def_id);
78        let path_graph = path_analyzer
79            .graphs
80            .get(&def_id)
81            .cloned()
82            .unwrap_or_else(|| {
83                let mut g = crate::analysis::path_analysis::graph::PathGraph::new(tcx, def_id);
84                g.find_scc();
85                g
86            });
87        let mut safedrop_graph = SafeDropGraph::from_path_graph(tcx, def_id, path_graph, adt_owner);
88        rap_debug!("safedrop grah (raw): {}", safedrop_graph);
89        safedrop_graph.alias_graph.find_scc();
90        rap_debug!("safedrop graph (scc): {}", safedrop_graph);
91        safedrop_graph.process_function_paths_opt(paths, fn_map);
92        let visit_times = safedrop_graph.alias_graph.visit_times();
93        if visit_times <= VISIT_LIMIT {
94            safedrop_graph.report_bugs();
95        } else if !safedrop_graph.bug_records.is_bug_free() {
96            safedrop_graph.report_bugs();
97        }
98    }
99}