Skip to content

Commit 0eb19e2

Browse files
committed
Merge branch 'main' of github.com:Artisan-Lab/RAPx
2 parents a493691 + 0cd3bd2 commit 0eb19e2

19 files changed

+1355
-574
lines changed

rapx/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ walkdir = "2"
3737
cargo_metadata = "0.18"
3838
annotate-snippets = "0.11.4"
3939
petgraph = "0.7.0"
40+
if_chain = "1.0"
4041

4142
[features]
4243
backtraces = ["snafu/backtraces", "snafu/backtraces-impl-backtrace-crate"]

rapx/src/analysis/senryx.rs

+76-47
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,124 @@
11
pub mod contracts;
2+
pub mod generic_check;
23
pub mod inter_record;
34
pub mod matcher;
45
pub mod visitor;
56

7+
use crate::analysis::utils::fn_info::*;
68
use crate::{
79
analysis::unsafety_isolation::{
810
hir_visitor::{ContainsUnsafe, RelatedFnCollector},
911
UnsafetyIsolationCheck,
1012
},
1113
rap_info, rap_warn,
1214
};
15+
use inter_record::InterAnalysisRecord;
1316
use rustc_hir::def_id::DefId;
1417
use rustc_middle::mir::{BasicBlock, Operand, TerminatorKind};
1518
use rustc_middle::ty;
1619
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};
2022

21-
use super::unsafety_isolation::generate_dot::UigUnit;
23+
pub enum CheckLevel {
24+
High,
25+
Medium,
26+
Low,
27+
}
2228

2329
pub struct SenryxCheck<'tcx> {
2430
pub tcx: TyCtxt<'tcx>,
2531
pub threshhold: usize,
32+
pub global_recorder: HashMap<DefId, InterAnalysisRecord<'tcx>>,
2633
}
2734

2835
impl<'tcx> SenryxCheck<'tcx> {
2936
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+
}
3142
}
3243

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() {
3749
for (body_id, _span) in vec {
3850
let (function_unsafe, block_unsafe) =
39-
ContainsUnsafe::contains_unsafe(self.tcx, *body_id);
51+
ContainsUnsafe::contains_unsafe(tcx, *body_id);
4052
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+
}
4156
if block_unsafe {
4257
self.check_soundness(def_id);
4358
}
4459
if function_unsafe {
45-
self.annotate_safety(def_id);
60+
// self.annotate_safety(def_id, &mut global_recorder);
4661
}
4762
}
4863
}
4964
}
5065

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+
}
5675
}
5776

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);
6282
}
63-
Self::show_annotate_results(self.tcx, def_id, annotation_results);
6483
}
6584

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+
}
85114

