rapx/analysis/safetyflow_analysis/
safetyflow_unit.rs1use crate::helpers::fn_info::*;
2use rustc_hir::{Safety, def_id::DefId};
3use rustc_middle::mir::Local;
4use std::collections::HashSet;
5
6#[derive(Debug, Clone)]
7pub struct SafetyFlowUnit {
8 pub caller: FnInfo,
9 pub callees: HashSet<FnInfo>,
10 pub raw_ptrs: HashSet<Local>,
11 pub static_muts: HashSet<DefId>,
12 pub caller_cons: HashSet<FnInfo>,
13 pub mut_methods: HashSet<DefId>,
14}
15
16#[derive(Debug, Clone, Default)]
22pub struct BasicUnitCounts {
23 pub unsafe_fn_or_method_no_callees: u32,
25 pub safe_fn_call_unsafe_fn: u32,
27 pub safe_fn_call_unsafe_method: u32,
29 pub unsafe_fn_call_unsafe_fn: u32,
31 pub unsafe_fn_call_unsafe_method: u32,
33 pub unsafe_method_safe_cons_call_unsafe_fn: u32,
35 pub unsafe_method_unsafe_cons_call_unsafe_fn: u32,
37 pub unsafe_method_safe_cons_call_unsafe_method: u32,
39 pub unsafe_method_unsafe_cons_call_unsafe_method: u32,
41 pub safe_method_safe_cons_call_unsafe_fn: u32,
43 pub safe_method_unsafe_cons_call_unsafe_fn: u32,
45 pub safe_method_safe_cons_call_unsafe_method: u32,
47 pub safe_method_unsafe_cons_call_unsafe_method: u32,
49}
50
51impl BasicUnitCounts {
52 pub fn total(&self) -> u32 {
53 self.unsafe_fn_or_method_no_callees
54 + self.safe_fn_call_unsafe_fn
55 + self.safe_fn_call_unsafe_method
56 + self.unsafe_fn_call_unsafe_fn
57 + self.unsafe_fn_call_unsafe_method
58 + self.unsafe_method_safe_cons_call_unsafe_fn
59 + self.unsafe_method_unsafe_cons_call_unsafe_fn
60 + self.unsafe_method_safe_cons_call_unsafe_method
61 + self.unsafe_method_unsafe_cons_call_unsafe_method
62 + self.safe_method_safe_cons_call_unsafe_fn
63 + self.safe_method_unsafe_cons_call_unsafe_fn
64 + self.safe_method_safe_cons_call_unsafe_method
65 + self.safe_method_unsafe_cons_call_unsafe_method
66 }
67}
68
69impl SafetyFlowUnit {
70 pub fn new(
71 caller: FnInfo,
72 callees: HashSet<FnInfo>,
73 raw_ptrs: HashSet<Local>,
74 static_muts: HashSet<DefId>,
75 caller_cons: HashSet<FnInfo>,
76 mut_methods: HashSet<DefId>,
77 ) -> Self {
78 Self {
79 caller,
80 callees,
81 raw_ptrs,
82 static_muts,
83 caller_cons,
84 mut_methods,
85 }
86 }
87
88 pub fn count_basic_units(&self, c: &mut BasicUnitCounts) {
89 if self.caller.fn_safety == Safety::Unsafe && self.callees.is_empty() {
90 c.unsafe_fn_or_method_no_callees += 1;
91 }
92 if self.caller.fn_safety == Safety::Safe && self.caller.fn_kind != FnKind::Method {
93 for callee in &self.callees {
94 if callee.fn_kind == FnKind::Method {
95 c.safe_fn_call_unsafe_method += 1;
96 } else {
97 c.safe_fn_call_unsafe_fn += 1;
98 }
99 }
100 }
101 if self.caller.fn_safety == Safety::Unsafe && self.caller.fn_kind != FnKind::Method {
102 for callee in &self.callees {
103 if callee.fn_kind == FnKind::Method {
104 c.unsafe_fn_call_unsafe_method += 1;
105 } else {
106 c.unsafe_fn_call_unsafe_fn += 1;
107 }
108 }
109 }
110 if self.caller.fn_safety == Safety::Unsafe && self.caller.fn_kind == FnKind::Method {
111 let mut unsafe_cons = 0;
112 let mut safe_cons = 0;
113 for cons in &self.caller_cons {
114 if cons.fn_safety == Safety::Unsafe {
115 unsafe_cons += 1;
116 } else {
117 safe_cons += 1;
118 }
119 }
120 if unsafe_cons == 0 && safe_cons == 0 {
121 safe_cons = 1;
122 }
123 for callee in &self.callees {
124 if callee.fn_kind == FnKind::Method {
125 c.unsafe_method_safe_cons_call_unsafe_method += safe_cons;
126 c.unsafe_method_unsafe_cons_call_unsafe_method += unsafe_cons;
127 } else {
128 c.unsafe_method_safe_cons_call_unsafe_fn += safe_cons;
129 c.unsafe_method_unsafe_cons_call_unsafe_fn += unsafe_cons;
130 }
131 }
132 }
133 if self.caller.fn_safety == Safety::Safe && self.caller.fn_kind == FnKind::Method {
134 let mut unsafe_cons = 0;
135 let mut safe_cons = 0;
136 for cons in &self.caller_cons {
137 if cons.fn_safety == Safety::Unsafe {
138 unsafe_cons += 1;
139 } else {
140 safe_cons += 1;
141 }
142 }
143 if unsafe_cons == 0 && safe_cons == 0 {
144 safe_cons = 1;
145 }
146 for callee in &self.callees {
147 if callee.fn_kind == FnKind::Method {
148 c.safe_method_safe_cons_call_unsafe_method += safe_cons;
149 c.safe_method_unsafe_cons_call_unsafe_method += unsafe_cons;
150 } else {
151 c.safe_method_safe_cons_call_unsafe_fn += safe_cons;
152 c.safe_method_unsafe_cons_call_unsafe_fn += unsafe_cons;
153 }
154 }
155 }
156 }
157}