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