Skip to main content

rapx/check/safedrop/
mod.rs

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