1use rustc_middle::{
2 mir::{Operand, Place, ProjectionElem, TerminatorKind},
3 ty::{self, TyCtxt, TypingEnv},
4};
5
6use super::graph::*;
7use crate::analysis::{
8 core::alias_analysis::default::{
9 MopAAFact, MopAAResultMap, assign::*, block::Term, types::*, value::*,
10 },
11 utils::fn_info::convert_alias_to_sets,
12};
13
14impl<'tcx> SafeDropGraph<'tcx> {
15 pub fn alias_bb(&mut self, bb_index: usize) {
17 for stmt in self.mop_graph.blocks[bb_index].const_value.clone() {
18 self.mop_graph.constants.insert(stmt.def_id, stmt.value);
19 }
20 let cur_block = self.mop_graph.blocks[bb_index].clone();
21 for assign in cur_block.assignments {
22 let mut lv_idx = self.projection(false, assign.lv);
23 let rv_idx = self.projection(true, assign.rv);
24 match assign.atype {
25 AssignType::Variant => {
26 self.mop_graph.alias_set[lv_idx] = rv_idx;
27 continue;
28 }
29 AssignType::InitBox => {
30 lv_idx = *self.mop_graph.values[lv_idx].fields.get(&0).unwrap();
31 }
32 _ => {} }
34 self.fill_birth(lv_idx, self.mop_graph.blocks[bb_index].scc.enter as isize);
35 if self.mop_graph.values[lv_idx].local != self.mop_graph.values[rv_idx].local {
36 rap_debug!(
37 "merge alias: lv_idx/local:{}/{}, rv_idx/local:{}/{}",
38 lv_idx,
39 self.mop_graph.values[lv_idx].local,
40 rv_idx,
41 self.mop_graph.values[rv_idx].local
42 );
43 self.merge_alias(lv_idx, rv_idx, 0);
44 rap_debug!(
45 "Alias sets: {:?}",
46 convert_alias_to_sets(self.mop_graph.alias_set.clone())
47 );
48 }
49 self.uaf_check(bb_index, rv_idx, assign.span, false);
50 }
51 }
52
53 pub fn alias_bbcall(&mut self, bb_index: usize, tcx: TyCtxt<'tcx>, fn_map: &MopAAResultMap) {
55 let cur_block = self.mop_graph.blocks[bb_index].clone();
56 if let Term::Call(call) | Term::Drop(call) = cur_block.terminator {
57 if let TerminatorKind::Call {
58 ref func,
59 ref args,
60 ref destination,
61 target: _,
62 unwind: _,
63 call_source: _,
64 fn_span: _,
65 } = call.kind
66 {
67 if let Operand::Constant(constant) = func {
68 let lv = self.projection(false, destination.clone());
69 self.mop_graph.values[lv].birth = self.mop_graph.blocks[bb_index].scc.enter as isize;
70 let mut merge_vec = Vec::new();
71 merge_vec.push(lv);
72 let mut may_drop_flag = 0;
73 if self.mop_graph.values[lv].may_drop {
74 may_drop_flag += 1;
75 }
76 for arg in args {
77 match arg.node {
78 Operand::Copy(ref p) => {
79 let rv = self.projection(true, p.clone());
80 self.uaf_check(bb_index, rv, call.source_info.span, true);
82 merge_vec.push(rv);
83 if self.mop_graph.values[rv].may_drop {
84 may_drop_flag += 1;
85 }
86 }
87 Operand::Move(ref p) => {
88 let rv = self.projection(true, p.clone());
89 self.uaf_check(bb_index, rv, call.source_info.span, true);
90 merge_vec.push(rv);
91 if self.mop_graph.values[rv].may_drop {
92 may_drop_flag += 1;
93 }
94 }
95 Operand::Constant(_) => {
96 merge_vec.push(0);
97 }
98 }
99 }
100 if let ty::FnDef(target_id, _) = constant.const_.ty().kind() {
101 if may_drop_flag > 1 {
102 if tcx.is_mir_available(*target_id) {
103 if fn_map.contains_key(&target_id) {
104 let assignments = fn_map.get(&target_id).unwrap();
105 for assign in assignments.aliases().iter() {
106 if !assign.valuable() {
107 continue;
108 }
109 self.merge(assign, &merge_vec);
110 }
111 }
112 } else {
113 if self.mop_graph.values[lv].may_drop {
114 if self.corner_handle(lv, &merge_vec, *target_id) {
115 return;
116 }
117 let mut right_set = Vec::new();
118 for rv in &merge_vec {
119 if self.mop_graph.values[*rv].may_drop
120 && lv != *rv
121 && self.mop_graph.values[lv].is_ptr()
122 {
123 right_set.push(*rv);
124 }
125 }
126 if right_set.len() == 1 {
127 self.merge_alias(lv, right_set[0], 0);
128 }
129 }
130 }
131 }
132 }
133 }
134 }
135 }
136 }
137
138 pub fn fill_birth(&mut self, node: usize, birth: isize) {
140 self.mop_graph.values[node].birth = birth;
141 for i in 0..self.mop_graph.values.len() {
142 if self.mop_graph.union_is_same(i, node) && self.mop_graph.values[i].birth == -1 {
143 self.mop_graph.values[i].birth = birth;
144 }
145 }
146 for i in self.mop_graph.values[node].fields.clone().into_iter() {
147 self.fill_birth(i.1, birth); }
149 }
150
151 pub fn projection(&mut self, is_right: bool, place: Place<'tcx>) -> usize {
158 let mut local = place.local.as_usize();
159 let mut proj_id = local;
160 for proj in place.projection {
161 let new_id = self.mop_graph.values.len();
162 match proj {
163 ProjectionElem::Deref => {
164 proj_id = self.mop_graph.alias_set[proj_id];
166 }
167 ProjectionElem::Field(field, ty) => {
171 if is_right && self.mop_graph.alias_set[proj_id] != proj_id {
172 proj_id = self.mop_graph.alias_set[proj_id];
173 local = self.mop_graph.values[proj_id].local;
174 }
175 let field_idx = field.as_usize();
176 if !self.mop_graph.values[proj_id]
177 .fields
178 .contains_key(&field_idx)
179 {
180 let ty_env =
181 TypingEnv::post_analysis(self.mop_graph.tcx, self.mop_graph.def_id);
182 let need_drop = ty.needs_drop(self.mop_graph.tcx, ty_env);
183 let may_drop = !is_not_drop(self.mop_graph.tcx, ty);
184 let mut node = Value::new(new_id, local, need_drop, need_drop || may_drop);
185 node.kind = kind(ty);
186 node.birth = self.mop_graph.values[proj_id].birth;
187 node.field_id = field_idx;
188 self.mop_graph.values[proj_id]
189 .fields
190 .insert(field_idx, node.index);
191 self.mop_graph
192 .alias_set
193 .push(self.mop_graph.alias_set.len());
194 self.drop_record.push(self.drop_record[proj_id]);
195 self.mop_graph.values.push(node);
196 }
197 proj_id = *self.mop_graph.values[proj_id]
198 .fields
199 .get(&field_idx)
200 .unwrap();
201 }
202 _ => {}
203 }
204 }
205 return proj_id;
206 }
207
208 pub fn merge_alias(&mut self, lv: usize, rv: usize, depth: usize) {
210 if lv >= self.mop_graph.values.len() || rv >= self.mop_graph.values.len() {
217 return;
218 }
219 self.mop_graph.union_merge(lv, rv);
220
221 let max_field_depth = match std::env::var_os("SAFEDROP") {
222 Some(val) if val == "0" => 10,
223 Some(val) if val == "1" => 20,
224 Some(val) if val == "2" => 30,
225 Some(val) if val == "3" => 50,
226 _ => 15,
227 };
228
229 if depth > max_field_depth {
230 return;
231 }
232
233 for field in self.mop_graph.values[rv].fields.clone().into_iter() {
234 if !self.mop_graph.values[lv].fields.contains_key(&field.0) {
235 let mut node = Value::new(
236 self.mop_graph.values.len(),
237 self.mop_graph.values[lv].local,
238 self.mop_graph.values[field.1].need_drop,
239 self.mop_graph.values[field.1].may_drop,
240 );
241 node.kind = self.mop_graph.values[field.1].kind;
242 node.birth = self.mop_graph.values[lv].birth;
243 node.field_id = field.0;
244 self.mop_graph.values[lv].fields.insert(field.0, node.index);
245 self.mop_graph
246 .alias_set
247 .push(self.mop_graph.alias_set.len());
248 self.drop_record.push(DropRecord::false_record());
249 self.mop_graph.values.push(node);
250 }
251 let lv_field = *(self.mop_graph.values[lv].fields.get(&field.0).unwrap());
252 self.merge_alias(lv_field, field.1, depth + 1);
253 }
254 }
255
256 pub fn merge(&mut self, ret_alias: &MopAAFact, arg_vec: &Vec<usize>) {
258 if ret_alias.lhs_no() >= arg_vec.len() || ret_alias.rhs_no() >= arg_vec.len() {
259 rap_error!("Vector error!");
260 return;
261 }
262 let left_init = arg_vec[ret_alias.lhs_no()];
263 let mut right_init = arg_vec[ret_alias.rhs_no()];
264 let mut lv = left_init;
265 let mut rv = right_init;
266 for index in ret_alias.lhs_fields().iter() {
267 if self.mop_graph.values[lv].fields.contains_key(&index) == false {
268 let need_drop = ret_alias.lhs_need_drop;
269 let may_drop = ret_alias.lhs_may_drop;
270 let mut node =
271 Value::new(self.mop_graph.values.len(), left_init, need_drop, may_drop);
272 node.kind = TyKind::RawPtr;
273 node.birth = self.mop_graph.values[lv].birth;
274 node.field_id = *index;
275 self.mop_graph.values[lv].fields.insert(*index, node.index);
276 self.mop_graph
277 .alias_set
278 .push(self.mop_graph.alias_set.len());
279 self.drop_record.push(self.drop_record[lv]);
280 self.mop_graph.values.push(node);
281 }
282 lv = *self.mop_graph.values[lv].fields.get(&index).unwrap();
283 }
284 for index in ret_alias.rhs_fields().iter() {
285 if self
287 .mop_graph
288 .union_is_same(rv, self.mop_graph.alias_set[rv])
289 {
290 rv = self.mop_graph.values[rv].index;
291 right_init = self.mop_graph.values[rv].local;
292 }
293 if !self.mop_graph.values[rv].fields.contains_key(&index) {
294 let need_drop = ret_alias.rhs_need_drop;
295 let may_drop = ret_alias.rhs_may_drop;
296 let mut node = Value::new(
297 self.mop_graph.alias_set.len(),
298 right_init,
299 need_drop,
300 may_drop,
301 );
302 node.kind = TyKind::RawPtr;
303 node.birth = self.mop_graph.values[rv].birth;
304 node.field_id = *index;
305 self.mop_graph.values[rv].fields.insert(*index, node.index);
306 self.mop_graph.alias_set.push(self.mop_graph.values.len());
307 self.drop_record.push(self.drop_record[rv]);
308 self.mop_graph.values.push(node);
309 }
310 rv = *self.mop_graph.values[rv].fields.get(&index).unwrap();
311 }
312 self.merge_alias(lv, rv, 0);
313 }
314}