Skip to main content

rapx/check/safedrop/
drop.rs

1use super::checks;
2use super::graph::*;
3
4#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5pub struct LocalSpot {
6    pub bb: Option<usize>,
7    pub local: Option<usize>,
8}
9
10impl LocalSpot {
11    pub fn new(bb: usize, local: usize) -> Self {
12        LocalSpot {
13            bb: Some(bb),
14            local: Some(local),
15        }
16    }
17    pub fn from_local(local: usize) -> Self {
18        LocalSpot {
19            bb: None,
20            local: Some(local),
21        }
22    }
23    pub fn default() -> Self {
24        LocalSpot {
25            bb: None,
26            local: None,
27        }
28    }
29}
30
31#[derive(Debug, Clone)]
32pub struct DropRecord {
33    pub value_index: usize,
34    pub is_dropped: bool,
35    pub drop_spot: LocalSpot,
36    pub prop_chain: Vec<usize>,
37    pub has_dropped_field: bool,
38}
39
40impl DropRecord {
41    pub fn new(value_index: usize, is_dropped: bool, drop_spot: LocalSpot) -> Self {
42        DropRecord {
43            value_index,
44            is_dropped,
45            drop_spot,
46            prop_chain: Vec::new(),
47            has_dropped_field: false,
48        }
49    }
50    pub fn false_record(value_index: usize) -> Self {
51        DropRecord {
52            value_index,
53            is_dropped: false,
54            drop_spot: LocalSpot::default(),
55            prop_chain: Vec::new(),
56            has_dropped_field: false,
57        }
58    }
59    pub fn from(value_index: usize, record: &DropRecord) -> Self {
60        DropRecord {
61            value_index,
62            is_dropped: record.is_dropped,
63            drop_spot: record.drop_spot.clone(),
64            prop_chain: record.prop_chain.clone(),
65            has_dropped_field: record.has_dropped_field,
66        }
67    }
68    pub fn clear(&mut self) {
69        self.is_dropped = false;
70        self.drop_spot = LocalSpot::default();
71        self.prop_chain.clear();
72        self.has_dropped_field = false;
73    }
74}
75
76impl<'tcx> SafeDropGraph<'tcx> {
77    /*
78     * Mark the node as dropped.
79     * flag_cleanup: used to distinguish if a bug occurs in the unwinding path.
80     */
81    pub fn add_to_drop_record(
82        &mut self,
83        value_idx: usize, // the value to be dropped
84        bb_idx: usize,    // the block via_idx is dropped
85        flag_cleanup: bool,
86    ) {
87        rap_debug!(
88            "add_to_drop_record: value_idx = {}, bb_idx = {}",
89            value_idx,
90            bb_idx
91        );
92        if self.alias_graph.value_to_slot_idx(value_idx)
93            .map_or(false, |si| self.alias_graph.pts_graph.slot_is_ref_count(si)) {
94            return;
95        }
96        if self.df_check(value_idx, bb_idx, self.alias_graph.span(), flag_cleanup) {
97            return;
98        }
99        if !self.drop_record[value_idx].is_dropped {
100            let local = self.alias_graph.value_to_slot_idx(value_idx)
101                .and_then(|si| self.alias_graph.pts_graph.get_slot(si))
102                .map(|s| s.local)
103                .unwrap_or(value_idx);
104            let drop_spot = LocalSpot::new(bb_idx, local);
105            self.drop_record[value_idx] = DropRecord::new(value_idx, true, drop_spot);
106            rap_debug!("{:?}", self.drop_record[value_idx]);
107            checks::push_drop_info(&self.alias_graph, &mut self.drop_record, value_idx, drop_spot);
108        }
109    }
110}