86-
pub fn body_visit_and_check(&self, def_id: DefId) {
115+
pub fn body_visit_and_check_uig(&self, def_id: DefId) {
87116
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);
89118
if func_type == 1 && self.get_annotation(def_id).len() > 0 {
90119
let func_cons = uig_checker.search_constructor(def_id);
91120
for func_con in func_cons {
92-
if UnsafetyIsolationCheck::check_safety(self.tcx, func_con) {
121+
if check_safety(self.tcx, func_con) {
93122
Self::show_annotate_results(self.tcx, func_con, self.get_annotation(def_id));
94123
// uphold safety to unsafe constructor
95124
}
@@ -119,8 +148,8 @@ impl<'tcx> SenryxCheck<'tcx> {
119148
} => match func {
120149
Operand::Constant(c) => match c.ty().kind() {
121150
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));
124153
} else {
125154
results.extend(self.get_annotation(*id));
126155
}
@@ -138,7 +167,7 @@ impl<'tcx> SenryxCheck<'tcx> {
138167
pub fn show_check_results(tcx: TyCtxt<'tcx>, def_id: DefId, check_results: Vec<CheckResult>) {
139168
rap_info!(
140169
"--------In safe function {:?}---------",
141-
UigUnit::get_cleaned_def_path_name(tcx, def_id)
170+
get_cleaned_def_path_name(tcx, def_id)
142171
);
143172
for check_result in check_results {
144173
rap_info!(
@@ -160,7 +189,7 @@ impl<'tcx> SenryxCheck<'tcx> {
160189
) {
161190
rap_info!(
162191
"--------In unsafe function {:?}---------",
163-
UigUnit::get_cleaned_def_path_name(tcx, def_id)
192+
get_cleaned_def_path_name(tcx, def_id)
164193
);
165194
rap_warn!("Lack safety annotations: {:?}.", annotation_results);
166195
}

rapx/src/analysis/senryx/contracts/abstract_state.rs

+30-25
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::{
33
hash::Hash,
44
};
55

6+
use crate::analysis::senryx::visitor::PlaceTy;
7+
68
use super::state_lattice::Lattice;
79

810
#[derive(Debug, PartialEq, PartialOrd, Copy, Clone)]
@@ -15,10 +17,10 @@ pub enum Value {
1517
// ...
1618
}
1719

18-
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
19-
pub enum StateType {
20+
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
21+
pub enum StateType<'tcx> {
2022
AllocatedState(AllocatedState),
21-
AlignState(AlignState),
23+
AlignState(AlignState<'tcx>),
2224
// ...
2325
}
2426

@@ -42,11 +44,10 @@ pub enum AllocatedState {
4244
Bottom,
4345
}
4446

45-
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
46-
pub enum AlignState {
47+
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
48+
pub enum AlignState<'tcx> {
4749
Aligned,
48-
Small2BigCast(usize, usize),
49-
Big2SmallCast(usize, usize),
50+
Cast(PlaceTy<'tcx>, PlaceTy<'tcx>),
5051
Unaligned,
5152
}
5253

@@ -56,30 +57,30 @@ pub enum InitState {
5657
PartlyInitialized,
5758
}
5859

59-
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
60-
pub enum VType {
61-
Pointer(usize, usize), // (align, size)
62-
// todo
60+
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
61+
pub enum VType<'tcx> {
62+
Pointer(PlaceTy<'tcx>),
63+
// todo
6364
}
6465

65-
#[derive(Debug, PartialEq, Clone)]
66-
pub struct AbstractStateItem {
66+
#[derive(Debug, Clone, PartialEq)]
67+
pub struct AbstractStateItem<'tcx> {
6768
pub value: (Value, Value),
68-
pub vtype: VType,
69-
pub state: HashSet<StateType>,
69+
pub vtype: VType<'tcx>,
70+
pub state: HashSet<StateType<'tcx>>,
7071
}
7172

72-
impl AbstractStateItem {
73-
pub fn new(value: (Value, Value), vtype: VType, state: HashSet<StateType>) -> Self {
73+
impl<'tcx> AbstractStateItem<'tcx> {
74+
pub fn new(value: (Value, Value), vtype: VType<'tcx>, state: HashSet<StateType<'tcx>>) -> Self {
7475
Self {
7576
value,
7677
vtype,
7778
state,
7879
}
7980
}
8081

81-
pub fn meet_state_item(&mut self, other_state: &AbstractStateItem) {
82-
let mut new_state = HashSet::new();
82+
pub fn meet_state_item(&mut self, other_state: &AbstractStateItem<'tcx>) {
83+
let mut new_state: HashSet<StateType<'tcx>> = HashSet::new();
8384

8485
// visit 'self.state' and 'other_state.state',matching states and calling meet method
8586
for state_self in &self.state {
@@ -92,14 +93,14 @@ impl AbstractStateItem {
9293
StateType::AllocatedState(s1.meet(*s2))
9394
}
9495
(StateType::AlignState(s1), StateType::AlignState(s2)) => {
95-
StateType::AlignState(s1.meet(*s2))
96+
StateType::AlignState(s1.meet(s2.clone()))
9697
}
9798
_ => continue,
9899
};
99100
new_state.insert(merged_state);
100101
} else {
101102
// if 'other_state' does not have the same state,then reserve the current state
102-
new_state.insert(*state_self);
103+
new_state.insert(state_self.clone());
103104
}
104105
}
105106

@@ -109,18 +110,22 @@ impl AbstractStateItem {
109110
}
110111

111112
#[derive(PartialEq)]
112-
pub struct AbstractState {
113-
pub state_map: HashMap<usize, Option<AbstractStateItem>>,
113+
pub struct AbstractState<'tcx> {
114+
pub state_map: HashMap<usize, Option<AbstractStateItem<'tcx>>>,
114115
}
115116

116-
impl AbstractState {
117+
impl<'tcx> AbstractState<'tcx> {
117118
pub fn new() -> Self {
118119
Self {
119120
state_map: HashMap::new(),
120121
}
121122
}
122123

123-
pub fn insert_abstate(&mut self, place: usize, place_state_item: Option<AbstractStateItem>) {
124+
pub fn insert_abstate(
125+
&mut self,
126+
place: usize,
127+
place_state_item: Option<AbstractStateItem<'tcx>>,
128+
) {
124129
self.state_map.insert(place, place_state_item);
125130
}
126131
}

rapx/src/analysis/senryx/contracts/checker.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ use core::mem;
44
use std::collections::HashMap;
55
use std::marker::PhantomData;
66

7-
pub trait Checker {
8-
fn variable_contracts(&self) -> &HashMap<usize, Vec<Contract>>;
7+
pub trait Checker<'tcx> {
8+
fn variable_contracts(&self) -> &HashMap<usize, Vec<Contract<'tcx>>>;
99
}
1010

11-
pub struct SliceFromRawPartsChecker<T> {
12-
pub variable_contracts: HashMap<usize, Vec<Contract>>,
11+
pub struct SliceFromRawPartsChecker<'tcx, T> {
12+
pub variable_contracts: HashMap<usize, Vec<Contract<'tcx>>>,
1313
_marker: PhantomData<T>,
1414
}
1515

16-
impl<T> Checker for SliceFromRawPartsChecker<T> {
17-
fn variable_contracts(&self) -> &HashMap<usize, Vec<Contract>> {
16+
impl<'tcx, T> Checker<'tcx> for SliceFromRawPartsChecker<'tcx, T> {
17+
fn variable_contracts(&self) -> &HashMap<usize, Vec<Contract<'tcx>>> {
1818
&self.variable_contracts
1919
}
2020
}
2121

22-
impl<T> SliceFromRawPartsChecker<T> {
22+
impl<'tcx, T> SliceFromRawPartsChecker<'tcx, T> {
2323
pub fn new() -> Self {
2424
let mut map = HashMap::new();
2525
map.insert(

0 commit comments

Comments
 (0)