Skip to content

Commit

Permalink
Merge pull request #75 from DiuDiu777/senryx
Browse files Browse the repository at this point in the history
Fix contracts checking bugs in senryx
  • Loading branch information
hxuhack authored Nov 16, 2024
2 parents 0c0057f + 13236de commit a32584e
Show file tree
Hide file tree
Showing 9 changed files with 321 additions and 148 deletions.
4 changes: 2 additions & 2 deletions rap/src/analysis/senryx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ impl<'tcx> SenryxCheck<'tcx> {
pub fn pre_handle_type(&self, def_id: DefId) {
let mut uig_checker = UnsafetyIsolationCheck::new(self.tcx);
let func_type = uig_checker.get_type(def_id);
let mut body_visitor = BodyVisitor::new(self.tcx, def_id, true);
let mut body_visitor = BodyVisitor::new(self.tcx, def_id, 0);
if func_type == 1 {
let func_cons = uig_checker.search_constructor(def_id);
for func_con in func_cons {
let mut cons_body_visitor = BodyVisitor::new(self.tcx, func_con, true);
let mut cons_body_visitor = BodyVisitor::new(self.tcx, func_con, 0);
cons_body_visitor.path_forward_check();
// TODO: cache fields' states

Expand Down
9 changes: 5 additions & 4 deletions rap/src/analysis/senryx/contracts/abstract_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ pub enum AllocatedState {
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum AlignState {
Aligned,
Small2BigCast,
Big2SmallCast,
Small2BigCast(usize, usize),
Big2SmallCast(usize, usize),
Unaligned,
}

#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
Expand Down Expand Up @@ -109,7 +110,7 @@ impl AbstractStateItem {

#[derive(PartialEq)]
pub struct AbstractState {
pub state_map: HashMap<usize, AbstractStateItem>,
pub state_map: HashMap<usize, Option<AbstractStateItem>>,
}

impl AbstractState {
Expand All @@ -119,7 +120,7 @@ impl AbstractState {
}
}

pub fn insert_abstate(&mut self, place: usize, place_state_item: AbstractStateItem) {
pub fn insert_abstate(&mut self, place: usize, place_state_item: Option<AbstractStateItem>) {
self.state_map.insert(place, place_state_item);
}
}
4 changes: 2 additions & 2 deletions rap/src/analysis/senryx/contracts/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ impl<T> SliceFromRawPartsChecker<T> {
state: StateType::AllocatedState(AllocatedState::Alloc),
},
Contract::StateCheck {
op: Op::NE,
state: StateType::AlignState(AlignState::Small2BigCast),
op: Op::GT,
state: StateType::AlignState(AlignState::Unaligned),
},
],
);
Expand Down
16 changes: 15 additions & 1 deletion rap/src/analysis/senryx/contracts/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ pub fn check_contract(contract: Contract, abstate_item: &AbstractStateItem) -> b
}
Contract::StateCheck { op, state } => {
for ab_state in &abstate_item.state {
if handle_state_op(*ab_state, op, state) {
if check_is_same_state_type(ab_state, &state)
&& handle_state_op(*ab_state, op, state)
{
return true;
}
}
Expand All @@ -23,6 +25,18 @@ pub fn check_contract(contract: Contract, abstate_item: &AbstractStateItem) -> b
}
}

pub fn check_is_same_state_type(left: &StateType, right: &StateType) -> bool {
match (*left, *right) {
(StateType::AllocatedState(_), StateType::AllocatedState(_)) => {
return true;
}
(StateType::AlignState(_), StateType::AlignState(_)) => {
return true;
}
_ => false,
}
}

pub fn handle_value_op<T: std::cmp::PartialEq + std::cmp::PartialOrd>(
left: &(T, T),
op: Op,
Expand Down
32 changes: 20 additions & 12 deletions rap/src/analysis/senryx/contracts/state_lattice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,27 +131,35 @@ impl Lattice for AlignState {
fn join(&self, other: Self) -> Self {
match (self, other) {
(AlignState::Aligned, _) => AlignState::Aligned,
(AlignState::Big2SmallCast, AlignState::Big2SmallCast) => AlignState::Big2SmallCast,
(AlignState::Big2SmallCast, AlignState::Small2BigCast) => AlignState::Big2SmallCast,
(AlignState::Big2SmallCast, AlignState::Aligned) => AlignState::Aligned,
(AlignState::Small2BigCast, _) => other,
(AlignState::Big2SmallCast(_, _), AlignState::Big2SmallCast(_, _)) => {
AlignState::Aligned
}
(AlignState::Big2SmallCast(_, _), AlignState::Small2BigCast(_, _)) => {
AlignState::Unaligned
}
(AlignState::Big2SmallCast(_, _), AlignState::Aligned) => AlignState::Aligned,
(AlignState::Unaligned, _) => AlignState::Unaligned,
(_, AlignState::Unaligned) => AlignState::Unaligned,
_ => other,
}
}

fn meet(&self, other: Self) -> Self {
match (self, other) {
(AlignState::Aligned, _) => other,
(AlignState::Big2SmallCast, AlignState::Big2SmallCast) => AlignState::Big2SmallCast,
(AlignState::Big2SmallCast, AlignState::Small2BigCast) => AlignState::Small2BigCast,
(AlignState::Big2SmallCast, AlignState::Aligned) => AlignState::Big2SmallCast,
(AlignState::Small2BigCast, _) => AlignState::Small2BigCast,
}
other
// match (self, other) {
// (AlignState::Aligned, _) => other,
// (AlignState::Big2SmallCast(_,_), AlignState::Big2SmallCast(_,_)) => AlignState::Aligned,
// (AlignState::Big2SmallCast(_,_), AlignState::Small2BigCast(_,_)) => AlignState::Unaligned,
// (AlignState::Big2SmallCast(_,_), AlignState::Aligned) => AlignState::Big2SmallCast(_,_),
// (AlignState::Small2BigCast, _) => AlignState::Small2BigCast,
// }
}

fn less_than(&self, other: Self) -> bool {
match (self, other) {
(_, AlignState::Aligned) => true,
(AlignState::Small2BigCast, AlignState::Big2SmallCast) => true,
(AlignState::Small2BigCast(_, _), AlignState::Big2SmallCast(_, _)) => true,
(AlignState::Small2BigCast(_, _), AlignState::Unaligned) => true,
_ => false,
}
}
Expand Down
13 changes: 8 additions & 5 deletions rap/src/analysis/senryx/inter_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,25 @@ lazy_static! {
// static mut GLOBAL_INTER_RECORDER: HashMap<DefId,InterAnalysisRecord> = HashMap::new();

pub struct InterAnalysisRecord {
pub pre_analysis_state: HashMap<usize, AbstractStateItem>,
pub post_analysis_state: HashMap<usize, AbstractStateItem>,
pub pre_analysis_state: HashMap<usize, Option<AbstractStateItem>>,
pub post_analysis_state: HashMap<usize, Option<AbstractStateItem>>,
}

impl InterAnalysisRecord {
pub fn new(
pre_analysis_state: HashMap<usize, AbstractStateItem>,
post_analysis_state: HashMap<usize, AbstractStateItem>,
pre_analysis_state: HashMap<usize, Option<AbstractStateItem>>,
post_analysis_state: HashMap<usize, Option<AbstractStateItem>>,
) -> Self {
Self {
pre_analysis_state,
post_analysis_state,
}
}

pub fn is_pre_state_same(&self, other_pre_state: &HashMap<usize, AbstractStateItem>) -> bool {
pub fn is_pre_state_same(
&self,
other_pre_state: &HashMap<usize, Option<AbstractStateItem>>,
) -> bool {
self.pre_analysis_state == *other_pre_state
}
}
4 changes: 2 additions & 2 deletions rap/src/analysis/senryx/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ fn process_checker(checker: &dyn Checker, args: &Box<[Spanned<Operand>]>, abstat
for contract in contracts_vec {
let arg_place = get_arg_place(&args[*idx].node);
if arg_place == 0 {
return;
continue;
}
if let Some(abstate_item) = abstate.state_map.get(&arg_place) {
if !check_contract(*contract, abstate_item) {
if !check_contract(*contract, &abstate_item.clone().unwrap()) {
println!("Contract failed! ---- {:?}", contract);
} else {
println!("Contract passed! ---- {:?}", contract);
Expand Down
Loading

0 comments on commit a32584e

Please sign in to comment.