1use crate::{
2 analysis::{
3 core::{
4 alias_analysis::AAResult,
5 ownedheap_analysis::OHAResultMap,
6 range_analysis::{default::RangeAnalyzer, RangeAnalysis},
7 },
8 safedrop::graph::SafeDropGraph,
9 senryx::contracts::property::{CisRangeItem, PropertyContract},
10 utils::{
11 fn_info::{
12 display_hashmap, get_all_std_unsafe_callees_block_id, get_callees,
13 get_cleaned_def_path_name, is_ptr, is_ref,
14 },
15 show_mir::display_mir,
16 },
17 Analysis,
18 },
19 rap_debug, rap_warn,
20};
21use rustc_middle::ty::GenericParamDefKind;
22use serde::de;
23use std::{
24 collections::{HashMap, HashSet},
25 fmt::Debug,
26 hash::Hash,
27};
28use syn::Constraint;
29
30use super::contracts::abstract_state::{
31 AbstractStateItem, AlignState, PathInfo, StateType, VType, Value,
32};
33use super::contracts::contract::Contract;
34use super::dominated_graph::DominatedGraph;
35use super::dominated_graph::InterResultNode;
36use super::generic_check::GenericChecker;
37use super::inter_record::InterAnalysisRecord;
38use super::matcher::UnsafeApi;
39use super::matcher::{get_arg_place, parse_unsafe_api};
40use rustc_data_structures::fx::FxHashMap;
41use rustc_hir::def_id::DefId;
42use rustc_middle::{
43 mir::{
44 self, AggregateKind, BasicBlock, BasicBlockData, BinOp, CastKind, Local, Operand, Place,
45 ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
46 },
47 ty::{self, GenericArgKind, PseudoCanonicalInput, Ty, TyCtxt, TyKind},
48};
49use rustc_span::{source_map::Spanned, Span};
50
51pub struct CheckResult {
53 pub func_name: String,
54 pub func_span: Span,
55 pub failed_contracts: HashMap<usize, HashSet<String>>,
56 pub passed_contracts: HashMap<usize, HashSet<String>>,
57}
58
59impl CheckResult {
60 pub fn new(func_name: &str, func_span: Span) -> Self {
61 Self {
62 func_name: func_name.to_string(),
63 func_span,
64 failed_contracts: HashMap::new(),
65 passed_contracts: HashMap::new(),
66 }
67 }
68}
69
70#[derive(Debug, PartialEq, Eq, Clone)]
71pub enum PlaceTy<'tcx> {
72 Ty(usize, usize), GenericTy(String, HashSet<Ty<'tcx>>, HashSet<(usize, usize)>), Unknown,
75}
76
77impl<'tcx> PlaceTy<'tcx> {
78 pub fn possible_aligns(&self) -> HashSet<usize> {
79 match self {
80 PlaceTy::Ty(align, _size) => {
81 let mut set = HashSet::new();
82 set.insert(*align);
83 set
84 }
85 PlaceTy::GenericTy(_, _, tys) => tys.iter().map(|ty| ty.0).collect(),
86 _ => HashSet::new(),
87 }
88 }
89}
90
91impl<'tcx> Hash for PlaceTy<'tcx> {
92 fn hash<H: std::hash::Hasher>(&self, _state: &mut H) {}
93}
94
95pub struct BodyVisitor<'tcx> {
96 pub tcx: TyCtxt<'tcx>,
97 pub def_id: DefId,
98 pub safedrop_graph: SafeDropGraph<'tcx>,
99 pub abstract_states: HashMap<usize, PathInfo<'tcx>>,
101 pub unsafe_callee_report: HashMap<String, usize>,
102 pub local_ty: HashMap<usize, PlaceTy<'tcx>>,
103 pub visit_time: usize,
104 pub check_results: Vec<CheckResult>,
105 pub generic_map: HashMap<String, HashSet<Ty<'tcx>>>,
106 pub global_recorder: HashMap<DefId, InterAnalysisRecord<'tcx>>,
107 pub proj_ty: HashMap<usize, Ty<'tcx>>,
108 pub chains: DominatedGraph<'tcx>,
109 }
111
112impl<'tcx> BodyVisitor<'tcx> {
113 pub fn new(
114 tcx: TyCtxt<'tcx>,
115 def_id: DefId,
116 global_recorder: HashMap<DefId, InterAnalysisRecord<'tcx>>,
117 visit_time: usize,
118 ) -> Self {
119 let body = tcx.optimized_mir(def_id);
120 let param_env = tcx.param_env(def_id);
121 let satisfied_ty_map_for_generic =
122 GenericChecker::new(tcx, param_env).get_satisfied_ty_map();
123 let mut chains = DominatedGraph::new(tcx, def_id);
124 chains.init_arg();
125 Self {
126 tcx,
127 def_id,
128 safedrop_graph: SafeDropGraph::new(body, tcx, def_id, OHAResultMap::default()),
129 abstract_states: HashMap::new(),
130 unsafe_callee_report: HashMap::new(),
131 local_ty: HashMap::new(),
132 visit_time,
133 check_results: Vec::new(),
134 generic_map: satisfied_ty_map_for_generic,
135 global_recorder,
136 proj_ty: HashMap::new(),
137 chains,
138 }
140 }
141
142 pub fn get_ty_by_place(&self, p: usize) -> Ty<'tcx> {
143 let body = self.tcx.optimized_mir(self.def_id);
144 let locals = body.local_decls.clone();
145 return locals[Local::from(p)].ty;
146 }
147
148 pub fn update_fields_states(&mut self, inter_result: InterResultNode<'tcx>) {
149 self.chains.init_self_with_inter(inter_result);
150 }
151
152 pub fn path_forward_check(
153 &mut self,
154 fn_map: &FxHashMap<DefId, AAResult>,
155 ) -> InterResultNode<'tcx> {
156 let mut inter_return_value =
157 InterResultNode::construct_from_var_node(self.chains.clone(), 0);
158 if self.visit_time >= 1000 {
159 return inter_return_value;
160 }
161
162 let paths = self.get_all_paths();
164 let body = self.tcx.optimized_mir(self.def_id);
166
167 let locals = body.local_decls.clone();
169 for (idx, local) in locals.iter().enumerate() {
170 let local_ty = local.ty;
171 let layout = self.visit_ty_and_get_layout(local_ty);
172 self.local_ty.insert(idx, layout);
173 }
174
175 let tmp_chain = self.chains.clone();
177 for (index, (path, constraint)) in paths.iter().enumerate() {
178 self.chains = tmp_chain.clone();
179 self.set_constraint(constraint);
180 self.abstract_states.insert(index, PathInfo::new());
181 for block_index in path.iter() {
182 if block_index >= &body.basic_blocks.len() {
183 continue;
184 }
185 self.path_analyze_block(
186 &body.basic_blocks[BasicBlock::from_usize(*block_index)].clone(),
187 index,
188 *block_index,
189 fn_map,
190 );
191 let tem_scc_sub_blocks = self.safedrop_graph.blocks[*block_index]
192 .scc_sub_blocks
193 .clone();
194 if tem_scc_sub_blocks.len() > 0 {
195 for sub_block in &tem_scc_sub_blocks {
196 self.path_analyze_block(
197 &body.basic_blocks[BasicBlock::from_usize(*sub_block)].clone(),
198 index,
199 *block_index,
200 fn_map,
201 );
202 }
203 }
204 }
205 let curr_path_inter_return_value =
207 InterResultNode::construct_from_var_node(self.chains.clone(), 0);
208 inter_return_value.merge(curr_path_inter_return_value);
209 }
210
211 inter_return_value
212 }
213
214 pub fn path_analyze_block(
215 &mut self,
216 block: &BasicBlockData<'tcx>,
217 path_index: usize,
218 bb_index: usize,
219 fn_map: &FxHashMap<DefId, AAResult>,
220 ) {
221 for statement in block.statements.iter() {
222 self.path_analyze_statement(statement, path_index);
223 }
224 self.path_analyze_terminator(&block.terminator(), path_index, bb_index, fn_map);
225 }
226
227 pub fn path_analyze_statement(&mut self, statement: &Statement<'tcx>, _path_index: usize) {
228 match statement.kind {
229 StatementKind::Assign(box (ref lplace, ref rvalue)) => {
230 self.path_analyze_assign(lplace, rvalue, _path_index);
231 }
232 StatementKind::Intrinsic(box ref intrinsic) => match intrinsic {
233 mir::NonDivergingIntrinsic::CopyNonOverlapping(cno) => {
234 if cno.src.place().is_some() && cno.dst.place().is_some() {
235 let _src_pjc_local =
236 self.handle_proj(true, cno.src.place().unwrap().clone());
237 let _dst_pjc_local =
238 self.handle_proj(true, cno.dst.place().unwrap().clone());
239 }
240 }
241 _ => {}
242 },
243 StatementKind::StorageDead(local) => {
244 }
246 _ => {}
247 }
248 }
249
250 pub fn path_analyze_terminator(
251 &mut self,
252 terminator: &Terminator<'tcx>,
253 path_index: usize,
254 bb_index: usize,
255 fn_map: &FxHashMap<DefId, AAResult>,
256 ) {
257 match &terminator.kind {
258 TerminatorKind::Call {
259 func,
260 args,
261 destination: dst_place,
262 target: _,
263 unwind: _,
264 call_source: _,
265 fn_span,
266 } => {
267 if let Operand::Constant(func_constant) = func {
268 if let ty::FnDef(ref callee_def_id, raw_list) = func_constant.const_.ty().kind()
269 {
270 let mut mapping = FxHashMap::default();
271 self.get_generic_mapping(raw_list.as_slice(), callee_def_id, &mut mapping);
272 rap_debug!(
273 "func {:?}, generic type mapping {:?}",
274 callee_def_id,
275 mapping
276 );
277 self.handle_call(
278 dst_place,
279 callee_def_id,
280 args,
281 path_index,
282 fn_map,
283 *fn_span,
284 mapping,
285 );
286 }
287 }
288 }
289 TerminatorKind::Drop {
290 place,
291 target: _,
292 unwind: _,
293 replace: _,
294 drop: _,
295 async_fut: _,
296 } => {
297 let drop_local = self.handle_proj(false, *place);
298 if !self.chains.set_drop(drop_local) {
299 }
304 }
305 _ => {}
306 }
307 }
308
309 fn get_generic_mapping(
314 &self,
315 raw_list: &[rustc_middle::ty::GenericArg<'tcx>],
316 def_id: &DefId,
317 generic_mapping: &mut FxHashMap<String, Ty<'tcx>>,
318 ) {
319 let generics = self.tcx.generics_of(def_id);
320 for param in &generics.own_params {
321 if let GenericParamDefKind::Type {
322 has_default: _,
323 synthetic: _,
324 } = param.kind
325 {
326 if let Some(ty) = raw_list.get(param.index as usize) {
327 if let GenericArgKind::Type(actual_ty) = (*ty).kind() {
328 let param_name = param.name.to_string();
329 generic_mapping.insert(param_name, actual_ty);
330 }
331 }
332 }
333 }
334 if generics.own_params.len() == 0 && generics.parent.is_some() {
335 let parent_def_id = generics.parent.unwrap();
336 self.get_generic_mapping(raw_list, &parent_def_id, generic_mapping);
337 }
338 }
339
340 pub fn path_analyze_assign(
341 &mut self,
342 lplace: &Place<'tcx>,
343 rvalue: &Rvalue<'tcx>,
344 path_index: usize,
345 ) {
346 let lpjc_local = self.handle_proj(false, lplace.clone());
347 match rvalue {
348 Rvalue::Use(op) => match op {
349 Operand::Move(rplace) => {
350 let rpjc_local = self.handle_proj(true, rplace.clone());
351 self.chains.merge(lpjc_local, rpjc_local);
352 }
353 Operand::Copy(rplace) => {
354 let rpjc_local = self.handle_proj(true, rplace.clone());
355 self.chains.copy_node(lpjc_local, rpjc_local);
356 }
357 _ => {}
358 },
359 Rvalue::Repeat(op, _const) => match op {
360 Operand::Move(rplace) | Operand::Copy(rplace) => {
361 let _rpjc_local = self.handle_proj(true, rplace.clone());
362 }
363 _ => {}
364 },
365 Rvalue::Ref(_, _, rplace) | Rvalue::RawPtr(_, rplace) => {
366 let rpjc_local = self.handle_proj(true, rplace.clone());
367 self.chains.point(lpjc_local, rpjc_local);
369 }
370 Rvalue::Cast(cast_kind, op, ty) => match op {
371 Operand::Move(rplace) | Operand::Copy(rplace) => {
372 let rpjc_local = self.handle_proj(true, rplace.clone());
373 let r_point_to = self.chains.get_point_to_id(rpjc_local);
374 if r_point_to == rpjc_local {
375 self.chains.merge(lpjc_local, rpjc_local);
376 } else {
377 self.chains.point(lpjc_local, r_point_to);
378 }
379 }
380 _ => {}
381 },
382 Rvalue::BinaryOp(_bin_op, box (ref _op1, ref _op2)) => {}
383 Rvalue::ShallowInitBox(op, _ty) => match op {
384 Operand::Move(rplace) | Operand::Copy(rplace) => {
385 let _rpjc_local = self.handle_proj(true, rplace.clone());
386 }
387 _ => {}
388 },
389 Rvalue::Aggregate(box ref agg_kind, op_vec) => match agg_kind {
390 AggregateKind::Array(_ty) => {}
391 AggregateKind::Adt(_adt_def_id, _, _, _, _) => {
392 for (idx, op) in op_vec.into_iter().enumerate() {
393 let (is_const, val) = get_arg_place(op);
394 if is_const {
395 self.chains.insert_field_node(
396 lpjc_local,
397 idx,
398 Some(Ty::new_uint(self.tcx, rustc_middle::ty::UintTy::Usize)),
399 );
400 } else {
401 let node = self.chains.get_var_node_mut(lpjc_local).unwrap();
402 node.field.insert(idx, val);
403 }
404 }
405 }
406 _ => {}
407 },
408 Rvalue::Discriminant(_place) => {
409 }
411 _ => {}
412 }
413 }
414
415 pub fn handle_call(
416 &mut self,
417 dst_place: &Place<'tcx>,
418 def_id: &DefId,
419 args: &Box<[Spanned<Operand>]>,
420 path_index: usize,
421 fn_map: &FxHashMap<DefId, AAResult>,
422 fn_span: Span,
423 generic_mapping: FxHashMap<String, Ty<'tcx>>,
424 ) {
425 if !self.tcx.is_mir_available(def_id) {
426 self.insert_path_abstate(
427 path_index,
428 dst_place.local.as_usize(),
429 AbstractStateItem::new_default(),
430 );
431 return;
432 }
433
434 if let Some(fn_result) =
436 parse_unsafe_api(get_cleaned_def_path_name(self.tcx, *def_id).as_str())
437 {
438 self.handle_std_unsafe_call(
439 dst_place,
440 def_id,
441 args,
442 path_index,
443 fn_map,
444 fn_span,
445 fn_result,
446 generic_mapping,
447 );
448 }
449
450 self.set_bound(def_id, dst_place, args);
451
452 self.handle_ret_alias(dst_place, def_id, fn_map, args);
454
455 }
496
497 fn set_bound(
498 &mut self,
499 def_id: &DefId,
500 dst_place: &Place<'tcx>,
501 args: &Box<[Spanned<Operand>]>,
502 ) {
503 if args.len() == 0 || !get_cleaned_def_path_name(self.tcx, *def_id).contains("slice::len") {
504 return;
505 }
506 let d_local = self.handle_proj(false, dst_place.clone());
507 let ptr_local = get_arg_place(&args[0].node).1;
508 let mem_local = self.chains.get_point_to_id(ptr_local);
509 let mem_var = self.chains.get_var_node_mut(mem_local).unwrap();
510 for cis in &mut mem_var.cis.contracts {
511 if let PropertyContract::InBound(cis_ty, len) = cis {
512 *len = CisRangeItem::new_var(d_local);
513 }
514 }
515 }
516
517 pub fn handle_ret_alias(
519 &mut self,
520 dst_place: &Place<'tcx>,
521 def_id: &DefId,
522 fn_map: &FxHashMap<DefId, AAResult>,
523 args: &Box<[Spanned<Operand>]>,
524 ) {
525 let d_local = self.handle_proj(false, dst_place.clone());
526 if let Some(retalias) = fn_map.get(def_id) {
529 for alias_set in retalias.aliases() {
530 let (l, r) = (alias_set.lhs_no, alias_set.rhs_no);
531 let (l_fields, r_fields) =
532 (alias_set.lhs_fields.clone(), alias_set.rhs_fields.clone());
533 let (l_place, r_place) = (
534 if l != 0 {
535 get_arg_place(&args[l - 1].node)
536 } else {
537 (false, d_local)
538 },
539 if r != 0 {
540 get_arg_place(&args[r - 1].node)
541 } else {
542 (false, d_local)
543 },
544 );
545 if l_place.0 {
547 let snd_var = self.chains.find_var_id_with_fields_seq(r_place.1, r_fields);
548 self.chains
549 .update_value(self.chains.get_point_to_id(snd_var), l_place.1);
550 continue;
551 }
552 if r_place.0 {
554 let fst_var = self.chains.find_var_id_with_fields_seq(l_place.1, l_fields);
555 self.chains
556 .update_value(self.chains.get_point_to_id(fst_var), r_place.1);
557 continue;
558 }
559 let (fst_var, snd_var) = (
560 self.chains.find_var_id_with_fields_seq(l_place.1, l_fields),
561 self.chains.find_var_id_with_fields_seq(r_place.1, r_fields),
562 );
563 let fst_to = self.chains.get_point_to_id(fst_var);
565 let snd_to = self.chains.get_point_to_id(snd_var);
566 let is_fst_point = fst_to != fst_var;
567 let is_snd_point = snd_to != snd_var;
568 let fst_node = self.chains.get_var_node(fst_var).unwrap();
569 let snd_node = self.chains.get_var_node(snd_var).unwrap();
570 let is_fst_ptr = is_ptr(fst_node.ty.unwrap()) || is_ref(fst_node.ty.unwrap());
571 let is_snd_ptr = is_ptr(snd_node.ty.unwrap()) || is_ref(snd_node.ty.unwrap());
572 rap_debug!(
573 "{:?}: {fst_var},{fst_to},{is_fst_ptr} -- {snd_var},{snd_to},{is_snd_ptr}",
574 def_id
575 );
576 match (is_fst_ptr, is_snd_ptr) {
577 (false, true) => {
578 if is_snd_point {
580 self.chains.point(snd_var, fst_var);
581 } else {
582 self.chains.merge(fst_var, snd_to);
583 }
584 }
585 (false, false) => {
586 self.chains.merge(fst_var, snd_var);
587 }
588 (true, true) => {
589 if is_fst_point && is_snd_point {
590 self.chains.merge(fst_to, snd_to);
591 } else if !is_fst_point && is_snd_point {
592 self.chains.point(fst_var, snd_to);
593 } else if is_fst_point && !is_snd_point {
594 self.chains.point(snd_var, fst_to);
595 } else {
596 self.chains.merge(fst_var, snd_var);
597 }
598 }
599 (true, false) => {
600 if is_fst_point {
601 self.chains.point(fst_var, snd_var);
602 } else {
603 self.chains.merge(snd_var, fst_to);
604 }
605 }
606 }
607 }
608 }
609 else {
611 let d_ty = self.chains.get_local_ty_by_place(d_local);
612 if d_ty.is_some() && (is_ptr(d_ty.unwrap()) || is_ref(d_ty.unwrap())) {
613 self.chains
614 .generate_ptr_with_obj_node(d_ty.unwrap(), d_local);
615 }
616 }
617 }
618
619 pub fn update_post_state(
621 &mut self,
622 post_state: &HashMap<usize, AbstractStateItem<'tcx>>,
623 args: &Box<[Spanned<Operand>]>,
624 path_index: usize,
625 ) {
626 for (idx, arg) in args.iter().enumerate() {
627 let arg_place = get_arg_place(&arg.node);
628 if let Some(state_item) = post_state.get(&idx) {
629 self.insert_path_abstate(path_index, arg_place.1, state_item.clone());
630 }
631 }
632 }
633
634 pub fn get_args_post_states(&mut self) -> HashMap<usize, AbstractStateItem<'tcx>> {
635 let tcx = self.tcx;
636 let def_id = self.def_id;
637 let final_states = self.abstract_states_mop();
638 let mut result_states = HashMap::new();
639 let fn_sig = tcx.fn_sig(def_id).skip_binder();
640 let num_params = fn_sig.inputs().skip_binder().len();
641 for i in 0..num_params + 1 {
642 if let Some(state) = final_states.state_map.get(&(i)) {
643 result_states.insert(i, state.clone());
644 } else {
645 result_states.insert(i, AbstractStateItem::new_default());
646 }
647 }
648 result_states
649 }
650
651 pub fn get_all_paths(&mut self) -> HashMap<Vec<usize>, Vec<(Place<'tcx>, Place<'tcx>, BinOp)>> {
652 let mut range_analyzer = RangeAnalyzer::<i128>::new(self.tcx, false);
653 let path_constraints_option =
654 range_analyzer.start_path_constraints_analysis_for_defid(self.def_id); let mut path_constraints: HashMap<Vec<usize>, Vec<(_, _, _)>> =
656 if path_constraints_option.is_none() {
657 let mut results = HashMap::new();
658 let paths: Vec<Vec<usize>> = self.safedrop_graph.get_paths();
659 for path in paths {
660 results.insert(path, Vec::new());
661 }
662 results
663 } else {
664 path_constraints_option.unwrap()
665 };
666 self.safedrop_graph.solve_scc();
667 if self.visit_time == 0 {
669 let contains_unsafe_blocks = get_all_std_unsafe_callees_block_id(self.tcx, self.def_id);
670 path_constraints.retain(|path, cons| {
671 path.iter()
672 .any(|block_id| contains_unsafe_blocks.contains(block_id))
673 });
674 }
675 path_constraints
677 }
678
679 pub fn abstract_states_mop(&mut self) -> PathInfo<'tcx> {
694 let mut result_state = PathInfo {
695 state_map: HashMap::new(),
696 };
697
698 for (_path_idx, abstract_state) in &self.abstract_states {
699 for (var_index, state_item) in &abstract_state.state_map {
700 if let Some(existing_state_item) = result_state.state_map.get_mut(&var_index) {
701 existing_state_item
702 .clone()
703 .meet_state_item(&state_item.clone());
704 } else {
705 result_state
706 .state_map
707 .insert(*var_index, state_item.clone());
708 }
709 }
710 }
711 result_state
712 }
713
714 pub fn update_callee_report_level(&mut self, unsafe_callee: String, report_level: usize) {
715 self.unsafe_callee_report
716 .entry(unsafe_callee)
717 .and_modify(|e| {
718 if report_level < *e {
719 *e = report_level;
720 }
721 })
722 .or_insert(report_level);
723 }
724
725 pub fn output_results(&self, threshold: usize) {
728 for (unsafe_callee, report_level) in &self.unsafe_callee_report {
729 if *report_level == 0 {
730 rap_warn!("Find one bug in {:?}!", unsafe_callee);
731 } else if *report_level <= threshold {
732 rap_warn!("Find an unsoundness issue in {:?}!", unsafe_callee);
733 }
734 }
735 }
736
737 pub fn insert_path_abstate(
738 &mut self,
739 path_index: usize,
740 place: usize,
741 abitem: AbstractStateItem<'tcx>,
742 ) {
743 self.abstract_states
744 .entry(path_index)
745 .or_insert_with(|| PathInfo {
746 state_map: HashMap::new(),
747 })
748 .state_map
749 .insert(place, abitem);
750 }
751
752 pub fn set_constraint(&mut self, constraint: &Vec<(Place<'tcx>, Place<'tcx>, BinOp)>) {
753 for (p1, p2, op) in constraint {
754 let p1_num = self.handle_proj(false, p1.clone());
755 let p2_num = self.handle_proj(false, p2.clone());
756 self.chains.insert_patial_op(p1_num, p2_num, op);
757 }
758 }
759
760 pub fn get_layout_by_place_usize(&self, place: usize) -> PlaceTy<'tcx> {
761 if let Some(ty) = self.chains.get_obj_ty_through_chain(place) {
762 return self.visit_ty_and_get_layout(ty);
763 } else {
764 return PlaceTy::Unknown;
765 }
766 }
767
768 pub fn visit_ty_and_get_layout(&self, ty: Ty<'tcx>) -> PlaceTy<'tcx> {
769 match ty.kind() {
770 TyKind::RawPtr(ty, _)
771 | TyKind::Ref(_, ty, _)
772 | TyKind::Slice(ty)
773 | TyKind::Array(ty, _) => self.visit_ty_and_get_layout(*ty),
774 TyKind::Param(param_ty) => {
775 let generic_name = param_ty.name.to_string();
776 let mut layout_set: HashSet<(usize, usize)> = HashSet::new();
777 let ty_set = self.generic_map.get(&generic_name.clone());
778 if ty_set.is_none() {
779 if self.visit_time == 0 {
780 rap_warn!(
781 "Can not get generic type set: {:?}, def_id:{:?}",
782 generic_name,
783 self.def_id
784 );
785 }
786 return PlaceTy::GenericTy(generic_name, HashSet::new(), layout_set);
787 }
788 for ty in ty_set.unwrap().clone() {
789 if let PlaceTy::Ty(align, size) = self.visit_ty_and_get_layout(ty) {
790 layout_set.insert((align, size));
791 }
792 }
793 return PlaceTy::GenericTy(generic_name, ty_set.unwrap().clone(), layout_set);
794 }
795 TyKind::Adt(def, _list) => {
796 if def.is_enum() {
797 return PlaceTy::Unknown;
798 } else {
799 PlaceTy::Unknown
800 }
801 }
802 TyKind::Closure(_, _) => PlaceTy::Unknown,
803 TyKind::Alias(_, ty) => {
804 return self.visit_ty_and_get_layout(ty.self_ty());
806 }
807 _ => {
808 let param_env = self.tcx.param_env(self.def_id);
809 let ty_env = ty::TypingEnv::post_analysis(self.tcx, self.def_id);
810 let input = PseudoCanonicalInput {
811 typing_env: ty_env,
812 value: ty,
813 };
814 if let Ok(layout) = self.tcx.layout_of(input) {
815 let align = layout.align.abi.bytes_usize();
817 let size = layout.size.bytes() as usize;
818 return PlaceTy::Ty(align, size);
819 } else {
820 rap_warn!("Find type {:?} that can't get layout!", ty);
821 PlaceTy::Unknown
822 }
823 }
824 }
825 }
826
827 pub fn get_abstate_by_place_in_path(
828 &self,
829 place: usize,
830 path_index: usize,
831 ) -> AbstractStateItem<'tcx> {
832 if let Some(abstate) = self.abstract_states.get(&path_index) {
833 if let Some(abs) = abstate.state_map.get(&place).cloned() {
834 return abs;
835 }
836 }
837 AbstractStateItem::new_default()
838 }
839
840 pub fn handle_cast(
841 &mut self,
842 rpjc_local: usize,
843 lpjc_local: usize,
844 ty: &Ty<'tcx>,
845 path_index: usize,
846 cast_kind: &CastKind,
847 ) {
848 let mut src_ty = self.get_layout_by_place_usize(rpjc_local);
849 match cast_kind {
850 CastKind::PtrToPtr | CastKind::PointerCoercion(_, _) => {
851 let r_abitem = self.get_abstate_by_place_in_path(rpjc_local, path_index);
852 for state in &r_abitem.state {
853 if let StateType::AlignState(r_align_state) = state.clone() {
854 match r_align_state {
855 AlignState::Cast(from, _to) => {
856 src_ty = from.clone();
857 }
858 _ => {}
859 }
860 }
861 }
862
863 let dst_ty = self.visit_ty_and_get_layout(*ty);
864 let align_state =
865 StateType::AlignState(AlignState::Cast(src_ty.clone(), dst_ty.clone()));
866 let abitem = AbstractStateItem::new(
867 (Value::None, Value::None),
868 VType::Pointer(dst_ty),
869 HashSet::from([align_state]),
870 );
871 self.insert_path_abstate(path_index, lpjc_local, abitem);
872 }
873 _ => {}
874 }
875 }
876
877 pub fn handle_binary_op(
878 &mut self,
879 first_op: &Operand,
880 bin_op: &BinOp,
881 second_op: &Operand,
882 path_index: usize,
883 ) {
884 match bin_op {
885 BinOp::Offset => {
886 let _first_place = get_arg_place(first_op);
887 let _second_place = get_arg_place(second_op);
888 }
889 _ => {}
890 }
891 }
892
893 pub fn handle_proj(&mut self, is_right: bool, place: Place<'tcx>) -> usize {
894 let mut proj_id = place.local.as_usize();
895 for proj in place.projection {
896 match proj {
897 ProjectionElem::Deref => {
898 proj_id = self.chains.get_point_to_id(place.local.as_usize());
899 if proj_id == place.local.as_usize() {
900 proj_id = self.chains.check_ptr(proj_id);
901 }
902 }
903 ProjectionElem::Field(field, ty) => {
904 proj_id = self
905 .chains
906 .get_field_node_id(proj_id, field.as_usize(), Some(ty));
907 }
908 _ => {}
909 }
910 }
911 proj_id
912 }
913}