1
1
pub mod contracts;
2
+ pub mod generic_check;
2
3
pub mod inter_record;
3
4
pub mod matcher;
4
5
pub mod visitor;
5
6
7
+ use crate :: analysis:: utils:: fn_info:: * ;
6
8
use crate :: {
7
9
analysis:: unsafety_isolation:: {
8
10
hir_visitor:: { ContainsUnsafe , RelatedFnCollector } ,
9
11
UnsafetyIsolationCheck ,
10
12
} ,
11
13
rap_info, rap_warn,
12
14
} ;
15
+ use inter_record:: InterAnalysisRecord ;
13
16
use rustc_hir:: def_id:: DefId ;
14
17
use rustc_middle:: mir:: { BasicBlock , Operand , TerminatorKind } ;
15
18
use rustc_middle:: ty;
16
19
use rustc_middle:: ty:: TyCtxt ;
17
- use std:: collections:: HashSet ;
18
- use visitor:: CheckResult ;
19
- // use visitor::{BodyVisitor, CheckResult};
20
+ use std:: collections:: { HashMap , HashSet } ;
21
+ use visitor:: { BodyVisitor , CheckResult } ;
20
22
21
- use super :: unsafety_isolation:: generate_dot:: UigUnit ;
23
+ pub enum CheckLevel {
24
+ High ,
25
+ Medium ,
26
+ Low ,
27
+ }
22
28
23
29
pub struct SenryxCheck < ' tcx > {
24
30
pub tcx : TyCtxt < ' tcx > ,
25
31
pub threshhold : usize ,
32
+ pub global_recorder : HashMap < DefId , InterAnalysisRecord < ' tcx > > ,
26
33
}
27
34
28
35
impl < ' tcx > SenryxCheck < ' tcx > {
29
36
pub fn new ( tcx : TyCtxt < ' tcx > , threshhold : usize ) -> Self {
30
- Self { tcx, threshhold }
37
+ Self {
38
+ tcx,
39
+ threshhold,
40
+ global_recorder : HashMap :: new ( ) ,
41
+ }
31
42
}
32
43
33
- pub fn start ( & self ) {
34
- let related_items = RelatedFnCollector :: collect ( self . tcx ) ; // find all func
35
- let hir_map = self . tcx . hir ( ) ;
36
- for ( _, & ref vec) in & related_items {
44
+ pub fn start ( & mut self , check_level : CheckLevel ) {
45
+ let hir_map = self . tcx . hir ( ) . clone ( ) ;
46
+ let tcx = self . tcx ;
47
+ let related_items = RelatedFnCollector :: collect ( tcx) ;
48
+ for ( _, & ref vec) in & related_items. clone ( ) {
37
49
for ( body_id, _span) in vec {
38
50
let ( function_unsafe, block_unsafe) =
39
- ContainsUnsafe :: contains_unsafe ( self . tcx , * body_id) ;
51
+ ContainsUnsafe :: contains_unsafe ( tcx, * body_id) ;
40
52
let def_id = hir_map. body_owner_def_id ( * body_id) . to_def_id ( ) ;
53
+ if !Self :: filter_by_check_level ( tcx, & check_level, def_id) {
54
+ continue ;
55
+ }
41
56
if block_unsafe {
42
57
self . check_soundness ( def_id) ;
43
58
}
44
59
if function_unsafe {
45
- self . annotate_safety ( def_id) ;
60
+ // self.annotate_safety(def_id, &mut global_recorder );
46
61
}
47
62
}
48
63
}
49
64
}
50
65
51
- pub fn check_soundness ( & self , def_id : DefId ) {
52
- let _check_results = self . body_visit_and_check ( def_id) ;
53
- // if check_results.len() > 0 {
54
- // Self::show_check_results(def_id, check_results);
55
- // }
66
+ pub fn filter_by_check_level (
67
+ tcx : TyCtxt < ' tcx > ,
68
+ check_level : & CheckLevel ,
69
+ def_id : DefId ,
70
+ ) -> bool {
71
+ match * check_level {
72
+ CheckLevel :: High => check_visibility ( tcx, def_id) ,
73
+ _ => true ,
74
+ }
56
75
}
57
76
58
- pub fn annotate_safety ( & self , def_id : DefId ) {
59
- let annotation_results = self . get_annotation ( def_id) ;
60
- if annotation_results. len ( ) == 0 {
61
- return ;
77
+ pub fn check_soundness ( & mut self , def_id : DefId ) {
78
+ let check_results = self . body_visit_and_check ( def_id) ;
79
+ let tcx = self . tcx ;
80
+ if check_results. len ( ) > 0 {
81
+ Self :: show_check_results ( tcx, def_id, check_results) ;
62
82
}
63
- Self :: show_annotate_results ( self . tcx , def_id, annotation_results) ;
64
83
}
65
84
66
- // pub fn body_visit_and_check(&self, def_id: DefId) -> Vec<CheckResult> {
67
- // let mut uig_checker = UnsafetyIsolationCheck::new(self.tcx);
68
- // let func_type = UnsafetyIsolationCheck::get_type(self.tcx,def_id);
69
- // let mut body_visitor = BodyVisitor::new(self.tcx, def_id, 0);
70
- // if func_type == 1 {
71
- // let func_cons = uig_checker.search_constructor(def_id);
72
- // for func_con in func_cons {
73
- // let mut cons_body_visitor = BodyVisitor::new(self.tcx, func_con, 0);
74
- // cons_body_visitor.path_forward_check();
75
- // // TODO: cache fields' states
76
- // // TODO: update method body's states
77
- // // analyze body's states
78
- // body_visitor.path_forward_check();
79
- // }
80
- // } else {
81
- // body_visitor.path_forward_check();
82
- // }
83
- // return body_visitor.check_results;
84
- // }
85
+ pub fn annotate_safety ( & self , _def_id : DefId ) {
86
+ // let annotation_results = self.get_annotation(def_id, global_recorder);
87
+ // if annotation_results.len() == 0 {
88
+ // return;
89
+ // }
90
+ // Self::show_annotate_results(self.tcx, def_id, annotation_results);
91
+ }
92
+
93
+ pub fn body_visit_and_check ( & mut self , def_id : DefId ) -> Vec < CheckResult < ' tcx > > {
94
+ let mut body_visitor = BodyVisitor :: new ( self . tcx , def_id, self . global_recorder . clone ( ) , 0 ) ;
95
+ let func_type = get_type ( self . tcx , def_id) ;
96
+ if func_type == 1 {
97
+ let func_cons = get_cons ( self . tcx , def_id) ;
98
+ for func_con in func_cons {
99
+ let mut cons_body_visitor =
100
+ BodyVisitor :: new ( self . tcx , func_con. 0 , self . global_recorder . clone ( ) , 0 ) ;
101
+ cons_body_visitor. path_forward_check ( ) ;
102
+ // TODO: cache fields' states
103
+
104
+ // TODO: update method body's states
105
+
106
+ // analyze body's states
107
+ body_visitor. path_forward_check ( ) ;
108
+ }
109
+ } else {
110
+ body_visitor. path_forward_check ( ) ;
111
+ }
112
+ return body_visitor. check_results ;
113
+ }
85
114
86
- pub fn body_visit_and_check ( & self , def_id : DefId ) {
115
+ pub fn body_visit_and_check_uig ( & self , def_id : DefId ) {
87
116
let mut uig_checker = UnsafetyIsolationCheck :: new ( self . tcx ) ;
88
- let func_type = UnsafetyIsolationCheck :: get_type ( self . tcx , def_id) ;
117
+ let func_type = get_type ( self . tcx , def_id) ;
89
118
if func_type == 1 && self . get_annotation ( def_id) . len ( ) > 0 {
90
119
let func_cons = uig_checker. search_constructor ( def_id) ;
91
120
for func_con in func_cons {
92
- if UnsafetyIsolationCheck :: check_safety ( self . tcx , func_con) {
121
+ if check_safety ( self . tcx , func_con) {
93
122
Self :: show_annotate_results ( self . tcx , func_con, self . get_annotation ( def_id) ) ;
94
123
// uphold safety to unsafe constructor
95
124
}
@@ -119,8 +148,8 @@ impl<'tcx> SenryxCheck<'tcx> {
119
148
} => match func {
120
149
Operand :: Constant ( c) => match c. ty ( ) . kind ( ) {
121
150
ty:: FnDef ( id, ..) => {
122
- if UigUnit :: get_sp ( self . tcx , * id) . len ( ) > 0 {
123
- results. extend ( UigUnit :: get_sp ( self . tcx , * id) ) ;
151
+ if get_sp ( self . tcx , * id) . len ( ) > 0 {
152
+ results. extend ( get_sp ( self . tcx , * id) ) ;
124
153
} else {
125
154
results. extend ( self . get_annotation ( * id) ) ;
126
155
}
@@ -138,7 +167,7 @@ impl<'tcx> SenryxCheck<'tcx> {
138
167
pub fn show_check_results ( tcx : TyCtxt < ' tcx > , def_id : DefId , check_results : Vec < CheckResult > ) {
139
168
rap_info ! (
140
169
"--------In safe function {:?}---------" ,
141
- UigUnit :: get_cleaned_def_path_name( tcx, def_id)
170
+ get_cleaned_def_path_name( tcx, def_id)
142
171
) ;
143
172
for check_result in check_results {
144
173
rap_info ! (
@@ -160,7 +189,7 @@ impl<'tcx> SenryxCheck<'tcx> {
160
189
) {
161
190
rap_info ! (
162
191
"--------In unsafe function {:?}---------" ,
163
- UigUnit :: get_cleaned_def_path_name( tcx, def_id)
192
+ get_cleaned_def_path_name( tcx, def_id)
164
193
) ;
165
194
rap_warn ! ( "Lack safety annotations: {:?}." , annotation_results) ;
166
195
}
0 commit comments