Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
cwe_checker
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fact-depend
cwe_checker
Commits
decc1254
Unverified
Commit
decc1254
authored
2 years ago
by
van den Bosch
Committed by
GitHub
2 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Test refactoring collection (#386)
parent
dcbdac1e
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
603 additions
and
1274 deletions
+603
-1274
mod.rs
...we_checker_lib/src/analysis/expression_propagation/mod.rs
+124
-3
tests.rs
..._checker_lib/src/analysis/expression_propagation/tests.rs
+26
-0
forward_interprocedural_fixpoint.rs
...cker_lib/src/analysis/forward_interprocedural_fixpoint.rs
+2
-1
global_var_propagation.rs
...src/analysis/function_signature/global_var_propagation.rs
+2
-2
graph.rs
src/cwe_checker_lib/src/analysis/graph.rs
+5
-3
tests.rs
...ecker_lib/src/analysis/pointer_inference/context/tests.rs
+0
-0
tests.rs
...hecker_lib/src/analysis/pointer_inference/object/tests.rs
+2
-2
tests.rs
...r_lib/src/analysis/pointer_inference/object_list/tests.rs
+3
-2
mod.rs
...ker_lib/src/analysis/pointer_inference/state/tests/mod.rs
+3
-3
specialized_expressions.rs
.../pointer_inference/state/tests/specialized_expressions.rs
+2
-2
tests.rs
...er_lib/src/analysis/stack_alignment_substitution/tests.rs
+2
-6
memcpy.rs
...nalysis/string_abstraction/context/symbol_calls/memcpy.rs
+13
-12
scanf.rs
...analysis/string_abstraction/context/symbol_calls/scanf.rs
+13
-13
tests.rs
.../string_abstraction/context/symbol_calls/sprintf/tests.rs
+34
-46
strcat.rs
...nalysis/string_abstraction/context/symbol_calls/strcat.rs
+3
-4
tests.rs
...analysis/string_abstraction/context/symbol_calls/tests.rs
+9
-9
tests.rs
.../analysis/string_abstraction/context/trait_impls/tests.rs
+2
-2
tests.rs
...hecker_lib/src/analysis/string_abstraction/state/tests.rs
+30
-27
tests.rs
src/cwe_checker_lib/src/analysis/string_abstraction/tests.rs
+11
-55
state.rs
src/cwe_checker_lib/src/checkers/cwe_119/state.rs
+3
-3
blk.rs
src/cwe_checker_lib/src/intermediate_representation/blk.rs
+1
-227
def.rs
src/cwe_checker_lib/src/intermediate_representation/def.rs
+7
-38
builder.rs
...lib/src/intermediate_representation/expression/builder.rs
+0
-88
tests.rs
...r_lib/src/intermediate_representation/expression/tests.rs
+27
-37
jmp.rs
src/cwe_checker_lib/src/intermediate_representation/jmp.rs
+0
-20
mod.rs
...checker_lib/src/intermediate_representation/macros/mod.rs
+1
-1
mod.rs
src/cwe_checker_lib/src/intermediate_representation/mod.rs
+0
-44
program.rs
...we_checker_lib/src/intermediate_representation/program.rs
+0
-72
project.rs
...we_checker_lib/src/intermediate_representation/project.rs
+0
-69
propagate_control_flow.rs
...rmediate_representation/project/propagate_control_flow.rs
+4
-9
runtime_memory_image.rs
...b/src/intermediate_representation/runtime_memory_image.rs
+10
-87
sub.rs
src/cwe_checker_lib/src/intermediate_representation/sub.rs
+0
-229
term.rs
src/cwe_checker_lib/src/intermediate_representation/term.rs
+2
-1
builder.rs
...ecker_lib/src/intermediate_representation/term/builder.rs
+0
-60
builder_high_lvl.rs
.../src/intermediate_representation/term/builder_high_lvl.rs
+230
-0
builder_low_lvl.rs
...b/src/intermediate_representation/term/builder_low_lvl.rs
+0
-0
variable.rs
...e_checker_lib/src/intermediate_representation/variable.rs
+0
-15
tests.rs
...e_checker_lib/src/pcode/subregister_substitution/tests.rs
+16
-41
tests.rs
src/cwe_checker_lib/src/utils/arguments/tests.rs
+16
-41
No files found.
src/cwe_checker_lib/src/analysis/expression_propagation/mod.rs
View file @
decc1254
...
@@ -186,12 +186,12 @@ fn extract_results<'a>(
...
@@ -186,12 +186,12 @@ fn extract_results<'a>(
///
///
/// This uses the expression propagation of basic blocks, thus performs intra-basic-block insertion of expressions.
/// This uses the expression propagation of basic blocks, thus performs intra-basic-block insertion of expressions.
fn
insert_expressions
(
fn
insert_expressions
(
inser
a
tables
:
HashMap
<
Tid
,
HashMap
<
Variable
,
Expression
>>
,
insertables
:
HashMap
<
Tid
,
HashMap
<
Variable
,
Expression
>>
,
program
:
&
mut
Program
,
program
:
&
mut
Program
,
)
{
)
{
for
sub
in
program
.subs
.values_mut
()
{
for
sub
in
program
.subs
.values_mut
()
{
for
block
in
sub
.term.blocks
.iter_mut
()
{
for
block
in
sub
.term.blocks
.iter_mut
()
{
block
.propagate_input_expressions
(
insera
tables
.get
(
&
block
.tid
)
.cloned
());
propagate_input_expressions
(
block
,
inser
tables
.get
(
&
block
.tid
)
.cloned
());
}
}
}
}
}
}
...
@@ -200,11 +200,132 @@ fn insert_expressions(
...
@@ -200,11 +200,132 @@ fn insert_expressions(
fn
merge_same_var_assignments
(
project
:
&
mut
Project
)
{
fn
merge_same_var_assignments
(
project
:
&
mut
Project
)
{
for
sub
in
project
.program.term.subs
.values_mut
()
{
for
sub
in
project
.program.term.subs
.values_mut
()
{
for
blk
in
sub
.term.blocks
.iter_mut
()
{
for
blk
in
sub
.term.blocks
.iter_mut
()
{
blk
.merge_def_assignments_to_same_var
(
);
merge_def_assignments_to_same_var
(
blk
);
}
}
}
}
}
}
/// Wherever possible, substitute input variables of expressions
/// with the input expression that defines the input variable.
///
/// Note that substitution is only possible
/// if the input variables of the input expression itself did not change since the definition of said variable.
///
/// The expression propagation allows more dead stores to be removed during
/// [dead variable elimination](crate::analysis::dead_variable_elimination).
pub
fn
propagate_input_expressions
(
blk
:
&
mut
Term
<
Blk
>
,
apriori_insertable_expressions
:
Option
<
HashMap
<
Variable
,
Expression
>>
,
)
{
let
mut
insertable_expressions
=
HashMap
::
new
();
if
let
Some
(
insertables
)
=
apriori_insertable_expressions
{
insertable_expressions
=
insertables
;
}
for
def
in
blk
.term.defs
.iter_mut
()
{
match
&
mut
def
.term
{
Def
::
Assign
{
var
,
value
:
expression
,
}
=>
{
// insert known input expressions
for
(
input_var
,
input_expr
)
in
insertable_expressions
.iter
()
{
expression
.substitute_input_var
(
input_var
,
input_expr
);
}
// expressions dependent on the assigned variable are no longer insertable
insertable_expressions
.retain
(|
input_var
,
input_expr
|
{
input_var
!=
var
&&
!
input_expr
.input_vars
()
.into_iter
()
.any
(|
x
|
x
==
var
)
});
// If the value of the assigned variable does not depend on the former value of the variable,
// then it is insertable for future expressions.
if
!
expression
.input_vars
()
.into_iter
()
.any
(|
x
|
x
==
var
)
{
insertable_expressions
.insert
(
var
.clone
(),
expression
.clone
());
}
}
Def
::
Load
{
var
,
address
:
expression
,
}
=>
{
// insert known input expressions
for
(
input_var
,
input_expr
)
in
insertable_expressions
.iter
()
{
expression
.substitute_input_var
(
input_var
,
input_expr
);
}
// expressions dependent on the assigned variable are no longer insertable
insertable_expressions
.retain
(|
input_var
,
input_expr
|
{
input_var
!=
var
&&
!
input_expr
.input_vars
()
.into_iter
()
.any
(|
x
|
x
==
var
)
});
}
Def
::
Store
{
address
,
value
}
=>
{
// insert known input expressions
for
(
input_var
,
input_expr
)
in
insertable_expressions
.iter
()
{
address
.substitute_input_var
(
input_var
,
input_expr
);
value
.substitute_input_var
(
input_var
,
input_expr
);
}
}
}
}
for
jump
in
blk
.term.jmps
.iter_mut
()
{
match
&
mut
jump
.term
{
Jmp
::
Branch
(
_
)
|
Jmp
::
Call
{
..
}
|
Jmp
::
CallOther
{
..
}
=>
(),
Jmp
::
BranchInd
(
expr
)
|
Jmp
::
CBranch
{
condition
:
expr
,
..
}
|
Jmp
::
CallInd
{
target
:
expr
,
..
}
|
Jmp
::
Return
(
expr
)
=>
{
// insert known input expressions
for
(
input_var
,
input_expr
)
in
insertable_expressions
.iter
()
{
expr
.substitute_input_var
(
input_var
,
input_expr
);
}
}
}
}
}
/// Merge subsequent assignments to the same variable to a single assignment to that variable.
pub
fn
merge_def_assignments_to_same_var
(
blk
:
&
mut
Term
<
Blk
>
)
{
let
mut
new_defs
=
Vec
::
new
();
let
mut
last_def_opt
=
None
;
for
def
in
blk
.term.defs
.iter
()
{
if
let
Def
::
Assign
{
var
:
current_var
,
..
}
=
&
def
.term
{
if
let
Some
(
Term
{
term
:
Def
::
Assign
{
var
:
last_var
,
value
:
last_value
,
},
..
})
=
&
last_def_opt
{
if
current_var
==
last_var
{
let
mut
substituted_def
=
def
.clone
();
substituted_def
.substitute_input_var
(
last_var
,
last_value
);
last_def_opt
=
Some
(
substituted_def
);
}
else
{
new_defs
.push
(
last_def_opt
.unwrap
());
last_def_opt
=
Some
(
def
.clone
());
}
}
else
if
last_def_opt
.is_some
()
{
panic!
();
// Only assign-defs should be saved in last_def.
}
else
{
last_def_opt
=
Some
(
def
.clone
());
}
}
else
{
if
let
Some
(
last_def
)
=
last_def_opt
{
new_defs
.push
(
last_def
);
}
new_defs
.push
(
def
.clone
());
last_def_opt
=
None
;
}
}
if
let
Some
(
last_def
)
=
last_def_opt
{
new_defs
.push
(
last_def
);
}
blk
.term.defs
=
new_defs
;
}
/// Replaces variables by expressions that can be propagated within functions.
/// Replaces variables by expressions that can be propagated within functions.
///
///
/// This is performed by a fixpoint computation and might panic, if it does not stabilize.
/// This is performed by a fixpoint computation and might panic, if it does not stabilize.
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/expression_propagation/tests.rs
View file @
decc1254
...
@@ -95,6 +95,32 @@ fn get_mock_entry_block() -> Term<Blk> {
...
@@ -95,6 +95,32 @@ fn get_mock_entry_block() -> Term<Blk> {
}
}
#[test]
#[test]
fn
expression_propagation
()
{
use
super
::
*
;
let
defs
=
defs!
[
"tid_1: X:8 = -(Y:8)"
,
"tid_2: Y:8 = X:8 + Y:8"
,
"tid_3: X:8 = -(X:8)"
,
"tid_4: Y:8 = -(Y:8)"
,
"tid_5: Y:8 = X:8 + Y:8"
];
let
block
=
&
mut
Blk
::
mock
();
block
.term.defs
=
defs
;
merge_def_assignments_to_same_var
(
block
);
propagate_input_expressions
(
block
,
None
);
let
result_defs
=
defs!
[
"tid_1: X:8 = -(Y:8)"
,
"tid_2: Y:8 = -(Y:8) + Y:8"
,
"tid_3: X:8 = -(X:8)"
,
"tid_5: Y:8 = X:8 + -(Y:8)"
];
assert_eq!
(
block
.term.defs
,
result_defs
);
}
#[test]
/// Tests the propagation of insertable expressions among basic blocks.
/// Tests the propagation of insertable expressions among basic blocks.
fn
inter_block_propagation
()
{
fn
inter_block_propagation
()
{
let
mut
project
=
mock_project
();
let
mut
project
=
mock_project
();
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/forward_interprocedural_fixpoint.rs
View file @
decc1254
...
@@ -333,6 +333,7 @@ mod tests {
...
@@ -333,6 +333,7 @@ mod tests {
create_computation_with_top_down_worklist_order
,
create_computation_with_top_down_worklist_order
,
},
},
},
},
expr
,
intermediate_representation
::
*
,
intermediate_representation
::
*
,
};
};
use
std
::
collections
::{
BTreeMap
,
HashMap
,
HashSet
};
use
std
::
collections
::{
BTreeMap
,
HashMap
,
HashSet
};
...
@@ -353,7 +354,7 @@ mod tests {
...
@@ -353,7 +354,7 @@ mod tests {
let
mut
callee_block
=
new_block
(
"callee block"
);
let
mut
callee_block
=
new_block
(
"callee block"
);
callee_block
.term.jmps
.push
(
Term
{
callee_block
.term.jmps
.push
(
Term
{
tid
:
Tid
::
new
(
"ret"
),
tid
:
Tid
::
new
(
"ret"
),
term
:
Jmp
::
Return
(
Expression
::
const_from_i32
(
42
)),
term
:
Jmp
::
Return
(
expr!
(
"42:4"
)),
});
});
let
called_function
=
Term
{
let
called_function
=
Term
{
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/function_signature/global_var_propagation.rs
View file @
decc1254
...
@@ -235,14 +235,14 @@ pub mod tests {
...
@@ -235,14 +235,14 @@ pub mod tests {
// main -> callee1 -> callee2
// main -> callee1 -> callee2
let
mut
func
=
Sub
::
mock
(
"main"
);
let
mut
func
=
Sub
::
mock
(
"main"
);
let
mut
call_blk
=
Blk
::
mock_with_tid
(
"main_blk"
);
let
mut
call_blk
=
Blk
::
mock_with_tid
(
"main_blk"
);
let
call
=
Jmp
::
mock_call
(
"callee1"
,
None
);
let
call
=
Jmp
::
call
(
"call_callee1"
,
"callee1"
,
None
);
call_blk
.term.jmps
.push
(
call
);
call_blk
.term.jmps
.push
(
call
);
func
.term.blocks
.push
(
call_blk
);
func
.term.blocks
.push
(
call_blk
);
project
.program.term.subs
.insert
(
Tid
::
new
(
"main"
),
func
);
project
.program.term.subs
.insert
(
Tid
::
new
(
"main"
),
func
);
let
mut
func
=
Sub
::
mock
(
"callee1"
);
let
mut
func
=
Sub
::
mock
(
"callee1"
);
let
mut
call_blk
=
Blk
::
mock_with_tid
(
"callee1_blk"
);
let
mut
call_blk
=
Blk
::
mock_with_tid
(
"callee1_blk"
);
let
call
=
Jmp
::
mock_call
(
"callee2"
,
None
);
let
call
=
Jmp
::
call
(
"call_callee2"
,
"callee2"
,
None
);
call_blk
.term.jmps
.push
(
call
);
call_blk
.term.jmps
.push
(
call
);
func
.term.blocks
.push
(
call_blk
);
func
.term.blocks
.push
(
call_blk
);
project
.program.term.subs
.insert
(
Tid
::
new
(
"callee1"
),
func
);
project
.program.term.subs
.insert
(
Tid
::
new
(
"callee1"
),
func
);
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/graph.rs
View file @
decc1254
...
@@ -512,6 +512,8 @@ pub fn get_entry_nodes_of_subs(graph: &Graph) -> HashMap<Tid, NodeIndex> {
...
@@ -512,6 +512,8 @@ pub fn get_entry_nodes_of_subs(graph: &Graph) -> HashMap<Tid, NodeIndex> {
#[cfg(test)]
#[cfg(test)]
mod
tests
{
mod
tests
{
use
crate
::
expr
;
use
super
::
*
;
use
super
::
*
;
use
std
::
collections
::{
BTreeMap
,
BTreeSet
};
use
std
::
collections
::{
BTreeMap
,
BTreeSet
};
use
std
::
iter
::
FromIterator
;
use
std
::
iter
::
FromIterator
;
...
@@ -526,7 +528,7 @@ mod tests {
...
@@ -526,7 +528,7 @@ mod tests {
};
};
let
return_term
=
Term
{
let
return_term
=
Term
{
tid
:
Tid
::
new
(
"return"
.to_string
()),
tid
:
Tid
::
new
(
"return"
.to_string
()),
term
:
Jmp
::
Return
(
Expression
::
Const
(
Bitvector
::
zero
(
64
.into
())
)),
// The return term does not matter
term
:
Jmp
::
Return
(
expr!
(
"0:8"
)),
// The return term does not matter
};
};
let
jmp
=
Jmp
::
Branch
(
Tid
::
new
(
"sub1_blk1"
));
let
jmp
=
Jmp
::
Branch
(
Tid
::
new
(
"sub1_blk1"
));
let
jmp_term
=
Term
{
let
jmp_term
=
Term
{
...
@@ -559,7 +561,7 @@ mod tests {
...
@@ -559,7 +561,7 @@ mod tests {
};
};
let
cond_jump
=
Jmp
::
CBranch
{
let
cond_jump
=
Jmp
::
CBranch
{
target
:
Tid
::
new
(
"sub1_blk1"
),
target
:
Tid
::
new
(
"sub1_blk1"
),
condition
:
Expression
::
Const
(
Bitvector
::
from_u8
(
0
)
),
condition
:
expr!
(
"0:1"
),
};
};
let
cond_jump_term
=
Term
{
let
cond_jump_term
=
Term
{
tid
:
Tid
::
new
(
"cond_jump"
),
tid
:
Tid
::
new
(
"cond_jump"
),
...
@@ -618,7 +620,7 @@ mod tests {
...
@@ -618,7 +620,7 @@ mod tests {
fn
add_indirect_jumps
()
{
fn
add_indirect_jumps
()
{
let
indirect_jmp_term
=
Term
{
let
indirect_jmp_term
=
Term
{
tid
:
Tid
::
new
(
"indrect_jmp"
.to_string
()),
tid
:
Tid
::
new
(
"indrect_jmp"
.to_string
()),
term
:
Jmp
::
BranchInd
(
Expression
::
Const
(
Bitvector
::
from_u32
(
0x1000
)
)),
// At the moment the expression does not matter
term
:
Jmp
::
BranchInd
(
expr!
(
"0x1000:4"
)),
// At the moment the expression does not matter
};
};
let
mut
blk_tid
=
Tid
::
new
(
"blk_00001000"
);
let
mut
blk_tid
=
Tid
::
new
(
"blk_00001000"
);
blk_tid
.address
=
"00001000"
.to_string
();
blk_tid
.address
=
"00001000"
.to_string
();
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/pointer_inference/context/tests.rs
View file @
decc1254
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/pointer_inference/object/tests.rs
View file @
decc1254
use
super
::
*
;
use
super
::
*
;
use
crate
::
intermediate_representation
::
Variable
;
use
crate
::
{
intermediate_representation
::
*
,
variable
}
;
use
std
::
collections
::
BTreeMap
;
use
std
::
collections
::
BTreeMap
;
fn
new_abstract_object
()
->
AbstractObject
{
fn
new_abstract_object
()
->
AbstractObject
{
...
@@ -23,7 +23,7 @@ fn bv(number: i64) -> ValueDomain {
...
@@ -23,7 +23,7 @@ fn bv(number: i64) -> ValueDomain {
fn
new_id
(
tid
:
&
str
,
reg_name
:
&
str
)
->
AbstractIdentifier
{
fn
new_id
(
tid
:
&
str
,
reg_name
:
&
str
)
->
AbstractIdentifier
{
AbstractIdentifier
::
new
(
AbstractIdentifier
::
new
(
Tid
::
new
(
tid
),
Tid
::
new
(
tid
),
AbstractLocation
::
Register
(
Variable
::
mock
(
reg_name
,
ByteSize
::
new
(
8
))),
AbstractLocation
::
Register
(
variable!
(
format!
(
"{reg_name}:8"
))),
)
)
}
}
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/pointer_inference/object_list/tests.rs
View file @
decc1254
use
crate
::
intermediate_representation
::
Variable
;
use
crate
::
intermediate_representation
::
*
;
use
crate
::
variable
;
use
super
::
super
::
ValueDomain
;
use
super
::
super
::
ValueDomain
;
use
super
::
*
;
use
super
::
*
;
...
@@ -10,7 +11,7 @@ fn bv(value: i64) -> ValueDomain {
...
@@ -10,7 +11,7 @@ fn bv(value: i64) -> ValueDomain {
fn
new_id
(
name
:
&
str
)
->
AbstractIdentifier
{
fn
new_id
(
name
:
&
str
)
->
AbstractIdentifier
{
AbstractIdentifier
::
new
(
AbstractIdentifier
::
new
(
Tid
::
new
(
"time0"
),
Tid
::
new
(
"time0"
),
AbstractLocation
::
Register
(
Variable
::
mock
(
name
,
ByteSize
::
new
(
8
))),
AbstractLocation
::
Register
(
variable!
(
format!
(
"{name}:8"
))),
)
)
}
}
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/pointer_inference/state/tests/mod.rs
View file @
decc1254
...
@@ -316,7 +316,7 @@ fn test_widening_hints_after_pointer_specialization() {
...
@@ -316,7 +316,7 @@ fn test_widening_hints_after_pointer_specialization() {
.add_signed_greater_equal_bound
(
&
Bitvector
::
from_i64
(
6
))
.add_signed_greater_equal_bound
(
&
Bitvector
::
from_i64
(
6
))
.unwrap
();
.unwrap
();
let
expected_val
=
Data
::
from_target
(
new_id
(
"func_tid"
,
"RSP"
),
offset_with_lower_bound
);
let
expected_val
=
Data
::
from_target
(
new_id
(
"func_tid"
,
"RSP"
),
offset_with_lower_bound
);
assert_eq!
(
state
.get_register
(
&
Variable
::
mock
(
"RBX"
,
8
)),
expected_val
);
assert_eq!
(
state
.get_register
(
&
variable!
(
"RBX:8"
)),
expected_val
);
}
}
#[test]
#[test]
...
@@ -363,11 +363,11 @@ fn from_fn_sig() {
...
@@ -363,11 +363,11 @@ fn from_fn_sig() {
Data
::
from_target
(
new_id
(
"func"
,
"RSP"
),
bv
(
0
)
.into
())
Data
::
from_target
(
new_id
(
"func"
,
"RSP"
),
bv
(
0
)
.into
())
);
);
assert_eq!
(
assert_eq!
(
state
.get_register
(
&
Variable
::
mock
(
"RDI"
,
8
)),
state
.get_register
(
&
variable!
(
"RDI:8"
)),
Data
::
from_target
(
new_id
(
"func"
,
"RDI"
),
bv
(
0
)
.into
())
Data
::
from_target
(
new_id
(
"func"
,
"RDI"
),
bv
(
0
)
.into
())
);
);
assert_eq!
(
assert_eq!
(
state
.get_register
(
&
Variable
::
mock
(
"RSI"
,
8
)),
state
.get_register
(
&
variable!
(
"RSI:8"
)),
Data
::
from_target
(
new_id
(
"func"
,
"RSI"
),
bv
(
0
)
.into
())
Data
::
from_target
(
new_id
(
"func"
,
"RSI"
),
bv
(
0
)
.into
())
);
);
}
}
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/pointer_inference/state/tests/specialized_expressions.rs
View file @
decc1254
...
@@ -167,11 +167,11 @@ fn specialize_by_binop() {
...
@@ -167,11 +167,11 @@ fn specialize_by_binop() {
);
);
assert
!
(
x
.is_ok
());
assert
!
(
x
.is_ok
());
assert_eq!
(
assert_eq!
(
state
.get_register
(
&
Variable
::
mock
(
"FLAG1"
,
1u64
)),
state
.get_register
(
&
variable!
(
"FLAG1:1"
)),
bitvec!
(
"1:1"
)
.into
()
bitvec!
(
"1:1"
)
.into
()
);
);
assert_eq!
(
assert_eq!
(
state
.get_register
(
&
Variable
::
mock
(
"FLAG2"
,
1u64
)),
state
.get_register
(
&
variable!
(
"FLAG2:1"
)),
bitvec!
(
"1:1"
)
.into
()
bitvec!
(
"1:1"
)
.into
()
);
);
// Expr = (FLAG bool_and 1 = Const)
// Expr = (FLAG bool_and 1 = Const)
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/stack_alignment_substitution/tests.rs
View file @
decc1254
...
@@ -285,9 +285,7 @@ fn supports_commutative_and() {
...
@@ -285,9 +285,7 @@ fn supports_commutative_and() {
Expression
::
BinOp
{
Expression
::
BinOp
{
op
:
BinOpType
::
IntAnd
,
op
:
BinOpType
::
IntAnd
,
lhs
:
Box
::
new
(
expr!
(
"RSP:8"
)),
lhs
:
Box
::
new
(
expr!
(
"RSP:8"
)),
rhs
:
Box
::
new
(
Expression
::
const_from_apint
(
ApInt
::
from_u64
(
rhs
:
Box
::
new
(
expr!
(
format!
(
"{}:8"
,
0xFFFFFFFF
_FFFFFFFF_u64
<<
4
))),
0xFFFFFFFF
_FFFFFFFF
<<
4
,
// 16 Byte alignment
))),
},
},
);
);
let
bitmask_and_var
=
Def
::
assign
(
let
bitmask_and_var
=
Def
::
assign
(
...
@@ -330,9 +328,7 @@ fn skips_empty_blocks() {
...
@@ -330,9 +328,7 @@ fn skips_empty_blocks() {
lhs
:
Box
::
new
(
Expression
::
Var
(
lhs
:
Box
::
new
(
Expression
::
Var
(
Project
::
mock_x64
()
.stack_pointer_register
.clone
(),
Project
::
mock_x64
()
.stack_pointer_register
.clone
(),
)),
)),
rhs
:
Box
::
new
(
Expression
::
const_from_apint
(
ApInt
::
from_u64
(
rhs
:
Box
::
new
(
expr!
(
format!
(
"{}:8"
,
0xFFFFFFFF
_FFFFFFFF_u64
<<
4
))),
0xFFFFFFFF
_FFFFFFFF
<<
4
,
// 16 Byte alignment
))),
},
},
);
);
// get project with empty block
// get project with empty block
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/context/symbol_calls/memcpy.rs
View file @
decc1254
...
@@ -7,7 +7,7 @@ use crate::{
...
@@ -7,7 +7,7 @@ use crate::{
AbstractDomain
,
DataDomain
,
DomainInsertion
,
HasTop
,
IntervalDomain
,
TryToBitvec
,
AbstractDomain
,
DataDomain
,
DomainInsertion
,
HasTop
,
IntervalDomain
,
TryToBitvec
,
},
},
analysis
::
string_abstraction
::{
context
::
Context
,
state
::
State
},
analysis
::
string_abstraction
::{
context
::
Context
,
state
::
State
},
intermediate_representation
::
ExternSymbol
,
intermediate_representation
::
*
,
};
};
use
std
::
collections
::
BTreeMap
;
use
std
::
collections
::
BTreeMap
;
...
@@ -206,7 +206,8 @@ mod tests {
...
@@ -206,7 +206,8 @@ mod tests {
context
::
symbol_calls
::
tests
::
Setup
,
context
::
symbol_calls
::
tests
::
Setup
,
tests
::
mock_project_with_intraprocedural_control_flow
,
tests
::
mock_project_with_intraprocedural_control_flow
,
},
},
intermediate_representation
::{
Bitvector
,
Tid
,
Variable
},
intermediate_representation
::{
Bitvector
,
Tid
},
variable
,
};
};
use
std
::
collections
::{
BTreeMap
,
BTreeSet
};
use
std
::
collections
::{
BTreeMap
,
BTreeSet
};
...
@@ -226,12 +227,12 @@ mod tests {
...
@@ -226,12 +227,12 @@ mod tests {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
heap_id
=
AbstractIdentifier
::
new
(
let
heap_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r5"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r5:4"
))
.unwrap
(),
);
);
let
mut
parameter_pointer
:
DataDomain
<
IntervalDomain
>
=
let
mut
parameter_pointer
:
DataDomain
<
IntervalDomain
>
=
...
@@ -250,7 +251,7 @@ mod tests {
...
@@ -250,7 +251,7 @@ mod tests {
setup
setup
.pi_state_before_symbol_call
.pi_state_before_symbol_call
.set_register
(
&
Variable
::
mock
(
"r1"
,
4
),
parameter_pointer
);
.set_register
(
&
variable!
(
"r1:4"
),
parameter_pointer
);
setup
setup
.state_before_call
.state_before_call
...
@@ -314,7 +315,7 @@ mod tests {
...
@@ -314,7 +315,7 @@ mod tests {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
expected_data
:
DataDomain
<
IntervalDomain
>
=
let
expected_data
:
DataDomain
<
IntervalDomain
>
=
...
@@ -365,12 +366,12 @@ mod tests {
...
@@ -365,12 +366,12 @@ mod tests {
let
return_targets
=
setup
let
return_targets
=
setup
.pi_state_before_symbol_call
.pi_state_before_symbol_call
.get_register
(
&
Variable
::
mock
(
"r0"
,
4
));
.get_register
(
&
variable!
(
"r0:4"
));
let
input_target
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
let
input_target
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
setup
setup
.pi_state_before_symbol_call
.pi_state_before_symbol_call
.get_register
(
&
Variable
::
mock
(
"r1"
,
4
))
.get_register
(
&
variable!
(
"r1:4"
))
.get_absolute_value
()
.get_absolute_value
()
.unwrap
()
.unwrap
()
.clone
(),
.clone
(),
...
@@ -407,14 +408,14 @@ mod tests {
...
@@ -407,14 +408,14 @@ mod tests {
let
return_targets
=
setup
let
return_targets
=
setup
.pi_state_before_symbol_call
.pi_state_before_symbol_call
.get_register
(
&
Variable
::
mock
(
"r0"
,
4
))
.get_register
(
&
variable!
(
"r0:4"
))
.get_relative_values
()
.get_relative_values
()
.clone
();
.clone
();
let
input_target
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
let
input_target
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
setup
setup
.pi_state_before_symbol_call
.pi_state_before_symbol_call
.get_register
(
&
Variable
::
mock
(
"r1"
,
4
))
.get_register
(
&
variable!
(
"r1:4"
))
.get_absolute_value
()
.get_absolute_value
()
.unwrap
()
.unwrap
()
.clone
(),
.clone
(),
...
@@ -462,11 +463,11 @@ mod tests {
...
@@ -462,11 +463,11 @@ mod tests {
fn
test_has_multiple_targets
()
{
fn
test_has_multiple_targets
()
{
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
heap_id
=
AbstractIdentifier
::
new
(
let
heap_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r5"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r5:4"
))
.unwrap
(),
);
);
// Test Case 1: Only one relative target.
// Test Case 1: Only one relative target.
let
mut
data
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
mock_from_target_map
(
let
mut
data
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
mock_from_target_map
(
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/context/symbol_calls/scanf.rs
View file @
decc1254
...
@@ -199,7 +199,7 @@ mod tests {
...
@@ -199,7 +199,7 @@ mod tests {
use
crate
::
abstract_domain
::{
AbstractIdentifier
,
AbstractLocation
,
CharacterInclusionDomain
};
use
crate
::
abstract_domain
::{
AbstractIdentifier
,
AbstractLocation
,
CharacterInclusionDomain
};
use
crate
::
analysis
::
pointer_inference
::
PointerInference
as
PointerInferenceComputation
;
use
crate
::
analysis
::
pointer_inference
::
PointerInference
as
PointerInferenceComputation
;
use
crate
::
analysis
::
string_abstraction
::
tests
::
mock_project_with_intraprocedural_control_flow
;
use
crate
::
analysis
::
string_abstraction
::
tests
::
mock_project_with_intraprocedural_control_flow
;
use
crate
::
intermediate_representation
::{
Expression
,
V
ariable
};
use
crate
::
{
expr
,
intermediate_representation
::
*
,
v
ariable
};
#[test]
#[test]
fn
test_handle_scanf_calls
()
{
fn
test_handle_scanf_calls
()
{
...
@@ -222,7 +222,7 @@ mod tests {
...
@@ -222,7 +222,7 @@ mod tests {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
assert
!
(
new_state
assert
!
(
new_state
...
@@ -285,7 +285,7 @@ mod tests {
...
@@ -285,7 +285,7 @@ mod tests {
#[test]
#[test]
fn
test_create_abstract_domain_entries_for_function_return_values_with_known_values
()
{
fn
test_create_abstract_domain_entries_for_function_return_values_with_known_values
()
{
let
r2_reg
=
Variable
::
mock
(
"r2"
,
4
);
let
r2_reg
=
variable!
(
"r2:4"
);
let
sscanf_symbol
=
ExternSymbol
::
mock_sscanf_symbol_arm
();
let
sscanf_symbol
=
ExternSymbol
::
mock_sscanf_symbol_arm
();
let
project
=
mock_project_with_intraprocedural_control_flow
(
let
project
=
mock_project_with_intraprocedural_control_flow
(
...
@@ -299,7 +299,7 @@ mod tests {
...
@@ -299,7 +299,7 @@ mod tests {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
mut
arg_to_value_map
:
HashMap
<
Arg
,
Option
<
String
>>
=
HashMap
::
new
();
let
mut
arg_to_value_map
:
HashMap
<
Arg
,
Option
<
String
>>
=
HashMap
::
new
();
...
@@ -309,7 +309,7 @@ mod tests {
...
@@ -309,7 +309,7 @@ mod tests {
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
};
};
let
stack_arg
=
Arg
::
Stack
{
let
stack_arg
=
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"sp"
,
4
)
),
address
:
expr!
(
"sp:4"
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
};
};
...
@@ -361,7 +361,7 @@ mod tests {
...
@@ -361,7 +361,7 @@ mod tests {
#[test]
#[test]
fn
test_create_abstract_domain_entries_for_function_return_values_with_unknown_values
()
{
fn
test_create_abstract_domain_entries_for_function_return_values_with_unknown_values
()
{
let
r1_reg
=
Variable
::
mock
(
"r1"
,
4
);
let
r1_reg
=
variable!
(
"r1:4"
);
let
scanf_symbol
=
ExternSymbol
::
mock_scanf_symbol_arm
();
let
scanf_symbol
=
ExternSymbol
::
mock_scanf_symbol_arm
();
let
project
=
mock_project_with_intraprocedural_control_flow
(
let
project
=
mock_project_with_intraprocedural_control_flow
(
...
@@ -375,7 +375,7 @@ mod tests {
...
@@ -375,7 +375,7 @@ mod tests {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
mut
arg_to_value_map
:
HashMap
<
Arg
,
Option
<
String
>>
=
HashMap
::
new
();
let
mut
arg_to_value_map
:
HashMap
<
Arg
,
Option
<
String
>>
=
HashMap
::
new
();
...
@@ -384,7 +384,7 @@ mod tests {
...
@@ -384,7 +384,7 @@ mod tests {
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
};
};
let
stack_arg
=
Arg
::
Stack
{
let
stack_arg
=
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"sp"
,
4
)
),
address
:
expr!
(
"sp:4"
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
};
};
...
@@ -448,7 +448,7 @@ mod tests {
...
@@ -448,7 +448,7 @@ mod tests {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
return_target
:
DataDomain
<
IntervalDomain
>
=
let
return_target
:
DataDomain
<
IntervalDomain
>
=
...
@@ -532,7 +532,7 @@ mod tests {
...
@@ -532,7 +532,7 @@ mod tests {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
new_state
=
setup
let
new_state
=
setup
...
@@ -585,7 +585,7 @@ mod tests {
...
@@ -585,7 +585,7 @@ mod tests {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
new_state
=
setup
let
new_state
=
setup
...
@@ -734,7 +734,7 @@ mod tests {
...
@@ -734,7 +734,7 @@ mod tests {
),
),
(
(
Arg
::
Stack
{
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"sp"
,
4
)
),
address
:
expr!
(
"sp:4"
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
},
},
...
@@ -742,7 +742,7 @@ mod tests {
...
@@ -742,7 +742,7 @@ mod tests {
),
),
(
(
Arg
::
Stack
{
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"sp"
,
4
))
.plus_const
(
4
),
address
:
expr!
(
"sp:4 + 4:4"
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
},
},
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/context/symbol_calls/sprintf/tests.rs
View file @
decc1254
...
@@ -3,13 +3,13 @@ use std::collections::BTreeSet;
...
@@ -3,13 +3,13 @@ use std::collections::BTreeSet;
use
super
::
*
;
use
super
::
*
;
use
crate
::
abstract_domain
::{
AbstractIdentifier
,
AbstractLocation
};
use
crate
::
abstract_domain
::{
AbstractIdentifier
,
AbstractLocation
};
use
crate
::
analysis
::
pointer_inference
::
PointerInference
as
PointerInferenceComputation
;
use
crate
::
analysis
::
pointer_inference
::
PointerInference
as
PointerInferenceComputation
;
use
crate
::
intermediate_representation
::{
Bitvector
,
Expression
,
Tid
,
Variable
};
use
crate
::{
use
crate
::{
abstract_domain
::{
CharacterInclusionDomain
,
CharacterSet
},
abstract_domain
::{
CharacterInclusionDomain
,
CharacterSet
},
analysis
::
string_abstraction
::{
analysis
::
string_abstraction
::{
context
::
symbol_calls
::
tests
::
Setup
,
tests
::
mock_project_with_intraprocedural_control_flow
,
context
::
symbol_calls
::
tests
::
Setup
,
tests
::
mock_project_with_intraprocedural_control_flow
,
},
},
};
};
use
crate
::{
bitvec
,
expr
,
intermediate_representation
::
*
,
variable
};
#[test]
#[test]
fn
test_handle_sprintf_and_snprintf_calls
()
{
fn
test_handle_sprintf_and_snprintf_calls
()
{
...
@@ -29,10 +29,10 @@ fn test_handle_sprintf_and_snprintf_calls() {
...
@@ -29,10 +29,10 @@ fn test_handle_sprintf_and_snprintf_calls() {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
return_pointer
:
DataDomain
<
IntervalDomain
>
=
let
return_pointer
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
stack_id
,
IntervalDomain
::
from
(
Bitvector
::
from_i32
(
-
84
)));
DataDomain
::
from_target
(
stack_id
,
IntervalDomain
::
from
(
bitvec!
(
"-84:4"
)));
assert_eq!
(
assert_eq!
(
return_pointer
,
return_pointer
,
...
@@ -68,10 +68,10 @@ fn test_parse_format_string_and_add_new_string_domain() {
...
@@ -68,10 +68,10 @@ fn test_parse_format_string_and_add_new_string_domain() {
let
format_string_index
:
usize
=
1
;
let
format_string_index
:
usize
=
1
;
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
return_pointer
:
DataDomain
<
IntervalDomain
>
=
let
return_pointer
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
stack_id
,
IntervalDomain
::
from
(
Bitvector
::
from_i32
(
-
84
)));
DataDomain
::
from_target
(
stack_id
,
IntervalDomain
::
from
(
bitvec!
(
"-84:4"
)));
let
project
=
mock_project_with_intraprocedural_control_flow
(
let
project
=
mock_project_with_intraprocedural_control_flow
(
vec!
[(
sprintf_symbol
.clone
(),
vec!
[
true
])],
vec!
[(
sprintf_symbol
.clone
(),
vec!
[
true
])],
...
@@ -174,15 +174,15 @@ fn test_create_string_domain_using_data_type_approximations() {
...
@@ -174,15 +174,15 @@ fn test_create_string_domain_using_data_type_approximations() {
fn
test_create_string_domain_using_constants_and_sub_domains
()
{
fn
test_create_string_domain_using_constants_and_sub_domains
()
{
let
sprintf_symbol
=
ExternSymbol
::
mock_sprintf_symbol_arm
();
let
sprintf_symbol
=
ExternSymbol
::
mock_sprintf_symbol_arm
();
let
string_arg
=
Arg
::
Register
{
let
string_arg
=
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"r6"
,
4
)),
expr
:
Expression
::
Var
(
variable!
(
"r6:4"
)),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
};
};
let
integer_arg
=
Arg
::
Register
{
let
integer_arg
=
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"r7"
,
4
)),
expr
:
Expression
::
Var
(
variable!
(
"r7:4"
)),
data_type
:
Some
(
Datatype
::
Integer
),
data_type
:
Some
(
Datatype
::
Integer
),
};
};
let
char_arg
=
Arg
::
Register
{
let
char_arg
=
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"r8"
,
4
)),
expr
:
Expression
::
Var
(
variable!
(
"r8:4"
)),
data_type
:
Some
(
Datatype
::
Char
),
data_type
:
Some
(
Datatype
::
Char
),
};
};
...
@@ -199,27 +199,21 @@ fn test_create_string_domain_using_constants_and_sub_domains() {
...
@@ -199,27 +199,21 @@ fn test_create_string_domain_using_constants_and_sub_domains() {
let
mut
setup
:
Setup
<
CharacterInclusionDomain
>
=
Setup
::
new
(
&
pi_results
);
let
mut
setup
:
Setup
<
CharacterInclusionDomain
>
=
Setup
::
new
(
&
pi_results
);
setup
.pi_state_before_symbol_call
.set_register
(
setup
.pi_state_before_symbol_call
.set_register
(
&
Variable
::
mock
(
"r6"
,
4
),
&
variable!
(
"r6:4"
),
DataDomain
::
from
(
IntervalDomain
::
new
(
DataDomain
::
from
(
IntervalDomain
::
new
(
Bitvector
::
from_u64
(
0x3002
),
bitvec!
(
"0x3002:8"
),
Bitvector
::
from_u64
(
0x3002
),
bitvec!
(
"0x3002:8"
),
)),
)),
);
);
setup
.pi_state_before_symbol_call
.set_register
(
setup
.pi_state_before_symbol_call
.set_register
(
&
Variable
::
mock
(
"r7"
,
4
),
&
variable!
(
"r7:4"
),
DataDomain
::
from
(
IntervalDomain
::
new
(
DataDomain
::
from
(
IntervalDomain
::
new
(
bitvec!
(
"2:8"
),
bitvec!
(
"2:8"
))),
Bitvector
::
from_u64
(
2
),
Bitvector
::
from_u64
(
2
),
)),
);
);
setup
.pi_state_before_symbol_call
.set_register
(
setup
.pi_state_before_symbol_call
.set_register
(
&
Variable
::
mock
(
"r8"
,
4
),
&
variable!
(
"r8:4"
),
DataDomain
::
from
(
IntervalDomain
::
new
(
DataDomain
::
from
(
IntervalDomain
::
new
(
bitvec!
(
"0x42:8"
),
bitvec!
(
"0x42:8"
))),
Bitvector
::
from_u64
(
0x42
),
Bitvector
::
from_u64
(
0x42
),
)),
);
);
let
result_domain
=
setup
let
result_domain
=
setup
...
@@ -341,15 +335,15 @@ fn test_no_specifiers() {
...
@@ -341,15 +335,15 @@ fn test_no_specifiers() {
fn
test_fetch_constant_and_domain_for_format_specifier
()
{
fn
test_fetch_constant_and_domain_for_format_specifier
()
{
let
sprintf_symbol
=
ExternSymbol
::
mock_sprintf_symbol_arm
();
let
sprintf_symbol
=
ExternSymbol
::
mock_sprintf_symbol_arm
();
let
string_arg
=
Arg
::
Register
{
let
string_arg
=
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"r6"
,
4
)
),
expr
:
expr!
(
"r6:4"
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
};
};
let
integer_arg
=
Arg
::
Register
{
let
integer_arg
=
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"r7"
,
4
)
),
expr
:
expr!
(
"r7:4"
),
data_type
:
Some
(
Datatype
::
Integer
),
data_type
:
Some
(
Datatype
::
Integer
),
};
};
let
char_arg
=
Arg
::
Register
{
let
char_arg
=
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"r8"
,
4
)
),
expr
:
expr!
(
"r8:4"
),
data_type
:
Some
(
Datatype
::
Char
),
data_type
:
Some
(
Datatype
::
Char
),
};
};
...
@@ -408,11 +402,8 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
...
@@ -408,11 +402,8 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
// Test Case 4: Integer and tracked constant.
// Test Case 4: Integer and tracked constant.
setup
.pi_state_before_symbol_call
.set_register
(
setup
.pi_state_before_symbol_call
.set_register
(
&
Variable
::
mock
(
"r7"
,
4
),
&
variable!
(
"r7:4"
),
DataDomain
::
from
(
IntervalDomain
::
new
(
DataDomain
::
from
(
IntervalDomain
::
new
(
bitvec!
(
"2:8"
),
bitvec!
(
"2:8"
))),
Bitvector
::
from_u64
(
2
),
Bitvector
::
from_u64
(
2
),
)),
);
);
assert_eq!
(
assert_eq!
(
...
@@ -429,11 +420,8 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
...
@@ -429,11 +420,8 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
// Test Case 5: Char and tracked constant.
// Test Case 5: Char and tracked constant.
setup
.pi_state_before_symbol_call
.set_register
(
setup
.pi_state_before_symbol_call
.set_register
(
&
Variable
::
mock
(
"r8"
,
4
),
&
variable!
(
"r8:4"
),
DataDomain
::
from
(
IntervalDomain
::
new
(
DataDomain
::
from
(
IntervalDomain
::
new
(
bitvec!
(
"0x42:4"
),
bitvec!
(
"0x42:4"
))),
Bitvector
::
from_u32
(
0x42
),
Bitvector
::
from_u32
(
0x42
),
)),
);
);
assert_eq!
(
assert_eq!
(
...
@@ -450,10 +438,10 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
...
@@ -450,10 +438,10 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
// Test Case 6: String and tracked constant.
// Test Case 6: String and tracked constant.
setup
.pi_state_before_symbol_call
.set_register
(
setup
.pi_state_before_symbol_call
.set_register
(
&
Variable
::
mock
(
"r6"
,
4
),
&
variable!
(
"r6:4"
),
DataDomain
::
from
(
IntervalDomain
::
new
(
DataDomain
::
from
(
IntervalDomain
::
new
(
Bitvector
::
from_u32
(
0x3002
),
bitvec!
(
"0x3002:4"
),
Bitvector
::
from_u32
(
0x3002
),
bitvec!
(
"0x3002:4"
),
)),
)),
);
);
...
@@ -471,22 +459,22 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
...
@@ -471,22 +459,22 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
mut
pointer
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
let
mut
pointer
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
stack_id
,
stack_id
,
IntervalDomain
::
new
(
Bitvector
::
from_i32
(
16
),
Bitvector
::
from_i32
(
16
)),
IntervalDomain
::
new
(
bitvec!
(
"16:4"
),
bitvec!
(
"16:4"
)),
);
);
let
heap_id
=
AbstractIdentifier
::
new
(
let
heap_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r9"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r9:4"
))
.unwrap
(),
);
);
pointer
.insert_relative_value
(
pointer
.insert_relative_value
(
heap_id
.clone
(),
heap_id
.clone
(),
IntervalDomain
::
new
(
Bitvector
::
from_i32
(
0
),
Bitvector
::
from_i32
(
0
)),
IntervalDomain
::
new
(
bitvec!
(
"0:4"
),
bitvec!
(
"0:4"
)),
);
);
setup
setup
...
@@ -499,7 +487,7 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
...
@@ -499,7 +487,7 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
// Test Case 5: String and tracked domain.
// Test Case 5: String and tracked domain.
setup
setup
.pi_state_before_symbol_call
.pi_state_before_symbol_call
.set_register
(
&
Variable
::
mock
(
"r6"
,
4
),
pointer
);
.set_register
(
&
variable!
(
"r6:4"
),
pointer
);
let
expected_domain
=
CharacterInclusionDomain
::
Value
((
let
expected_domain
=
CharacterInclusionDomain
::
Value
((
CharacterSet
::
Value
(
BTreeSet
::
new
()),
CharacterSet
::
Value
(
BTreeSet
::
new
()),
...
@@ -557,7 +545,7 @@ fn test_fetch_subdomains_if_available() {
...
@@ -557,7 +545,7 @@ fn test_fetch_subdomains_if_available() {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
// Test Case 2: Target value is not of type string pointer.
// Test Case 2: Target value is not of type string pointer.
...
@@ -600,13 +588,13 @@ fn test_fetch_constant_domain_if_available() {
...
@@ -600,13 +588,13 @@ fn test_fetch_constant_domain_if_available() {
pi_results
.compute
(
false
);
pi_results
.compute
(
false
);
let
setup
:
Setup
<
CharacterInclusionDomain
>
=
Setup
::
new
(
&
pi_results
);
let
setup
:
Setup
<
CharacterInclusionDomain
>
=
Setup
::
new
(
&
pi_results
);
let
string_data
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
Bitvector
::
from_i32
(
0x7000
));
let
string_data
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
bitvec!
(
"0x7000:4"
));
let
string_arg
:
Arg
=
Arg
::
mock_pointer_register
(
"r0"
,
4
);
let
string_arg
:
Arg
=
Arg
::
mock_pointer_register
(
"r0"
,
4
);
let
integer_data
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
Bitvector
::
from_i32
(
2
));
let
integer_data
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
bitvec!
(
"2:4"
));
let
integer_arg
:
Arg
=
Arg
::
mock_register_with_data_type
(
"r0"
,
4
,
Some
(
Datatype
::
Integer
));
let
integer_arg
:
Arg
=
Arg
::
mock_register_with_data_type
(
"r0"
,
4
,
Some
(
Datatype
::
Integer
));
let
char_data
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
Bitvector
::
from_i32
(
0x61
));
let
char_data
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from
(
bitvec!
(
"0x61:4"
));
let
char_arg
:
Arg
=
Arg
::
mock_register_with_data_type
(
"r0"
,
4
,
Some
(
Datatype
::
Char
));
let
char_arg
:
Arg
=
Arg
::
mock_register_with_data_type
(
"r0"
,
4
,
Some
(
Datatype
::
Char
));
assert_eq!
(
assert_eq!
(
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/context/symbol_calls/strcat.rs
View file @
decc1254
...
@@ -107,11 +107,10 @@ mod tests {
...
@@ -107,11 +107,10 @@ mod tests {
context
::
symbol_calls
::
tests
::
Setup
,
context
::
symbol_calls
::
tests
::
Setup
,
tests
::
mock_project_with_intraprocedural_control_flow
,
tests
::
mock_project_with_intraprocedural_control_flow
,
},
},
intermediate_representation
::{
ByteSize
,
Variable
},
intermediate_representation
::
*
,
variable
,
};
};
use
super
::
*
;
#[test]
#[test]
fn
test_handle_strcat_and_strncat_calls_with_known_second_input
()
{
fn
test_handle_strcat_and_strncat_calls_with_known_second_input
()
{
let
strcat_symbol
=
ExternSymbol
::
mock_strcat_symbol_arm
();
let
strcat_symbol
=
ExternSymbol
::
mock_strcat_symbol_arm
();
...
@@ -247,7 +246,7 @@ mod tests {
...
@@ -247,7 +246,7 @@ mod tests {
#[test]
#[test]
fn
test_process_second_input_domain_local_and_global
()
{
fn
test_process_second_input_domain_local_and_global
()
{
let
r1_reg
=
Variable
::
mock
(
"r1"
,
ByteSize
::
new
(
4
)
);
let
r1_reg
=
variable!
(
"r1:4"
);
let
strcat_symbol
=
ExternSymbol
::
mock_strcat_symbol_arm
();
let
strcat_symbol
=
ExternSymbol
::
mock_strcat_symbol_arm
();
let
project
=
mock_project_with_intraprocedural_control_flow
(
let
project
=
mock_project_with_intraprocedural_control_flow
(
vec!
[(
strcat_symbol
.clone
(),
vec!
[
false
])],
vec!
[(
strcat_symbol
.clone
(),
vec!
[
false
])],
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/context/symbol_calls/tests.rs
View file @
decc1254
...
@@ -13,10 +13,10 @@ use crate::analysis::pointer_inference::PointerInference as PointerInferenceComp
...
@@ -13,10 +13,10 @@ use crate::analysis::pointer_inference::PointerInference as PointerInferenceComp
use
crate
::
analysis
::
pointer_inference
::
State
as
PiState
;
use
crate
::
analysis
::
pointer_inference
::
State
as
PiState
;
use
crate
::
analysis
::
string_abstraction
::
state
::
State
;
use
crate
::
analysis
::
string_abstraction
::
state
::
State
;
use
crate
::
analysis
::
string_abstraction
::
tests
::
*
;
use
crate
::
analysis
::
string_abstraction
::
tests
::
*
;
use
crate
::
intermediate_representation
::{
Bitvector
,
ExternSymbol
,
Project
,
Sub
};
use
crate
::
intermediate_representation
::
*
;
use
crate
::
variable
;
use
crate
::{
use
crate
::{
abstract_domain
::{
AbstractIdentifier
,
AbstractLocation
},
abstract_domain
::{
AbstractIdentifier
,
AbstractLocation
},
intermediate_representation
::{
Tid
,
Variable
},
utils
::
symbol_utils
::
get_symbol_map
,
utils
::
symbol_utils
::
get_symbol_map
,
};
};
...
@@ -119,7 +119,7 @@ fn test_handle_generic_symbol_calls() {
...
@@ -119,7 +119,7 @@ fn test_handle_generic_symbol_calls() {
let
mut
setup
:
Setup
<
CharacterInclusionDomain
>
=
Setup
::
new
(
&
pi_results
);
let
mut
setup
:
Setup
<
CharacterInclusionDomain
>
=
Setup
::
new
(
&
pi_results
);
setup
.state_before_call
.add_new_variable_to_pointer_entry
(
setup
.state_before_call
.add_new_variable_to_pointer_entry
(
Variable
::
mock
(
"r1"
,
4
),
variable!
(
"r1:4"
),
DataDomain
::
from
(
IntervalDomain
::
from
(
Bitvector
::
from_i32
(
32
))),
DataDomain
::
from
(
IntervalDomain
::
from
(
Bitvector
::
from_i32
(
32
))),
);
);
...
@@ -143,7 +143,7 @@ fn test_handle_unknown_symbol_calls() {
...
@@ -143,7 +143,7 @@ fn test_handle_unknown_symbol_calls() {
let
mut
setup
:
Setup
<
CharacterInclusionDomain
>
=
Setup
::
new
(
&
pi_results
);
let
mut
setup
:
Setup
<
CharacterInclusionDomain
>
=
Setup
::
new
(
&
pi_results
);
setup
.state_before_call
.add_new_variable_to_pointer_entry
(
setup
.state_before_call
.add_new_variable_to_pointer_entry
(
Variable
::
mock
(
"r1"
,
4
),
variable!
(
"r1:4"
),
DataDomain
::
from
(
IntervalDomain
::
from
(
Bitvector
::
from_i32
(
32
))),
DataDomain
::
from
(
IntervalDomain
::
from
(
Bitvector
::
from_i32
(
32
))),
);
);
...
@@ -174,7 +174,7 @@ fn test_add_new_string_abstract_domain() {
...
@@ -174,7 +174,7 @@ fn test_add_new_string_abstract_domain() {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
stack_pointer
=
DataDomain
::
from_target
(
let
stack_pointer
=
DataDomain
::
from_target
(
stack_id
.clone
(),
stack_id
.clone
(),
...
@@ -194,7 +194,7 @@ fn test_add_new_string_abstract_domain() {
...
@@ -194,7 +194,7 @@ fn test_add_new_string_abstract_domain() {
let
heap_id
=
AbstractIdentifier
::
new
(
let
heap_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r5"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r5:4"
))
.unwrap
(),
);
);
let
heap_pointer
=
DataDomain
::
from_target
(
let
heap_pointer
=
DataDomain
::
from_target
(
...
@@ -227,12 +227,12 @@ fn test_merge_domains_from_multiple_pointer_targets() {
...
@@ -227,12 +227,12 @@ fn test_merge_domains_from_multiple_pointer_targets() {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
heap_id
=
AbstractIdentifier
::
new
(
let
heap_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r5"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r5:4"
))
.unwrap
(),
);
);
let
mut
domain_pointer
:
DataDomain
<
IntervalDomain
>
=
let
mut
domain_pointer
:
DataDomain
<
IntervalDomain
>
=
...
@@ -424,7 +424,7 @@ fn test_insert_constant_string_into_format_string() {
...
@@ -424,7 +424,7 @@ fn test_insert_constant_string_into_format_string() {
fn
test_handle_free
()
{
fn
test_handle_free
()
{
let
free_symbol
=
ExternSymbol
::
mock_free_symbol_arm
();
let
free_symbol
=
ExternSymbol
::
mock_free_symbol_arm
();
let
malloc_symbol
=
ExternSymbol
::
mock_malloc_symbol_arm
();
let
malloc_symbol
=
ExternSymbol
::
mock_malloc_symbol_arm
();
let
r0_reg
=
Variable
::
mock
(
"r0"
,
4
);
let
r0_reg
=
variable!
(
"r0:4"
);
let
project
=
mock_project_with_intraprocedural_control_flow
(
let
project
=
mock_project_with_intraprocedural_control_flow
(
vec!
[
vec!
[
(
malloc_symbol
.clone
(),
vec!
[]),
(
malloc_symbol
.clone
(),
vec!
[]),
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/context/trait_impls/tests.rs
View file @
decc1254
...
@@ -28,8 +28,8 @@ fn test_update_def() {
...
@@ -28,8 +28,8 @@ fn test_update_def() {
setup
.context.block_first_def_set
=
HashSet
::
new
();
setup
.context.block_first_def_set
=
HashSet
::
new
();
let
assign_def
=
def!
[
"assign_def: r1:4 = 0x7000:4"
];
let
assign_def
=
def!
[
"assign_def: r1:4 = 0x7000:4"
];
let
load_def
=
load_var_content_from_temp_var
(
"load_def"
,
"r5"
,
"r2"
);
let
load_def
=
Def
::
load_var_content_from_temp_var
(
"load_def"
,
"r5"
,
"r2"
);
let
store_def
=
store_var_content_at_temp_var
(
"store_def"
,
"r0"
,
"r5"
);
let
store_def
=
Def
::
store_var_content_at_temp_var
(
"store_def"
,
"r0"
,
"r5"
);
let
new_state
=
setup
let
new_state
=
setup
.context
.context
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/state/tests.rs
View file @
decc1254
...
@@ -5,13 +5,16 @@ use crate::{
...
@@ -5,13 +5,16 @@ use crate::{
pointer_inference
::
State
as
PiState
,
pointer_inference
::
State
as
PiState
,
string_abstraction
::
tests
::
mock_project_with_intraprocedural_control_flow
,
string_abstraction
::
tests
::
mock_project_with_intraprocedural_control_flow
,
},
},
expr
,
intermediate_representation
::
*
,
variable
,
};
};
use
std
::
collections
::
BTreeSet
;
use
std
::
collections
::
BTreeSet
;
impl
<
T
:
AbstractDomain
+
DomainInsertion
+
HasTop
+
Eq
+
From
<
String
>>
State
<
T
>
{
impl
<
T
:
AbstractDomain
+
DomainInsertion
+
HasTop
+
Eq
+
From
<
String
>>
State
<
T
>
{
pub
fn
mock_with_default_pi_state
(
current_sub
:
Term
<
Sub
>
)
->
Self
{
pub
fn
mock_with_default_pi_state
(
current_sub
:
Term
<
Sub
>
)
->
Self
{
let
pi_state
=
PointerInferenceState
::
new
(
let
pi_state
=
PointerInferenceState
::
new
(
&
Variable
::
mock
(
"sp"
,
4
as
u64
),
&
variable!
(
"sp:4"
),
current_sub
.tid
.clone
(),
current_sub
.tid
.clone
(),
BTreeSet
::
new
(),
BTreeSet
::
new
(),
);
);
...
@@ -50,7 +53,7 @@ fn test_delete_string_map_entries_if_no_pointer_targets_are_tracked() {
...
@@ -50,7 +53,7 @@ fn test_delete_string_map_entries_if_no_pointer_targets_are_tracked() {
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
stack_pointer
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
let
stack_pointer
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
stack_id
.clone
(),
stack_id
.clone
(),
...
@@ -59,7 +62,7 @@ fn test_delete_string_map_entries_if_no_pointer_targets_are_tracked() {
...
@@ -59,7 +62,7 @@ fn test_delete_string_map_entries_if_no_pointer_targets_are_tracked() {
let
heap_id_1
=
AbstractIdentifier
::
new
(
let
heap_id_1
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r5"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r5:4"
))
.unwrap
(),
);
);
let
heap_pointer_1
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
let
heap_pointer_1
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
...
@@ -69,7 +72,7 @@ fn test_delete_string_map_entries_if_no_pointer_targets_are_tracked() {
...
@@ -69,7 +72,7 @@ fn test_delete_string_map_entries_if_no_pointer_targets_are_tracked() {
let
heap_id_2
=
AbstractIdentifier
::
new
(
let
heap_id_2
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r6"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r6:4"
))
.unwrap
(),
);
);
let
heap_pointer_2
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
let
heap_pointer_2
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
...
@@ -79,12 +82,12 @@ fn test_delete_string_map_entries_if_no_pointer_targets_are_tracked() {
...
@@ -79,12 +82,12 @@ fn test_delete_string_map_entries_if_no_pointer_targets_are_tracked() {
let
heap_id_3
=
AbstractIdentifier
::
new
(
let
heap_id_3
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r7"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r7:4"
))
.unwrap
(),
);
);
state
state
.variable_to_pointer_map
.variable_to_pointer_map
.insert
(
Variable
::
mock
(
"r0"
,
4
),
stack_pointer
);
.insert
(
variable!
(
"r0:4"
),
stack_pointer
);
state
.stack_offset_to_pointer_map
.insert
(
-
8
,
heap_pointer_1
);
state
.stack_offset_to_pointer_map
.insert
(
-
8
,
heap_pointer_1
);
state
.unassigned_return_pointer
.insert
(
heap_pointer_2
);
state
.unassigned_return_pointer
.insert
(
heap_pointer_2
);
...
@@ -153,10 +156,10 @@ fn test_handle_assign_and_load() {
...
@@ -153,10 +156,10 @@ fn test_handle_assign_and_load() {
let
sub
=
Sub
::
mock
(
"func"
);
let
sub
=
Sub
::
mock
(
"func"
);
let
mut
state
:
State
<
CharacterInclusionDomain
>
=
State
::
mock_with_default_pi_state
(
sub
.clone
());
let
mut
state
:
State
<
CharacterInclusionDomain
>
=
State
::
mock_with_default_pi_state
(
sub
.clone
());
let
runtime_memory_image
=
RuntimeMemoryImage
::
mock
();
let
runtime_memory_image
=
RuntimeMemoryImage
::
mock
();
let
output
=
Variable
::
mock
(
"r1"
,
4
);
let
output
=
variable!
(
"r1:4"
);
let
constant_input
=
Expression
::
Const
(
Bitvector
::
from_str_radix
(
16
,
"7000"
)
.unwrap
());
let
constant_input
=
Expression
::
Const
(
Bitvector
::
from_str_radix
(
16
,
"7000"
)
.unwrap
());
let
return_address_input
=
Expression
::
Const
(
Bitvector
::
from_str_radix
(
16
,
"14718"
)
.unwrap
());
let
return_address_input
=
Expression
::
Const
(
Bitvector
::
from_str_radix
(
16
,
"14718"
)
.unwrap
());
let
other_input
=
Expression
::
var
(
"r6"
,
4
);
let
other_input
=
expr!
(
"r6:4"
);
let
mut
block_first_def_set
:
HashSet
<
(
Tid
,
Tid
)
>
=
HashSet
::
new
();
let
mut
block_first_def_set
:
HashSet
<
(
Tid
,
Tid
)
>
=
HashSet
::
new
();
let
mut
return_tid
=
Tid
::
new
(
"14718"
);
let
mut
return_tid
=
Tid
::
new
(
"14718"
);
...
@@ -211,7 +214,7 @@ fn test_handle_assign_and_load() {
...
@@ -211,7 +214,7 @@ fn test_handle_assign_and_load() {
// Test Case 2: Assign Def with other input
// Test Case 2: Assign Def with other input
let
heap_id
=
AbstractIdentifier
::
new
(
let
heap_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r5"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r5:4"
))
.unwrap
(),
);
);
let
heap_pointer
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
let
heap_pointer
:
DataDomain
<
IntervalDomain
>
=
DataDomain
::
from_target
(
...
@@ -263,19 +266,19 @@ fn test_handle_assign_and_load() {
...
@@ -263,19 +266,19 @@ fn test_handle_assign_and_load() {
#[test]
#[test]
fn
test_add_pointer_to_variable_maps_if_tracked
()
{
fn
test_add_pointer_to_variable_maps_if_tracked
()
{
let
output_var
=
Variable
::
mock
(
"r2"
,
4
);
let
output_var
=
variable!
(
"r2:4"
);
let
origin_var
=
Variable
::
mock
(
"r5"
,
4
);
let
origin_var
=
variable!
(
"r5:4"
);
let
mut
mock_state
=
let
mut
mock_state
=
State
::
<
CharacterInclusionDomain
>
::
mock_with_default_pi_state
(
Sub
::
mock
(
"func"
));
State
::
<
CharacterInclusionDomain
>
::
mock_with_default_pi_state
(
Sub
::
mock
(
"func"
));
let
pi_state
=
mock_state
.get_pointer_inference_state
()
.unwrap
()
.clone
();
let
pi_state
=
mock_state
.get_pointer_inference_state
()
.unwrap
()
.clone
();
let
heap_id
=
AbstractIdentifier
::
new
(
let
heap_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r5"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r5:4"
))
.unwrap
(),
);
);
let
stack_id
=
AbstractIdentifier
::
new
(
let
stack_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"func"
),
Tid
::
new
(
"func"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"sp"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"sp:4"
))
.unwrap
(),
);
);
let
mut
source_pointer
:
DataDomain
<
IntervalDomain
>
=
let
mut
source_pointer
:
DataDomain
<
IntervalDomain
>
=
...
@@ -339,7 +342,7 @@ fn test_pointer_targets_partially_tracked() {
...
@@ -339,7 +342,7 @@ fn test_pointer_targets_partially_tracked() {
let
heap_id
=
AbstractIdentifier
::
new
(
let
heap_id
=
AbstractIdentifier
::
new
(
Tid
::
new
(
"heap"
),
Tid
::
new
(
"heap"
),
AbstractLocation
::
from_var
(
&
Variable
::
mock
(
"r0"
,
4
))
.unwrap
(),
AbstractLocation
::
from_var
(
&
variable!
(
"r0:4"
))
.unwrap
(),
);
);
let
stack_id
=
pi_state
.stack_id
.clone
();
let
stack_id
=
pi_state
.stack_id
.clone
();
...
@@ -367,8 +370,8 @@ fn test_pointer_targets_partially_tracked() {
...
@@ -367,8 +370,8 @@ fn test_pointer_targets_partially_tracked() {
#[test]
#[test]
fn
test_pointer_is_in_pointer_maps
()
{
fn
test_pointer_is_in_pointer_maps
()
{
let
r2_reg
=
Variable
::
mock
(
"r2"
,
4
);
let
r2_reg
=
variable!
(
"r2:4"
);
let
sp_reg
=
Variable
::
mock
(
"sp"
,
4
);
let
sp_reg
=
variable!
(
"sp:4"
);
let
mut
mock_state
=
let
mut
mock_state
=
State
::
<
CharacterInclusionDomain
>
::
mock_with_default_pi_state
(
Sub
::
mock
(
"func"
));
State
::
<
CharacterInclusionDomain
>
::
mock_with_default_pi_state
(
Sub
::
mock
(
"func"
));
...
@@ -401,10 +404,10 @@ fn test_pointer_is_in_pointer_maps() {
...
@@ -401,10 +404,10 @@ fn test_pointer_is_in_pointer_maps() {
#[test]
#[test]
fn
test_handle_store
()
{
fn
test_handle_store
()
{
let
block_first_def_set
:
HashSet
<
(
Tid
,
Tid
)
>
=
HashSet
::
new
();
let
block_first_def_set
:
HashSet
<
(
Tid
,
Tid
)
>
=
HashSet
::
new
();
let
target_var
=
Variable
::
mock
(
"r2"
,
4
);
let
target_var
=
variable!
(
"r2:4"
);
let
value_var
=
Variable
::
mock
(
"r3"
,
4
);
let
value_var
=
variable!
(
"r3:4"
);
let
value_location
=
Expression
::
Var
(
value_var
.clone
());
let
value_location
=
Expression
::
Var
(
value_var
.clone
());
let
sp_reg
=
Variable
::
mock
(
"sp"
,
4
);
let
sp_reg
=
variable!
(
"sp:4"
);
let
target_location
=
Expression
::
Var
(
target_var
.clone
());
let
target_location
=
Expression
::
Var
(
target_var
.clone
());
let
runtime_memory_image
=
RuntimeMemoryImage
::
mock
();
let
runtime_memory_image
=
RuntimeMemoryImage
::
mock
();
let
mut
mock_state
=
let
mut
mock_state
=
...
@@ -465,7 +468,7 @@ fn test_handle_store() {
...
@@ -465,7 +468,7 @@ fn test_handle_store() {
mock_state
.set_all_maps_empty
();
mock_state
.set_all_maps_empty
();
mock_state
mock_state
.variable_to_pointer_map
.variable_to_pointer_map
.insert
(
Variable
::
mock
(
"r0"
,
4
),
string_pointer
.clone
());
.insert
(
variable!
(
"r0:4"
),
string_pointer
.clone
());
mock_state
.handle_store
(
mock_state
.handle_store
(
&
target_location
,
&
target_location
,
...
@@ -483,15 +486,15 @@ fn test_handle_store() {
...
@@ -483,15 +486,15 @@ fn test_handle_store() {
mock_state
.set_all_maps_empty
();
mock_state
.set_all_maps_empty
();
mock_state
mock_state
.variable_to_pointer_map
.variable_to_pointer_map
.insert
(
Variable
::
mock
(
"r0"
,
4
),
string_pointer
.clone
());
.insert
(
variable!
(
"r0:4"
),
string_pointer
.clone
());
// Test Case 5: Global address pointer as constant.
// Test Case 5: Global address pointer as constant.
// Test Case 6: Global address pointer in variable.
// Test Case 6: Global address pointer in variable.
}
}
#[test]
#[test]
fn
test_add_pointer_to_stack_map
()
{
fn
test_add_pointer_to_stack_map
()
{
let
r2_reg
=
Variable
::
mock
(
"r2"
,
4
);
let
r2_reg
=
variable!
(
"r2:4"
);
let
sp_reg
=
Variable
::
mock
(
"sp"
,
4
);
let
sp_reg
=
variable!
(
"sp:4"
);
let
target
=
Expression
::
Var
(
r2_reg
.clone
());
let
target
=
Expression
::
Var
(
r2_reg
.clone
());
let
mut
mock_state
=
let
mut
mock_state
=
State
::
<
CharacterInclusionDomain
>
::
mock_with_default_pi_state
(
Sub
::
mock
(
"func"
));
State
::
<
CharacterInclusionDomain
>
::
mock_with_default_pi_state
(
Sub
::
mock
(
"func"
));
...
@@ -532,18 +535,18 @@ fn test_remove_non_callee_saved_pointer_entries_for_external_symbol() {
...
@@ -532,18 +535,18 @@ fn test_remove_non_callee_saved_pointer_entries_for_external_symbol() {
mock_state
mock_state
.variable_to_pointer_map
.variable_to_pointer_map
.insert
(
Variable
::
mock
(
"r0"
,
4
),
top_domain
.clone
());
.insert
(
variable!
(
"r0:4"
),
top_domain
.clone
());
mock_state
mock_state
.variable_to_pointer_map
.variable_to_pointer_map
.insert
(
Variable
::
mock
(
"r11"
,
4
),
top_domain
);
.insert
(
variable!
(
"r11:4"
),
top_domain
);
mock_state
mock_state
.remove_non_callee_saved_pointer_entries_for_external_symbol
(
&
project
,
&
sprintf_symbol
);
.remove_non_callee_saved_pointer_entries_for_external_symbol
(
&
project
,
&
sprintf_symbol
);
assert
!
(
!
mock_state
assert
!
(
!
mock_state
.variable_to_pointer_map
.variable_to_pointer_map
.contains_key
(
&
Variable
::
mock
(
"r0"
,
4
)));
.contains_key
(
&
variable!
(
"r0:4"
)));
assert
!
(
mock_state
assert
!
(
mock_state
.variable_to_pointer_map
.variable_to_pointer_map
.contains_key
(
&
Variable
::
mock
(
"r11"
,
4
)));
.contains_key
(
&
variable!
(
"r11:4"
)));
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/tests.rs
View file @
decc1254
use
crate
::{
def
,
defs
,
expr
,
intermediate_representation
::
*
,
variable
};
use
crate
::{
def
,
defs
,
intermediate_representation
::
*
};
// FIXME: Move this function to the intermediate_representation module
pub
fn
pointer_plus_offset_to_temp_var
(
tid
:
&
str
,
tmp_name
:
&
str
,
pointer
:
&
str
,
offset
:
i64
,
)
->
Term
<
Def
>
{
Def
::
assign
(
tid
,
Variable
{
name
:
String
::
from
(
tmp_name
),
size
:
ByteSize
::
new
(
4
),
is_temp
:
true
,
},
expr!
(
format!
(
"{}:4 + {}:4"
,
pointer
,
offset
)),
)
}
// FIXME: Move this function to the intermediate_representation module
pub
fn
store_var_content_at_temp_var
(
tid
:
&
str
,
tmp_name
:
&
str
,
var
:
&
str
)
->
Term
<
Def
>
{
Def
::
store
(
tid
,
Expression
::
Var
(
Variable
{
name
:
String
::
from
(
tmp_name
),
size
:
ByteSize
::
new
(
4
),
is_temp
:
true
,
}),
expr!
(
format!
(
"{}:4"
,
var
)),
)
}
// FIXME: Move this function to the intermediate_representation module
pub
fn
load_var_content_from_temp_var
(
tid
:
&
str
,
var
:
&
str
,
tmp_name
:
&
str
)
->
Term
<
Def
>
{
Def
::
load
(
tid
,
variable!
(
format!
(
"{}:4"
,
var
)),
Expression
::
Var
(
Variable
{
name
:
String
::
from
(
tmp_name
),
size
:
ByteSize
::
new
(
4
),
is_temp
:
true
,
}),
)
}
fn
mock_defs_for_sprintf
(
format_known
:
bool
,
blk_num
:
usize
)
->
Vec
<
Term
<
Def
>>
{
fn
mock_defs_for_sprintf
(
format_known
:
bool
,
blk_num
:
usize
)
->
Vec
<
Term
<
Def
>>
{
/*
/*
...
@@ -81,13 +37,13 @@ fn mock_defs_for_sprintf(format_known: bool, blk_num: usize) -> Vec<Term<Def>> {
...
@@ -81,13 +37,13 @@ fn mock_defs_for_sprintf(format_known: bool, blk_num: usize) -> Vec<Term<Def>> {
.as_mut
(),
.as_mut
(),
);
);
defs
.push
(
pointer_plus_offset_to_temp_var
(
defs
.push
(
Def
::
pointer_plus_offset_to_temp_var
(
&
format!
(
"def_6_blk_{}"
,
blk_num
),
&
format!
(
"def_6_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"sp"
,
"sp"
,
0
,
0
,
));
));
defs
.push
(
store_var_content_at_temp_var
(
defs
.push
(
Def
::
store_var_content_at_temp_var
(
&
format!
(
"def_7_blk_{}"
,
blk_num
),
&
format!
(
"def_7_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"r12"
,
"r12"
,
...
@@ -98,13 +54,13 @@ fn mock_defs_for_sprintf(format_known: bool, blk_num: usize) -> Vec<Term<Def>> {
...
@@ -98,13 +54,13 @@ fn mock_defs_for_sprintf(format_known: bool, blk_num: usize) -> Vec<Term<Def>> {
blk_num
blk_num
)]);
)]);
defs
.push
(
pointer_plus_offset_to_temp_var
(
defs
.push
(
Def
::
pointer_plus_offset_to_temp_var
(
&
format!
(
"def_9_blk_{}"
,
blk_num
),
&
format!
(
"def_9_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"sp"
,
"sp"
,
4
,
4
,
));
));
defs
.push
(
store_var_content_at_temp_var
(
defs
.push
(
Def
::
store_var_content_at_temp_var
(
&
format!
(
"def_10_blk_{}"
,
blk_num
),
&
format!
(
"def_10_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"r12"
,
"r12"
,
...
@@ -132,14 +88,14 @@ fn mock_defs_for_scanf(format_known: bool, blk_num: usize) -> Vec<Term<Def>> {
...
@@ -132,14 +88,14 @@ fn mock_defs_for_scanf(format_known: bool, blk_num: usize) -> Vec<Term<Def>> {
format!
(
"def_1_blk_{}: r0:4 = r11:4 - 0x3c:4"
,
blk_num
)
format!
(
"def_1_blk_{}: r0:4 = r11:4 - 0x3c:4"
,
blk_num
)
];
];
defs
.push
(
pointer_plus_offset_to_temp_var
(
defs
.push
(
Def
::
pointer_plus_offset_to_temp_var
(
&
format!
(
"def_2_blk_{}"
,
blk_num
),
&
format!
(
"def_2_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"sp"
,
"sp"
,
0
,
0
,
));
));
defs
.push
(
store_var_content_at_temp_var
(
defs
.push
(
Def
::
store_var_content_at_temp_var
(
&
format!
(
"def_3_blk_{}"
,
blk_num
),
&
format!
(
"def_3_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"r0"
,
"r0"
,
...
@@ -196,14 +152,14 @@ fn mock_defs_for_sscanf(source_known: bool, format_known: bool, blk_num: usize)
...
@@ -196,14 +152,14 @@ fn mock_defs_for_sscanf(source_known: bool, format_known: bool, blk_num: usize)
format!
(
"def_1_blk_{}: r3:4 = r11:4 - 0x96:4"
,
blk_num
)
format!
(
"def_1_blk_{}: r3:4 = r11:4 - 0x96:4"
,
blk_num
)
];
];
defs
.push
(
pointer_plus_offset_to_temp_var
(
defs
.push
(
Def
::
pointer_plus_offset_to_temp_var
(
&
format!
(
"def_2_blk_{}"
,
blk_num
),
&
format!
(
"def_2_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"sp"
,
"sp"
,
0
,
0
,
));
));
defs
.push
(
store_var_content_at_temp_var
(
defs
.push
(
Def
::
store_var_content_at_temp_var
(
&
format!
(
"def_3_blk_{}"
,
blk_num
),
&
format!
(
"def_3_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"r3"
,
"r3"
,
...
@@ -214,13 +170,13 @@ fn mock_defs_for_sscanf(source_known: bool, format_known: bool, blk_num: usize)
...
@@ -214,13 +170,13 @@ fn mock_defs_for_sscanf(source_known: bool, format_known: bool, blk_num: usize)
blk_num
blk_num
)]);
)]);
defs
.push
(
pointer_plus_offset_to_temp_var
(
defs
.push
(
Def
::
pointer_plus_offset_to_temp_var
(
&
format!
(
"def_5_blk_{}"
,
blk_num
),
&
format!
(
"def_5_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"sp"
,
"sp"
,
4
,
4
,
));
));
defs
.push
(
store_var_content_at_temp_var
(
defs
.push
(
Def
::
store_var_content_at_temp_var
(
&
format!
(
"def_6_blk_{}"
,
blk_num
),
&
format!
(
"def_6_blk_{}"
,
blk_num
),
"$U1050"
,
"$U1050"
,
"r3"
,
"r3"
,
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/checkers/cwe_119/state.rs
View file @
decc1254
...
@@ -269,7 +269,7 @@ fn collect_tids_for_cwe_warning(
...
@@ -269,7 +269,7 @@ fn collect_tids_for_cwe_warning(
#[cfg(test)]
#[cfg(test)]
pub
mod
tests
{
pub
mod
tests
{
use
super
::
*
;
use
super
::
*
;
use
crate
::
intermediate_representation
::
Variable
;
use
crate
::
{
intermediate_representation
::
*
,
variable
}
;
#[test]
#[test]
fn
test_new
()
{
fn
test_new
()
{
...
@@ -279,7 +279,7 @@ pub mod tests {
...
@@ -279,7 +279,7 @@ pub mod tests {
&
FunctionSignature
::
mock_x64
(),
&
FunctionSignature
::
mock_x64
(),
context
.project
,
context
.project
,
);
);
let
stack_id
=
AbstractIdentifier
::
from_var
(
Tid
::
new
(
"func"
),
&
Variable
::
mock
(
"RSP"
,
8
));
let
stack_id
=
AbstractIdentifier
::
from_var
(
Tid
::
new
(
"func"
),
&
variable!
(
"RSP:8"
));
assert_eq!
(
state
.stack_id
,
stack_id
);
assert_eq!
(
state
.stack_id
,
stack_id
);
assert_eq!
(
state
.object_lower_bounds
.len
(),
1
);
assert_eq!
(
state
.object_lower_bounds
.len
(),
1
);
...
@@ -302,7 +302,7 @@ pub mod tests {
...
@@ -302,7 +302,7 @@ pub mod tests {
&
FunctionSignature
::
mock_x64
(),
&
FunctionSignature
::
mock_x64
(),
context
.project
,
context
.project
,
);
);
let
stack_id
=
AbstractIdentifier
::
from_var
(
Tid
::
new
(
"func"
),
&
Variable
::
mock
(
"RSP"
,
8
));
let
stack_id
=
AbstractIdentifier
::
from_var
(
Tid
::
new
(
"func"
),
&
variable!
(
"RSP:8"
));
// access in bounds
// access in bounds
let
address
=
Data
::
from_target
(
stack_id
.clone
(),
Bitvector
::
from_i64
(
-
12
)
.into
());
let
address
=
Data
::
from_target
(
stack_id
.clone
(),
Bitvector
::
from_i64
(
-
12
)
.into
());
assert
!
(
state
assert
!
(
state
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/blk.rs
View file @
decc1254
use
super
::
*
;
use
super
::
*
;
use
crate
::
utils
::
log
::
LogMessage
;
use
crate
::
utils
::
log
::
LogMessage
;
use
std
::{
use
std
::{
collections
::
HashSet
,
fmt
};
collections
::{
HashMap
,
HashSet
},
fmt
,
};
/// A basic block is a sequence of `Def` instructions followed by up to two `Jmp` instructions.
/// A basic block is a sequence of `Def` instructions followed by up to two `Jmp` instructions.
///
///
...
@@ -70,131 +67,6 @@ impl Term<Blk> {
...
@@ -70,131 +67,6 @@ impl Term<Blk> {
Err
(
logs
)
Err
(
logs
)
}
}
}
}
/// Wherever possible, substitute input variables of expressions
/// with the input expression that defines the input variable.
///
/// Note that substitution is only possible
/// if the input variables of the input expression itself did not change since the definition of said variable.
///
/// The expression propagation is used in [`expression_propagation` normalization pass](crate::analysis::expression_propagation)
/// to further simplify the generated expressions using a fixpoint algorithm
/// and allows more dead stores to be removed during [dead variable elimination](crate::analysis::dead_variable_elimination).
pub
fn
propagate_input_expressions
(
&
mut
self
,
apriori_insertable_expressions
:
Option
<
HashMap
<
Variable
,
Expression
>>
,
)
{
let
mut
insertable_expressions
=
HashMap
::
new
();
if
let
Some
(
insertables
)
=
apriori_insertable_expressions
{
insertable_expressions
=
insertables
;
}
for
def
in
self
.term.defs
.iter_mut
()
{
match
&
mut
def
.term
{
Def
::
Assign
{
var
,
value
:
expression
,
}
=>
{
// insert known input expressions
for
(
input_var
,
input_expr
)
in
insertable_expressions
.iter
()
{
expression
.substitute_input_var
(
input_var
,
input_expr
);
}
// expressions dependent on the assigned variable are no longer insertable
insertable_expressions
.retain
(|
input_var
,
input_expr
|
{
input_var
!=
var
&&
!
input_expr
.input_vars
()
.into_iter
()
.any
(|
x
|
x
==
var
)
});
// If the value of the assigned variable does not depend on the former value of the variable,
// then it is insertable for future expressions.
if
!
expression
.input_vars
()
.into_iter
()
.any
(|
x
|
x
==
var
)
{
insertable_expressions
.insert
(
var
.clone
(),
expression
.clone
());
}
}
Def
::
Load
{
var
,
address
:
expression
,
}
=>
{
// insert known input expressions
for
(
input_var
,
input_expr
)
in
insertable_expressions
.iter
()
{
expression
.substitute_input_var
(
input_var
,
input_expr
);
}
// expressions dependent on the assigned variable are no longer insertable
insertable_expressions
.retain
(|
input_var
,
input_expr
|
{
input_var
!=
var
&&
!
input_expr
.input_vars
()
.into_iter
()
.any
(|
x
|
x
==
var
)
});
}
Def
::
Store
{
address
,
value
}
=>
{
// insert known input expressions
for
(
input_var
,
input_expr
)
in
insertable_expressions
.iter
()
{
address
.substitute_input_var
(
input_var
,
input_expr
);
value
.substitute_input_var
(
input_var
,
input_expr
);
}
}
}
}
for
jump
in
self
.term.jmps
.iter_mut
()
{
match
&
mut
jump
.term
{
Jmp
::
Branch
(
_
)
|
Jmp
::
Call
{
..
}
|
Jmp
::
CallOther
{
..
}
=>
(),
Jmp
::
BranchInd
(
expr
)
|
Jmp
::
CBranch
{
condition
:
expr
,
..
}
|
Jmp
::
CallInd
{
target
:
expr
,
..
}
|
Jmp
::
Return
(
expr
)
=>
{
// insert known input expressions
for
(
input_var
,
input_expr
)
in
insertable_expressions
.iter
()
{
expr
.substitute_input_var
(
input_var
,
input_expr
);
}
}
}
}
}
/// Merge subsequent assignments to the same variable to a single assignment to that variable.
///
/// The value expressions of merged assignments can often be simplified later on
/// in the corresponding [`Project` normalization pass](Project::normalize).
pub
fn
merge_def_assignments_to_same_var
(
&
mut
self
)
{
let
mut
new_defs
=
Vec
::
new
();
let
mut
last_def_opt
=
None
;
for
def
in
self
.term.defs
.iter
()
{
if
let
Def
::
Assign
{
var
:
current_var
,
..
}
=
&
def
.term
{
if
let
Some
(
Term
{
term
:
Def
::
Assign
{
var
:
last_var
,
value
:
last_value
,
},
..
})
=
&
last_def_opt
{
if
current_var
==
last_var
{
let
mut
substituted_def
=
def
.clone
();
substituted_def
.substitute_input_var
(
last_var
,
last_value
);
last_def_opt
=
Some
(
substituted_def
);
}
else
{
new_defs
.push
(
last_def_opt
.unwrap
());
last_def_opt
=
Some
(
def
.clone
());
}
}
else
if
last_def_opt
.is_some
()
{
panic!
();
// Only assign-defs should be saved in last_def.
}
else
{
last_def_opt
=
Some
(
def
.clone
());
}
}
else
{
if
let
Some
(
last_def
)
=
last_def_opt
{
new_defs
.push
(
last_def
);
}
new_defs
.push
(
def
.clone
());
last_def_opt
=
None
;
}
}
if
let
Some
(
last_def
)
=
last_def_opt
{
new_defs
.push
(
last_def
);
}
self
.term.defs
=
new_defs
;
}
}
}
impl
fmt
::
Display
for
Blk
{
impl
fmt
::
Display
for
Blk
{
...
@@ -208,101 +80,3 @@ impl fmt::Display for Blk {
...
@@ -208,101 +80,3 @@ impl fmt::Display for Blk {
Ok
(())
Ok
(())
}
}
}
}
#[cfg(test)]
mod
tests
{
use
super
::
*
;
use
crate
::
intermediate_representation
::{
Def
,
Expression
,
Variable
};
impl
Blk
{
/// Creates empty block with tid "block".
pub
fn
mock
()
->
Term
<
Blk
>
{
Term
{
tid
:
Tid
::
new
(
"block"
),
term
:
Blk
{
defs
:
Vec
::
new
(),
jmps
:
Vec
::
new
(),
indirect_jmp_targets
:
Vec
::
new
(),
},
}
}
pub
fn
mock_with_tid
(
tid
:
&
str
)
->
Term
<
Blk
>
{
Term
{
tid
:
Tid
::
new
(
tid
),
term
:
Blk
{
defs
:
Vec
::
new
(),
jmps
:
Vec
::
new
(),
indirect_jmp_targets
:
Vec
::
new
(),
},
}
}
}
#[test]
fn
expression_propagation
()
{
use
crate
::
intermediate_representation
::
UnOpType
;
let
defs
=
vec!
[
Def
::
assign
(
"tid_1"
,
Variable
::
mock
(
"X"
,
8
),
Expression
::
var
(
"Y"
,
8
)
.un_op
(
UnOpType
::
IntNegate
),
),
Def
::
assign
(
"tid_2"
,
Variable
::
mock
(
"Y"
,
8
),
Expression
::
var
(
"X"
,
8
)
.plus
(
Expression
::
var
(
"Y"
,
8
)),
),
Def
::
assign
(
"tid_3"
,
Variable
::
mock
(
"X"
,
8
),
Expression
::
var
(
"X"
,
8
)
.un_op
(
UnOpType
::
IntNegate
),
),
Def
::
assign
(
"tid_4"
,
Variable
::
mock
(
"Y"
,
8
),
Expression
::
var
(
"Y"
,
8
)
.un_op
(
UnOpType
::
IntNegate
),
),
Def
::
assign
(
"tid_5"
,
Variable
::
mock
(
"Y"
,
8
),
Expression
::
var
(
"X"
,
8
)
.plus
(
Expression
::
var
(
"Y"
,
8
)),
),
];
let
mut
block
=
Term
{
tid
:
Tid
::
new
(
"block"
),
term
:
Blk
{
defs
,
jmps
:
Vec
::
new
(),
indirect_jmp_targets
:
Vec
::
new
(),
},
};
block
.merge_def_assignments_to_same_var
();
block
.propagate_input_expressions
(
None
);
let
result_defs
=
vec!
[
Def
::
assign
(
"tid_1"
,
Variable
::
mock
(
"X"
,
8
),
Expression
::
var
(
"Y"
,
8
)
.un_op
(
UnOpType
::
IntNegate
),
),
Def
::
assign
(
"tid_2"
,
Variable
::
mock
(
"Y"
,
8
),
Expression
::
var
(
"Y"
,
8
)
.un_op
(
UnOpType
::
IntNegate
)
.plus
(
Expression
::
var
(
"Y"
,
8
)),
),
Def
::
assign
(
"tid_3"
,
Variable
::
mock
(
"X"
,
8
),
Expression
::
var
(
"X"
,
8
)
.un_op
(
UnOpType
::
IntNegate
),
),
Def
::
assign
(
"tid_5"
,
Variable
::
mock
(
"Y"
,
8
),
Expression
::
var
(
"X"
,
8
)
.plus
(
Expression
::
var
(
"Y"
,
8
)
.un_op
(
UnOpType
::
IntNegate
)),
),
];
assert_eq!
(
block
.term.defs
,
result_defs
);
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/def.rs
View file @
decc1254
...
@@ -101,41 +101,18 @@ impl fmt::Display for Def {
...
@@ -101,41 +101,18 @@ impl fmt::Display for Def {
#[cfg(test)]
#[cfg(test)]
mod
tests
{
mod
tests
{
use
super
::
*
;
use
super
::
*
;
use
crate
::
intermediate_representation
::
BinOpType
;
use
crate
::
{
expr
,
intermediate_representation
::
*
,
variable
}
;
#[test]
#[test]
fn
zero_extension_check
()
{
fn
zero_extension_check
()
{
let
eax_variable
=
Expression
::
Var
(
Variable
{
name
:
String
::
from
(
"EAX"
),
size
:
ByteSize
::
new
(
4
),
is_temp
:
false
,
});
let
int_sub_expr
=
Expression
::
BinOp
{
op
:
BinOpType
::
IntSub
,
lhs
:
Box
::
new
(
Expression
::
Var
(
Variable
{
name
:
String
::
from
(
"EAX"
),
size
:
ByteSize
::
new
(
4
),
is_temp
:
false
,
})),
rhs
:
Box
::
new
(
Expression
::
Var
(
Variable
{
name
:
String
::
from
(
"ECX"
),
size
:
ByteSize
::
new
(
4
),
is_temp
:
false
,
})),
};
let
zero_extend_def
=
Term
{
let
zero_extend_def
=
Term
{
tid
:
Tid
::
new
(
"zero_tid"
),
tid
:
Tid
::
new
(
"zero_tid"
),
term
:
Def
::
Assign
{
term
:
Def
::
Assign
{
var
:
Variable
{
var
:
variable!
(
"RAX:8"
),
name
:
String
::
from
(
"RAX"
),
size
:
ByteSize
::
new
(
8
),
is_temp
:
false
,
},
value
:
Expression
::
Cast
{
value
:
Expression
::
Cast
{
op
:
CastOpType
::
IntZExt
,
op
:
CastOpType
::
IntZExt
,
size
:
ByteSize
::
new
(
8
),
size
:
ByteSize
::
new
(
8
),
arg
:
Box
::
new
(
e
ax_variable
.clone
(
)),
arg
:
Box
::
new
(
e
xpr!
(
"EAX:8"
)),
},
},
},
},
};
};
...
@@ -143,15 +120,11 @@ mod tests {
...
@@ -143,15 +120,11 @@ mod tests {
let
zero_extend_but_no_var_def
=
Term
{
let
zero_extend_but_no_var_def
=
Term
{
tid
:
Tid
::
new
(
"zero_tid"
),
tid
:
Tid
::
new
(
"zero_tid"
),
term
:
Def
::
Assign
{
term
:
Def
::
Assign
{
var
:
Variable
{
var
:
variable!
(
"RAX:8"
),
name
:
String
::
from
(
"RAX"
),
size
:
ByteSize
::
new
(
8
),
is_temp
:
false
,
},
value
:
Expression
::
Cast
{
value
:
Expression
::
Cast
{
op
:
CastOpType
::
IntZExt
,
op
:
CastOpType
::
IntZExt
,
size
:
ByteSize
::
new
(
8
),
size
:
ByteSize
::
new
(
8
),
arg
:
Box
::
new
(
int_sub_expr
.clone
(
)),
arg
:
Box
::
new
(
expr!
(
"EAX:8 - ECX:8"
)),
},
},
},
},
};
};
...
@@ -159,15 +132,11 @@ mod tests {
...
@@ -159,15 +132,11 @@ mod tests {
let
non_zero_extend_def
=
Term
{
let
non_zero_extend_def
=
Term
{
tid
:
Tid
::
new
(
"zero_tid"
),
tid
:
Tid
::
new
(
"zero_tid"
),
term
:
Def
::
Assign
{
term
:
Def
::
Assign
{
var
:
Variable
{
var
:
variable!
(
"RAX:8"
),
name
:
String
::
from
(
"RAX"
),
size
:
ByteSize
::
new
(
8
),
is_temp
:
false
,
},
value
:
Expression
::
Cast
{
value
:
Expression
::
Cast
{
op
:
CastOpType
::
IntSExt
,
op
:
CastOpType
::
IntSExt
,
size
:
ByteSize
::
new
(
8
),
size
:
ByteSize
::
new
(
8
),
arg
:
Box
::
new
(
e
ax_variable
.clone
(
)),
arg
:
Box
::
new
(
e
xpr!
(
"EAX:8"
)),
},
},
},
},
};
};
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/expression/builder.rs
View file @
decc1254
#
[
cfg
(
test
)]
use
apint
::
ApInt
;
#[cfg(test)]
use
super
::{
CastOpType
,
Variable
};
use
super
::
*
;
use
super
::
*
;
/// ## Helper functions for building expressions
/// ## Helper functions for building expressions
impl
Expression
{
impl
Expression
{
/// Shortcut for creating a constant expression from an i64 value
#[cfg(test)]
pub
fn
const_from_i64
(
value
:
i64
)
->
Expression
{
Expression
::
Const
(
Bitvector
::
from_i64
(
value
))
}
/// Shortcut for creating a constant expression from an i32 value
#[cfg(test)]
pub
fn
const_from_i32
(
value
:
i32
)
->
Expression
{
Expression
::
Const
(
Bitvector
::
from_i32
(
value
))
}
/// Shortcut for creating a constant expression from an apint value (e.g. copy of global address)
#[cfg(test)]
pub
fn
const_from_apint
(
value
:
ApInt
)
->
Expression
{
Expression
::
Const
(
value
)
}
/// Shortcut for creating a variable expression
#[cfg(test)]
pub
fn
var
(
name
:
impl
ToString
,
size_in_bytes
:
impl
Into
<
ByteSize
>
)
->
Expression
{
Expression
::
Var
(
Variable
{
name
:
name
.to_string
(),
size
:
size_in_bytes
.into
(),
is_temp
:
false
,
})
}
/// Shortcut for creating a cast expression
#[cfg(test)]
pub
fn
cast
(
self
,
op
:
CastOpType
)
->
Expression
{
Expression
::
Cast
{
op
,
size
:
ByteSize
::
new
(
8
),
arg
:
Box
::
new
(
self
),
}
}
/// Shortcut for creating a subpiece expression
#[cfg(test)]
pub
fn
subpiece
(
self
,
low_byte
:
ByteSize
,
size
:
ByteSize
)
->
Expression
{
Expression
::
Subpiece
{
low_byte
,
size
,
arg
:
Box
::
new
(
self
),
}
}
/// Shortcut for creating unary operation expressions.
#[cfg(test)]
pub
fn
un_op
(
self
,
op
:
UnOpType
)
->
Expression
{
Expression
::
UnOp
{
op
,
arg
:
Box
::
new
(
self
),
}
}
/// Shortcut for creating an `IntAdd`-expression
/// Shortcut for creating an `IntAdd`-expression
pub
fn
plus
(
self
,
rhs
:
Expression
)
->
Expression
{
pub
fn
plus
(
self
,
rhs
:
Expression
)
->
Expression
{
Expression
::
BinOp
{
Expression
::
BinOp
{
...
@@ -74,16 +11,6 @@ impl Expression {
...
@@ -74,16 +11,6 @@ impl Expression {
}
}
}
}
/// Shortcut for creating an `IntSub`-expression
#[cfg(test)]
pub
fn
minus
(
self
,
rhs
:
Expression
)
->
Expression
{
Expression
::
BinOp
{
lhs
:
Box
::
new
(
self
),
op
:
BinOpType
::
IntSub
,
rhs
:
Box
::
new
(
rhs
),
}
}
/// Construct an expression that adds a constant value to the given expression.
/// Construct an expression that adds a constant value to the given expression.
///
///
/// The bytesize of the value is automatically adjusted to the bytesize of the given expression.
/// The bytesize of the value is automatically adjusted to the bytesize of the given expression.
...
@@ -100,19 +27,4 @@ impl Expression {
...
@@ -100,19 +27,4 @@ impl Expression {
}
}
self
.plus
(
Expression
::
Const
(
value
))
self
.plus
(
Expression
::
Const
(
value
))
}
}
/// Construct an expression that subtracts a constant value from the given expression.
///
/// The bytesize of the value is automatically adjusted to the bytesize of the given expression.
#[cfg(test)]
pub
fn
minus_const
(
self
,
value
:
i64
)
->
Expression
{
let
bytesize
=
self
.bytesize
();
let
mut
value
=
Bitvector
::
from_i64
(
value
);
match
u64
::
from
(
bytesize
)
{
size
if
size
>
8
=>
value
.sign_extend
(
bytesize
)
.unwrap
(),
size
if
size
<
8
=>
value
.truncate
(
bytesize
)
.unwrap
(),
_
=>
(),
}
self
.minus
(
Expression
::
Const
(
value
))
}
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/expression/tests.rs
View file @
decc1254
use
super
::
*
;
use
super
::
*
;
use
crate
::{
expr
,
intermediate_representation
::
*
};
#[test]
#[test]
fn
trivial_expression_substitution
()
{
fn
trivial_expression_substitution
()
{
let
rax_variable
=
Expression
::
Var
(
Variable
::
mock
(
"RAX"
,
8
)
);
let
rax_variable
=
expr!
(
"RAX:8"
);
let
rcx_variable
=
Expression
::
Var
(
Variable
::
mock
(
"RCX"
,
8
)
);
let
rcx_variable
=
expr!
(
"RCX:8"
);
let
mut
expr
=
Expression
::
BinOp
{
let
mut
expr
=
Expression
::
BinOp
{
op
:
BinOpType
::
IntXOr
,
op
:
BinOpType
::
IntXOr
,
lhs
:
Box
::
new
(
rax_variable
.clone
()),
lhs
:
Box
::
new
(
rax_variable
.clone
()),
rhs
:
Box
::
new
(
rax_variable
.clone
()),
rhs
:
Box
::
new
(
rax_variable
.clone
()),
};
};
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
assert_eq!
(
assert_eq!
(
expr
,
expr!
(
"0:8"
));
expr
,
Expression
::
Const
(
Bitvector
::
zero
(
ByteSize
::
new
(
8
)
.into
()))
);
let
mut
expr
=
Expression
::
BinOp
{
let
mut
expr
=
Expression
::
BinOp
{
op
:
BinOpType
::
IntOr
,
op
:
BinOpType
::
IntOr
,
lhs
:
Box
::
new
(
rax_variable
.clone
()),
lhs
:
Box
::
new
(
rax_variable
.clone
()),
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
zero
(
ByteSize
::
new
(
8
)
.into
())
)),
rhs
:
Box
::
new
(
expr!
(
"0:8"
)),
};
};
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
assert_eq!
(
expr
,
rax_variable
);
assert_eq!
(
expr
,
rax_variable
);
let
sub_expr
=
Expression
::
BinOp
{
let
sub_expr
=
expr!
(
"RAX:8 - RCX:8"
);
lhs
:
Box
::
new
(
rax_variable
.clone
()),
op
:
BinOpType
::
IntSub
,
rhs
:
Box
::
new
(
rcx_variable
.clone
()),
};
let
mut
expr
=
Expression
::
BinOp
{
let
mut
expr
=
Expression
::
BinOp
{
op
:
BinOpType
::
IntEqual
,
op
:
BinOpType
::
IntEqual
,
lhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
zero
(
ByteSize
::
new
(
1
)
.into
())
)),
lhs
:
Box
::
new
(
expr!
(
"0:8"
)),
rhs
:
Box
::
new
(
sub_expr
.clone
()),
rhs
:
Box
::
new
(
sub_expr
.clone
()),
};
};
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
...
@@ -44,7 +38,7 @@ fn trivial_expression_substitution() {
...
@@ -44,7 +38,7 @@ fn trivial_expression_substitution() {
let
mut
expr
=
Expression
::
BinOp
{
let
mut
expr
=
Expression
::
BinOp
{
op
:
BinOpType
::
IntNotEqual
,
op
:
BinOpType
::
IntNotEqual
,
lhs
:
Box
::
new
(
sub_expr
.clone
()),
lhs
:
Box
::
new
(
sub_expr
.clone
()),
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
zero
(
ByteSize
::
new
(
1
)
.into
())
)),
rhs
:
Box
::
new
(
expr!
(
"0:8"
)),
};
};
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
assert_eq!
(
assert_eq!
(
...
@@ -108,29 +102,29 @@ fn trivial_expression_substitution() {
...
@@ -108,29 +102,29 @@ fn trivial_expression_substitution() {
arg
:
Box
::
new
(
Expression
::
Cast
{
arg
:
Box
::
new
(
Expression
::
Cast
{
op
:
CastOpType
::
IntSExt
,
op
:
CastOpType
::
IntSExt
,
size
:
ByteSize
::
new
(
8
),
size
:
ByteSize
::
new
(
8
),
arg
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"EAX"
,
4
)
)),
arg
:
Box
::
new
(
expr!
(
"EAX:4"
)),
}),
}),
};
};
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
assert_eq!
(
expr
,
Expression
::
Var
(
Variable
::
mock
(
"EAX"
,
4
)
));
assert_eq!
(
expr
,
expr!
(
"EAX:4"
));
let
mut
expr
=
Expression
::
Subpiece
{
let
mut
expr
=
Expression
::
Subpiece
{
low_byte
:
ByteSize
::
new
(
4
),
low_byte
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
arg
:
Box
::
new
(
Expression
::
BinOp
{
arg
:
Box
::
new
(
Expression
::
BinOp
{
op
:
BinOpType
::
Piece
,
op
:
BinOpType
::
Piece
,
lhs
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"EAX"
,
4
)
)),
lhs
:
Box
::
new
(
expr!
(
"EAX:4"
)),
rhs
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"EBX"
,
4
)
)),
rhs
:
Box
::
new
(
expr!
(
"EBX:4"
)),
}),
}),
};
};
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
assert_eq!
(
expr
,
Expression
::
Var
(
Variable
::
mock
(
"EAX"
,
4
)
));
assert_eq!
(
expr
,
expr!
(
"EAX:4"
));
let
mut
expr
=
Expression
::
Subpiece
{
let
mut
expr
=
Expression
::
Subpiece
{
low_byte
:
ByteSize
::
new
(
0
),
low_byte
:
ByteSize
::
new
(
0
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
arg
:
Box
::
new
(
Expression
::
Subpiece
{
arg
:
Box
::
new
(
Expression
::
Subpiece
{
low_byte
:
ByteSize
::
new
(
2
),
low_byte
:
ByteSize
::
new
(
2
),
size
:
ByteSize
::
new
(
6
),
size
:
ByteSize
::
new
(
6
),
arg
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"RAX"
,
8
)
)),
arg
:
Box
::
new
(
expr!
(
"RAX:8"
)),
}),
}),
};
};
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
...
@@ -139,7 +133,7 @@ fn trivial_expression_substitution() {
...
@@ -139,7 +133,7 @@ fn trivial_expression_substitution() {
Expression
::
Subpiece
{
Expression
::
Subpiece
{
low_byte
:
ByteSize
::
new
(
2
),
low_byte
:
ByteSize
::
new
(
2
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
arg
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"RAX"
,
8
)
)),
arg
:
Box
::
new
(
expr!
(
"RAX:8"
)),
}
}
);
);
...
@@ -165,10 +159,10 @@ fn trivial_expression_substitution() {
...
@@ -165,10 +159,10 @@ fn trivial_expression_substitution() {
lhs
:
Box
::
new
(
Expression
::
BinOp
{
lhs
:
Box
::
new
(
Expression
::
BinOp
{
lhs
:
Box
::
new
(
rax_variable
.clone
()),
lhs
:
Box
::
new
(
rax_variable
.clone
()),
op
:
BinOpType
::
IntSub
,
op
:
BinOpType
::
IntSub
,
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_i64
(
3
)
)),
rhs
:
Box
::
new
(
expr!
(
"3:8"
)),
}),
}),
op
:
BinOpType
::
IntSub
,
op
:
BinOpType
::
IntSub
,
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_i64
(
4
)
)),
rhs
:
Box
::
new
(
expr!
(
"4:8"
)),
};
};
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
assert_eq!
(
assert_eq!
(
...
@@ -176,7 +170,7 @@ fn trivial_expression_substitution() {
...
@@ -176,7 +170,7 @@ fn trivial_expression_substitution() {
Expression
::
BinOp
{
Expression
::
BinOp
{
lhs
:
Box
::
new
(
rax_variable
.clone
()),
lhs
:
Box
::
new
(
rax_variable
.clone
()),
op
:
BinOpType
::
IntSub
,
op
:
BinOpType
::
IntSub
,
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_i64
(
7
)
))
rhs
:
Box
::
new
(
expr!
(
"7:8"
))
}
}
);
);
}
}
...
@@ -187,17 +181,13 @@ fn test_complicated_a_less_than_b_substitution() {
...
@@ -187,17 +181,13 @@ fn test_complicated_a_less_than_b_substitution() {
use
Expression
::
*
;
use
Expression
::
*
;
let
sborrow_expr
=
BinOp
{
let
sborrow_expr
=
BinOp
{
op
:
IntSBorrow
,
op
:
IntSBorrow
,
lhs
:
Box
::
new
(
Var
(
Variable
::
mock
(
"RAX"
,
8
)
)),
lhs
:
Box
::
new
(
expr!
(
"RAX:8"
)),
rhs
:
Box
::
new
(
Var
(
Variable
::
mock
(
"RBX"
,
8
)
)),
rhs
:
Box
::
new
(
expr!
(
"RBX:8"
)),
};
};
let
a_minus_b_less_zero_expr
=
BinOp
{
let
a_minus_b_less_zero_expr
=
BinOp
{
op
:
IntSLess
,
op
:
IntSLess
,
lhs
:
Box
::
new
(
BinOp
{
lhs
:
Box
::
new
(
expr!
(
"RAX:8 - RBX:8"
)),
op
:
IntSub
,
rhs
:
Box
::
new
(
expr!
(
"0:8"
)),
lhs
:
Box
::
new
(
Var
(
Variable
::
mock
(
"RAX"
,
8
))),
rhs
:
Box
::
new
(
Var
(
Variable
::
mock
(
"RBX"
,
8
))),
}),
rhs
:
Box
::
new
(
Const
(
Bitvector
::
from_u64
(
0
))),
};
};
let
mut
expr
=
BinOp
{
let
mut
expr
=
BinOp
{
op
:
IntNotEqual
,
op
:
IntNotEqual
,
...
@@ -207,19 +197,19 @@ fn test_complicated_a_less_than_b_substitution() {
...
@@ -207,19 +197,19 @@ fn test_complicated_a_less_than_b_substitution() {
expr
.substitute_trivial_operations
();
expr
.substitute_trivial_operations
();
let
expected_expr
=
BinOp
{
let
expected_expr
=
BinOp
{
op
:
IntSLess
,
op
:
IntSLess
,
lhs
:
Box
::
new
(
Var
(
Variable
::
mock
(
"RAX"
,
8
)
)),
lhs
:
Box
::
new
(
expr!
(
"RAX:8"
)),
rhs
:
Box
::
new
(
Var
(
Variable
::
mock
(
"RBX"
,
8
)
)),
rhs
:
Box
::
new
(
expr!
(
"RBX:8"
)),
};
};
assert_eq!
(
expr
,
expected_expr
);
assert_eq!
(
expr
,
expected_expr
);
}
}
#[test]
#[test]
fn
display
()
{
fn
display
()
{
let
expr
=
Expression
::
const_from_i32
(
2
);
let
expr
=
expr!
(
"2:4"
);
let
mul
=
Expression
::
BinOp
{
let
mul
=
Expression
::
BinOp
{
op
:
BinOpType
::
IntMult
,
op
:
BinOpType
::
IntMult
,
lhs
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"RAX"
,
8
)
)),
lhs
:
Box
::
new
(
expr!
(
"RAX:8"
)),
rhs
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"RBP"
,
8
)
)),
rhs
:
Box
::
new
(
expr!
(
"RBP:8"
)),
};
};
let
expr
=
expr
.plus
(
mul
);
let
expr
=
expr
.plus
(
mul
);
let
expr
=
Expression
::
UnOp
{
let
expr
=
Expression
::
UnOp
{
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/jmp.rs
View file @
decc1254
...
@@ -92,23 +92,3 @@ impl fmt::Display for Jmp {
...
@@ -92,23 +92,3 @@ impl fmt::Display for Jmp {
}
}
}
}
}
}
#[cfg(test)]
pub
mod
tests
{
use
super
::
*
;
impl
Jmp
{
/// Create a mock call to a TID with the given `target` and `return_`
/// as the names of the target and return TIDs.
pub
fn
mock_call
(
target
:
&
str
,
return_
:
Option
<&
str
>
)
->
Term
<
Jmp
>
{
let
call
=
Jmp
::
Call
{
target
:
Tid
::
new
(
target
.to_string
()),
return_
:
return_
.map
(|
tid_name
|
Tid
::
new
(
tid_name
)),
};
Term
{
tid
:
Tid
::
new
(
format!
(
"call_{}"
,
target
.to_string
())),
term
:
call
,
}
}
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/macros/mod.rs
View file @
decc1254
...
@@ -189,7 +189,7 @@ pub mod parsing {
...
@@ -189,7 +189,7 @@ pub mod parsing {
#[allow(dead_code)]
#[allow(dead_code)]
pub
fn
parse_expr
<
S
:
AsRef
<
str
>>
(
str
:
S
)
->
Expression
{
pub
fn
parse_expr
<
S
:
AsRef
<
str
>>
(
str
:
S
)
->
Expression
{
let
set
=
RegexSet
::
new
([
let
set
=
RegexSet
::
new
([
r
"^[[:alnum:]&&[^0-9]]{1}[[:alnum:]&&[^x]]?[[:alnum:]]*:[0-9]{1,2}$"
,
// Variable
r
"^[[:alnum:]&&[^0-9]]{1}[[:alnum:]&&[^x]]?[[:alnum:]
_
]*:[0-9]{1,2}$"
,
// Variable
r
"^((0x(-)?[[:alnum:]]+)|^(-)?([0-9])+)+:[0-9]+$"
,
// Constant
r
"^((0x(-)?[[:alnum:]]+)|^(-)?([0-9])+)+:[0-9]+$"
,
// Constant
r
"^[^
\
+]*
\
+{1}[^
\
+]*$"
,
// BinOp (IntAdd)
r
"^[^
\
+]*
\
+{1}[^
\
+]*$"
,
// BinOp (IntAdd)
r
"^[[:ascii:]]+
\
-{1} [[:ascii:]]+$"
,
// BinOp (IntSub)
r
"^[[:ascii:]]+
\
-{1} [[:ascii:]]+$"
,
// BinOp (IntSub)
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/mod.rs
View file @
decc1254
...
@@ -194,50 +194,6 @@ mod tests {
...
@@ -194,50 +194,6 @@ mod tests {
use
super
::
*
;
use
super
::
*
;
use
apint
::
BitWidth
;
use
apint
::
BitWidth
;
impl
DatatypeProperties
{
pub
fn
mock
()
->
DatatypeProperties
{
DatatypeProperties
{
char_size
:
ByteSize
::
new
(
1
),
double_size
:
ByteSize
::
new
(
8
),
float_size
:
ByteSize
::
new
(
4
),
integer_size
:
ByteSize
::
new
(
4
),
long_double_size
:
ByteSize
::
new
(
8
),
long_long_size
:
ByteSize
::
new
(
8
),
long_size
:
ByteSize
::
new
(
4
),
pointer_size
:
ByteSize
::
new
(
8
),
short_size
:
ByteSize
::
new
(
2
),
}
}
/// Datatype sizes according to System V ABI
pub
fn
mock_x64
()
->
DatatypeProperties
{
DatatypeProperties
{
char_size
:
ByteSize
::
new
(
1
),
double_size
:
ByteSize
::
new
(
8
),
float_size
:
ByteSize
::
new
(
4
),
integer_size
:
ByteSize
::
new
(
4
),
long_double_size
:
ByteSize
::
new
(
16
),
long_long_size
:
ByteSize
::
new
(
8
),
long_size
:
ByteSize
::
new
(
8
),
pointer_size
:
ByteSize
::
new
(
8
),
short_size
:
ByteSize
::
new
(
2
),
}
}
pub
fn
mock_arm32
()
->
DatatypeProperties
{
DatatypeProperties
{
char_size
:
ByteSize
::
new
(
1
),
double_size
:
ByteSize
::
new
(
8
),
float_size
:
ByteSize
::
new
(
4
),
integer_size
:
ByteSize
::
new
(
4
),
long_double_size
:
ByteSize
::
new
(
8
),
long_long_size
:
ByteSize
::
new
(
8
),
long_size
:
ByteSize
::
new
(
4
),
pointer_size
:
ByteSize
::
new
(
4
),
short_size
:
ByteSize
::
new
(
2
),
}
}
}
#[test]
#[test]
fn
check_bit_to_byte_conversion
()
{
fn
check_bit_to_byte_conversion
()
{
let
bits
:
BitWidth
=
BitWidth
::
new
(
8
)
.unwrap
();
let
bits
:
BitWidth
=
BitWidth
::
new
(
8
)
.unwrap
();
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/program.rs
View file @
decc1254
...
@@ -49,75 +49,3 @@ impl Program {
...
@@ -49,75 +49,3 @@ impl Program {
None
None
}
}
}
}
#[cfg(test)]
mod
tests
{
use
crate
::
intermediate_representation
::{
CallingConvention
,
Datatype
};
use
super
::
*
;
impl
Program
{
fn
add_extern_symbols_to_program
(
a
:
Vec
<
(
Tid
,
ExternSymbol
)
>
)
->
Program
{
Program
{
subs
:
BTreeMap
::
new
(),
extern_symbols
:
BTreeMap
::
from_iter
(
a
),
entry_points
:
BTreeSet
::
new
(),
address_base_offset
:
0x1000u64
,
}
}
/// Returns Program with malloc, free and other_function
pub
fn
mock_x64
()
->
Program
{
let
malloc
=
ExternSymbol
::
create_extern_symbol
(
"malloc"
,
CallingConvention
::
mock_x64
(),
Some
(
Datatype
::
Integer
),
Some
(
Datatype
::
Pointer
),
);
let
free
=
ExternSymbol
::
create_extern_symbol
(
"free"
,
CallingConvention
::
mock_x64
(),
Some
(
Datatype
::
Pointer
),
None
,
);
let
other_function
=
ExternSymbol
::
create_extern_symbol
(
"other_function"
,
CallingConvention
::
mock_x64
(),
None
,
None
,
);
Program
::
add_extern_symbols_to_program
(
vec!
[
(
malloc
.tid
.clone
(),
malloc
),
(
free
.tid
.clone
(),
free
),
(
other_function
.tid
.clone
(),
other_function
),
])
}
/// Returns Program with malloc, free and other_function
pub
fn
mock_arm32
()
->
Program
{
let
malloc
=
ExternSymbol
::
create_extern_symbol
(
"malloc"
,
CallingConvention
::
mock_arm32
(),
Some
(
Datatype
::
Integer
),
Some
(
Datatype
::
Pointer
),
);
let
free
=
ExternSymbol
::
create_extern_symbol
(
"free"
,
CallingConvention
::
mock_arm32
(),
Some
(
Datatype
::
Pointer
),
None
,
);
let
other_function
=
ExternSymbol
::
create_extern_symbol
(
"other_function"
,
CallingConvention
::
mock_arm32
(),
None
,
None
,
);
Program
::
add_extern_symbols_to_program
(
vec!
[
(
malloc
.tid
.clone
(),
malloc
),
(
free
.tid
.clone
(),
free
),
(
other_function
.tid
.clone
(),
other_function
),
])
}
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/project.rs
View file @
decc1254
...
@@ -291,75 +291,6 @@ impl Term<Jmp> {
...
@@ -291,75 +291,6 @@ impl Term<Jmp> {
mod
tests
{
mod
tests
{
use
super
::
*
;
use
super
::
*
;
impl
Project
{
/// Returns project with x64 calling convention and mocked program.
pub
fn
mock_x64
()
->
Project
{
let
mut
none_cconv_register
:
Vec
<
Variable
>
=
vec!
[
"RAX"
,
"RBX"
,
"RSP"
,
"RBP"
,
"R10"
,
"R11"
,
"R12"
,
"R13"
,
"R14"
,
"R15"
,
]
.into_iter
()
.map
(|
name
|
Variable
::
mock
(
name
,
ByteSize
::
new
(
8
)))
.collect
();
let
mut
integer_register
=
CallingConvention
::
mock_x64
()
.integer_parameter_register
;
integer_register
.append
(
&
mut
none_cconv_register
);
let
calling_conventions
:
BTreeMap
<
String
,
CallingConvention
>
=
BTreeMap
::
from
([(
"__stdcall"
.to_string
(),
CallingConvention
::
mock_x64
())]);
Project
{
program
:
Term
{
tid
:
Tid
::
new
(
"program_tid"
),
term
:
Program
::
mock_x64
(),
},
cpu_architecture
:
"x86_64"
.to_string
(),
stack_pointer_register
:
Variable
::
mock
(
"RSP"
,
8u64
),
calling_conventions
,
register_set
:
integer_register
.iter
()
.cloned
()
.collect
(),
datatype_properties
:
DatatypeProperties
::
mock_x64
(),
runtime_memory_image
:
RuntimeMemoryImage
::
mock
(),
}
}
pub
fn
mock_arm32
()
->
Project
{
let
none_cconv_4byte_register
:
Vec
<
Variable
>
=
vec!
[
"r12"
,
"r14"
,
"r15"
]
.into_iter
()
.map
(|
name
|
Variable
::
mock
(
name
,
ByteSize
::
new
(
4
)))
.collect
();
let
none_cconv_16byte_register
:
Vec
<
Variable
>
=
vec!
[
"q0"
,
"q1"
,
"q2"
,
"q3"
,
"q8"
,
"q9"
,
"q10"
,
"q11"
,
"q12"
,
"q13"
,
"q14"
,
"q15"
,
]
.into_iter
()
.map
(|
name
|
Variable
::
mock
(
name
,
ByteSize
::
new
(
16
)))
.collect
();
let
callee_saved_register
=
CallingConvention
::
mock_arm32
()
.callee_saved_register
;
let
integer_register
=
CallingConvention
::
mock_arm32
()
.integer_parameter_register
.into_iter
()
.chain
(
none_cconv_4byte_register
)
.chain
(
none_cconv_16byte_register
)
.chain
(
callee_saved_register
);
Project
{
program
:
Term
{
tid
:
Tid
::
new
(
"program_tid"
),
term
:
Program
::
mock_arm32
(),
},
cpu_architecture
:
"arm32"
.to_string
(),
stack_pointer_register
:
Variable
::
mock
(
"sp"
,
4u64
),
calling_conventions
:
BTreeMap
::
from
([(
"__stdcall"
.to_string
(),
CallingConvention
::
mock_arm32
(),
)]),
register_set
:
integer_register
.collect
(),
datatype_properties
:
DatatypeProperties
::
mock_arm32
(),
runtime_memory_image
:
RuntimeMemoryImage
::
mock
(),
}
}
}
#[test]
#[test]
fn
retarget_nonexisting_jumps
()
{
fn
retarget_nonexisting_jumps
()
{
let
mut
jmp_term
=
Term
{
let
mut
jmp_term
=
Term
{
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/project/propagate_control_flow.rs
View file @
decc1254
...
@@ -245,12 +245,13 @@ fn negate_condition(expr: Expression) -> Expression {
...
@@ -245,12 +245,13 @@ fn negate_condition(expr: Expression) -> Expression {
#[cfg(test)]
#[cfg(test)]
pub
mod
tests
{
pub
mod
tests
{
use
super
::
*
;
use
super
::
*
;
use
crate
::{
def
,
expr
};
use
std
::
collections
::
BTreeMap
;
use
std
::
collections
::
BTreeMap
;
fn
mock_condition_block
(
name
:
&
str
,
if_target
:
&
str
,
else_target
:
&
str
)
->
Term
<
Blk
>
{
fn
mock_condition_block
(
name
:
&
str
,
if_target
:
&
str
,
else_target
:
&
str
)
->
Term
<
Blk
>
{
let
if_jmp
=
Jmp
::
CBranch
{
let
if_jmp
=
Jmp
::
CBranch
{
target
:
Tid
::
new
(
if_target
),
target
:
Tid
::
new
(
if_target
),
condition
:
Expression
::
Var
(
Variable
::
mock
(
"zero_flag"
,
ByteSize
::
new
(
1
))
),
condition
:
expr!
(
"zero_flag:1"
),
};
};
let
if_jmp
=
Term
{
let
if_jmp
=
Term
{
tid
:
Tid
::
new
(
name
.to_string
()
+
"_jmp_if"
),
tid
:
Tid
::
new
(
name
.to_string
()
+
"_jmp_if"
),
...
@@ -273,14 +274,8 @@ pub mod tests {
...
@@ -273,14 +274,8 @@ pub mod tests {
}
}
fn
mock_block_with_defs
(
name
:
&
str
,
return_target
:
&
str
)
->
Term
<
Blk
>
{
fn
mock_block_with_defs
(
name
:
&
str
,
return_target
:
&
str
)
->
Term
<
Blk
>
{
let
def
=
Def
::
Assign
{
let
def
=
def!
[
format!
(
"{name}_def: r0:4 = r1:4"
)];
var
:
Variable
::
mock
(
"r0"
,
ByteSize
::
new
(
4
)),
value
:
Expression
::
Var
(
Variable
::
mock
(
"r1"
,
ByteSize
::
new
(
4
))),
};
let
def
=
Term
{
tid
:
Tid
::
new
(
name
.to_string
()
+
"_def"
),
term
:
def
,
};
let
jmp
=
Jmp
::
Branch
(
Tid
::
new
(
return_target
));
let
jmp
=
Jmp
::
Branch
(
Tid
::
new
(
return_target
));
let
jmp
=
Term
{
let
jmp
=
Term
{
tid
:
Tid
::
new
(
name
.to_string
()
+
"_jmp"
),
tid
:
Tid
::
new
(
name
.to_string
()
+
"_jmp"
),
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/runtime_memory_image.rs
View file @
decc1254
...
@@ -5,8 +5,10 @@ use goblin::{elf, Object};
...
@@ -5,8 +5,10 @@ use goblin::{elf, Object};
/// A representation of the runtime image of a binary after being loaded into memory by the loader.
/// A representation of the runtime image of a binary after being loaded into memory by the loader.
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
RuntimeMemoryImage
{
pub
struct
RuntimeMemoryImage
{
memory_segments
:
Vec
<
MemorySegment
>
,
/// Sequence of memory segments.
is_little_endian
:
bool
,
pub
memory_segments
:
Vec
<
MemorySegment
>
,
/// Endianness
pub
is_little_endian
:
bool
,
}
}
impl
RuntimeMemoryImage
{
impl
RuntimeMemoryImage
{
...
@@ -276,108 +278,29 @@ impl RuntimeMemoryImage {
...
@@ -276,108 +278,29 @@ impl RuntimeMemoryImage {
}
}
}
}
impl
RuntimeMemoryImage
{
/// Creates a mock runtime memory image with: byte series, strings and format strings.
pub
fn
mock
()
->
RuntimeMemoryImage
{
RuntimeMemoryImage
{
memory_segments
:
vec!
[
MemorySegment
{
bytes
:
[
0xb0u8
,
0xb1
,
0xb2
,
0xb3
,
0xb4
]
.to_vec
(),
base_address
:
0x1000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
MemorySegment
{
bytes
:
[
0u8
;
8
]
.to_vec
(),
base_address
:
0x2000
,
read_flag
:
true
,
write_flag
:
true
,
execute_flag
:
false
,
},
// Contains the Hello World string at byte 3002.
MemorySegment
{
bytes
:
[
0x01
,
0x02
,
0x48
,
0x65
,
0x6c
,
0x6c
,
0x6f
,
0x20
,
0x57
,
0x6f
,
0x72
,
0x6c
,
0x64
,
0x00
,
]
.to_vec
(),
base_address
:
0x3000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
MemorySegment
{
bytes
:
[
0x02
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
]
.to_vec
(),
base_address
:
0x4000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
// Contains strings: '/dev/sd%c%d' and 'cat %s'
MemorySegment
{
bytes
:
[
0x2f
,
0x64
,
0x65
,
0x76
,
0x2f
,
0x73
,
0x64
,
0x25
,
0x63
,
0x25
,
0x64
,
0x00
,
0x63
,
0x61
,
0x74
,
0x20
,
0x25
,
0x73
,
0x00
,
]
.to_vec
(),
base_address
:
0x5000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
// Contains string: 'cat %s %s %s %s' starting at the first byte.
MemorySegment
{
bytes
:
[
0x63
,
0x61
,
0x74
,
0x20
,
0x25
,
0x73
,
0x20
,
0x25
,
0x73
,
0x20
,
0x25
,
0x73
,
0x20
,
0x25
,
0x73
,
0x00
,
]
.to_vec
(),
base_address
:
0x6000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
// Contains string: 'str1 str2 str3 str4'
MemorySegment
{
bytes
:
[
0x73
,
0x74
,
0x72
,
0x31
,
0x20
,
0x73
,
0x74
,
0x72
,
0x32
,
0x20
,
0x73
,
0x74
,
0x72
,
0x33
,
0x20
,
0x73
,
0x74
,
0x72
,
0x34
,
0x00
,
]
.to_vec
(),
base_address
:
0x7000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
],
is_little_endian
:
true
,
}
}
}
#[cfg(test)]
#[cfg(test)]
mod
tests
{
mod
tests
{
use
crate
::
intermediate_representation
::{
Bitvector
,
ByteSize
,
RuntimeMemoryImage
};
use
crate
::
{
bitvec
,
intermediate_representation
::
*
};
#[test]
#[test]
fn
read_endianness
()
{
fn
read_endianness
()
{
let
mut
mem_image
=
RuntimeMemoryImage
::
mock
();
let
mut
mem_image
=
RuntimeMemoryImage
::
mock
();
let
address
=
Bitvector
::
from_u32
(
0x1001
);
let
address
=
bitvec!
(
"0x1001:4"
);
assert_eq!
(
assert_eq!
(
mem_image
.read
(
&
address
,
ByteSize
::
new
(
4
))
.unwrap
(),
mem_image
.read
(
&
address
,
ByteSize
::
new
(
4
))
.unwrap
(),
Bitvector
::
from_u32
(
0xb4b3b2b1
)
.into
()
bitvec!
(
"0xb4b3b2b1:4"
)
.into
()
);
);
mem_image
.is_little_endian
=
false
;
mem_image
.is_little_endian
=
false
;
assert_eq!
(
assert_eq!
(
mem_image
.read
(
&
address
,
ByteSize
::
new
(
4
))
.unwrap
(),
mem_image
.read
(
&
address
,
ByteSize
::
new
(
4
))
.unwrap
(),
Bitvector
::
from_u32
(
0xb1b2b3b4
)
.into
()
bitvec!
(
"0xb1b2b3b4:4"
)
.into
()
);
);
}
}
#[test]
#[test]
fn
ro_data_pointer
()
{
fn
ro_data_pointer
()
{
let
mem_image
=
RuntimeMemoryImage
::
mock
();
let
mem_image
=
RuntimeMemoryImage
::
mock
();
let
address
=
Bitvector
::
from_u32
(
0x1002
);
let
address
=
bitvec!
(
"0x1002:4"
);
let
(
slice
,
index
)
=
mem_image
.get_ro_data_pointer_at_address
(
&
address
)
.unwrap
();
let
(
slice
,
index
)
=
mem_image
.get_ro_data_pointer_at_address
(
&
address
)
.unwrap
();
assert_eq!
(
index
,
2
);
assert_eq!
(
index
,
2
);
assert_eq!
(
&
slice
[
index
..
],
&
[
0xb2u8
,
0xb3
,
0xb4
]);
assert_eq!
(
&
slice
[
index
..
],
&
[
0xb2u8
,
0xb3
,
0xb4
]);
...
@@ -389,7 +312,7 @@ mod tests {
...
@@ -389,7 +312,7 @@ mod tests {
// the byte array contains "Hello World".
// the byte array contains "Hello World".
let
expected_string
:
&
str
=
let
expected_string
:
&
str
=
std
::
str
::
from_utf8
(
b
"
\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64
"
)
.unwrap
();
std
::
str
::
from_utf8
(
b
"
\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64
"
)
.unwrap
();
let
address
=
Bitvector
::
from_u32
(
0x3002
);
let
address
=
bitvec!
(
"0x3002:4"
);
assert_eq!
(
assert_eq!
(
expected_string
,
expected_string
,
mem_image
mem_image
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/sub.rs
View file @
decc1254
...
@@ -195,232 +195,3 @@ impl CallingConvention {
...
@@ -195,232 +195,3 @@ impl CallingConvention {
register_list
register_list
}
}
}
}
#[cfg(test)]
mod
tests
{
use
super
::
*
;
impl
Sub
{
pub
fn
mock
(
name
:
impl
ToString
)
->
Term
<
Sub
>
{
Term
{
tid
:
Tid
::
new
(
name
.to_string
()),
term
:
Sub
{
name
:
name
.to_string
(),
blocks
:
Vec
::
new
(),
calling_convention
:
None
,
},
}
}
}
/// Wrapper for subpiece to model float register for argument passing
fn
create_float_register_subpiece
(
name
:
&
str
,
reg_size
:
u64
,
low_byte
:
u64
,
size
:
u64
,
)
->
Expression
{
Expression
::
subpiece
(
Expression
::
Var
(
Variable
::
mock
(
name
,
reg_size
)),
ByteSize
::
new
(
low_byte
),
ByteSize
::
new
(
size
),
)
}
impl
CallingConvention
{
/// Creates System V Calling Convention with Advanced Vector Extensions 512
pub
fn
mock_x64
()
->
CallingConvention
{
CallingConvention
{
name
:
"__stdcall"
.to_string
(),
// so that the mock is useable as standard calling convention in tests
integer_parameter_register
:
vec!
[
Variable
::
mock
(
"RDI"
,
8
),
Variable
::
mock
(
"RSI"
,
8
),
Variable
::
mock
(
"RDX"
,
8
),
Variable
::
mock
(
"RCX"
,
8
),
Variable
::
mock
(
"R8"
,
8
),
Variable
::
mock
(
"R9"
,
8
),
],
// ABI: first 8 Bytes of ZMM0-ZMM7 for float parameter
// Ghidra: first 8 Bytes of YMM0-YMM7 for float parameter
float_parameter_register
:
vec!
[
create_float_register_subpiece
(
"ZMM0"
,
64
,
0
,
8
),
create_float_register_subpiece
(
"ZMM1"
,
64
,
0
,
8
),
create_float_register_subpiece
(
"ZMM2"
,
64
,
0
,
8
),
create_float_register_subpiece
(
"ZMM3"
,
64
,
0
,
8
),
create_float_register_subpiece
(
"ZMM4"
,
64
,
0
,
8
),
create_float_register_subpiece
(
"ZMM5"
,
64
,
0
,
8
),
create_float_register_subpiece
(
"ZMM6"
,
64
,
0
,
8
),
create_float_register_subpiece
(
"ZMM7"
,
64
,
0
,
8
),
],
integer_return_register
:
vec!
[
Variable
::
mock
(
"RAX"
,
8
),
Variable
::
mock
(
"RDX"
,
8
)],
// ABI: XMM0-XMM1 float return register
// Ghidra: uses XMM0 only
float_return_register
:
vec!
[
create_float_register_subpiece
(
"ZMM0"
,
64
,
0
,
8
)],
callee_saved_register
:
vec!
[
Variable
::
mock
(
"RBP"
,
8
),
Variable
::
mock
(
"RBX"
,
8
),
Variable
::
mock
(
"RSP"
,
8
),
Variable
::
mock
(
"R12"
,
8
),
Variable
::
mock
(
"R13"
,
8
),
Variable
::
mock
(
"R14"
,
8
),
Variable
::
mock
(
"R15"
,
8
),
],
}
}
/// Following ARM32 ABI with MVE Extention
pub
fn
mock_arm32
()
->
CallingConvention
{
CallingConvention
{
name
:
"__stdcall"
.to_string
(),
// so that the mock is useable as standard calling convention in tests
integer_parameter_register
:
vec!
[
Variable
::
mock
(
"r0"
,
4
),
Variable
::
mock
(
"r1"
,
4
),
Variable
::
mock
(
"r2"
,
4
),
Variable
::
mock
(
"r3"
,
4
),
],
// ABI: q0-q3 used for argument passing
// Ghidra: uses q0-q1 only
float_parameter_register
:
vec!
[
create_float_register_subpiece
(
"q0"
,
16
,
0
,
4
),
create_float_register_subpiece
(
"q0"
,
16
,
4
,
4
),
create_float_register_subpiece
(
"q0"
,
16
,
8
,
4
),
create_float_register_subpiece
(
"q0"
,
16
,
12
,
4
),
create_float_register_subpiece
(
"q1"
,
16
,
0
,
4
),
create_float_register_subpiece
(
"q1"
,
16
,
4
,
4
),
create_float_register_subpiece
(
"q1"
,
16
,
8
,
4
),
create_float_register_subpiece
(
"q1"
,
16
,
12
,
4
),
],
// ABI: r0-r1 used as integer return register
// Ghidra uses r0 only
integer_return_register
:
vec!
[
Variable
::
mock
(
"r0"
,
4
),
Variable
::
mock
(
"r1"
,
4
),
Variable
::
mock
(
"r2"
,
4
),
Variable
::
mock
(
"r3"
,
4
),
],
// ABI: whole q0 used as float return
// Ghidra: uses first 8 Bytes of q0 only
float_return_register
:
vec!
[
create_float_register_subpiece
(
"q0"
,
16
,
0
,
4
)],
callee_saved_register
:
vec!
[
Variable
::
mock
(
"r4"
,
4
),
Variable
::
mock
(
"r5"
,
4
),
Variable
::
mock
(
"r6"
,
4
),
Variable
::
mock
(
"r7"
,
4
),
Variable
::
mock
(
"r8"
,
4
),
Variable
::
mock
(
"r9"
,
4
),
Variable
::
mock
(
"r10"
,
4
),
Variable
::
mock
(
"r11"
,
4
),
Variable
::
mock
(
"r13"
,
4
),
Variable
::
mock
(
"q4"
,
16
),
Variable
::
mock
(
"q5"
,
16
),
Variable
::
mock
(
"q6"
,
16
),
Variable
::
mock
(
"q7"
,
16
),
],
}
}
}
impl
Arg
{
pub
fn
mock_register
(
name
:
impl
ToString
,
size_in_bytes
:
impl
Into
<
ByteSize
>
)
->
Arg
{
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
name
.to_string
(),
size_in_bytes
)),
data_type
:
None
,
}
}
pub
fn
mock_register_with_data_type
(
name
:
impl
ToString
,
size_in_bytes
:
impl
Into
<
ByteSize
>
,
data_type
:
Option
<
Datatype
>
,
)
->
Arg
{
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
name
.to_string
(),
size_in_bytes
)),
data_type
,
}
}
pub
fn
mock_pointer_register
(
name
:
impl
ToString
,
size_in_bytes
:
impl
Into
<
ByteSize
>
,
)
->
Arg
{
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
name
.to_string
(),
size_in_bytes
)),
data_type
:
Some
(
Datatype
::
Pointer
),
}
}
}
impl
ExternSymbol
{
pub
fn
mock_x64
(
name
:
impl
ToString
)
->
ExternSymbol
{
ExternSymbol
{
tid
:
Tid
::
new
(
name
.to_string
()),
addresses
:
vec!
[
"UNKNOWN"
.to_string
()],
name
:
name
.to_string
(),
calling_convention
:
Some
(
"__stdcall"
.to_string
()),
parameters
:
vec!
[
Arg
::
mock_register
(
"RDI"
,
8
)],
return_values
:
vec!
[
Arg
::
mock_register
(
"RAX"
,
8
)],
no_return
:
false
,
has_var_args
:
false
,
}
}
pub
fn
mock_arm32
(
name
:
impl
ToString
)
->
ExternSymbol
{
ExternSymbol
{
tid
:
Tid
::
new
(
name
.to_string
()),
addresses
:
vec!
[
"UNKNOWN"
.to_string
()],
name
:
name
.to_string
(),
calling_convention
:
Some
(
"__stdcall"
.to_string
()),
parameters
:
vec!
[
Arg
::
mock_register
(
"r0"
,
4
)],
return_values
:
vec!
[
Arg
::
mock_register
(
"r0"
,
4
)],
no_return
:
false
,
has_var_args
:
false
,
}
}
pub
fn
mock_sprintf_x64
()
->
Self
{
ExternSymbol
{
tid
:
Tid
::
new
(
"sprintf"
),
addresses
:
vec!
[
"UNKNOWN"
.to_string
()],
name
:
"sprintf"
.to_string
(),
calling_convention
:
Some
(
"__stdcall"
.to_string
()),
parameters
:
vec!
[
Arg
::
mock_register
(
"RDI"
,
8
),
Arg
::
mock_register
(
"RSI"
,
8
)],
return_values
:
vec!
[
Arg
::
mock_register
(
"RAX"
,
8
)],
no_return
:
false
,
has_var_args
:
true
,
}
}
/// Returns extern symbol with argument/return register according to calling convention
pub
fn
create_extern_symbol
(
name
:
&
str
,
cconv
:
CallingConvention
,
arg_type
:
Option
<
Datatype
>
,
return_type
:
Option
<
Datatype
>
,
)
->
ExternSymbol
{
ExternSymbol
{
tid
:
Tid
::
new
(
name
),
addresses
:
vec!
[],
name
:
name
.to_string
(),
calling_convention
:
Some
(
cconv
.name
),
parameters
:
match
arg_type
{
Some
(
data_type
)
=>
{
vec!
[
Arg
::
from_var
(
cconv
.integer_parameter_register
[
0
]
.clone
(),
Some
(
data_type
),
)]
}
None
=>
vec!
[],
},
return_values
:
match
return_type
{
Some
(
data_type
)
=>
{
vec!
[
Arg
::
from_var
(
cconv
.integer_return_register
[
0
]
.clone
(),
Some
(
data_type
),
)]
}
None
=>
vec!
[],
},
no_return
:
false
,
has_var_args
:
false
,
}
}
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/term.rs
View file @
decc1254
use
crate
::
prelude
::
*
;
use
crate
::
prelude
::
*
;
mod
builder
;
mod
builder_high_lvl
;
mod
builder_low_lvl
;
/// A term identifier consisting of an ID string (which is required to be unique)
/// A term identifier consisting of an ID string (which is required to be unique)
/// and an address to indicate where the term is located.
/// and an address to indicate where the term is located.
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/term/builder.rs
deleted
100644 → 0
View file @
dcbdac1e
//! This module contains the implementations of various builder functions
//! for different terms.
#[cfg(test)]
use
crate
::
intermediate_representation
::{
Def
,
Expression
,
Jmp
,
Variable
};
#[cfg(test)]
use
super
::{
Term
,
Tid
};
/// ## Helper functions for building defs
#[cfg(test)]
impl
Def
{
/// Shortcut for creating a assign def
pub
fn
assign
(
tid
:
&
str
,
var
:
Variable
,
value
:
Expression
)
->
Term
<
Def
>
{
Term
{
tid
:
Tid
::
new
(
tid
),
term
:
Def
::
Assign
{
var
,
value
},
}
}
/// Shortcut for creating a load def
pub
fn
load
(
tid
:
&
str
,
var
:
Variable
,
address
:
Expression
)
->
Term
<
Def
>
{
Term
{
tid
:
Tid
::
new
(
tid
),
term
:
Def
::
Load
{
var
,
address
},
}
}
/// Shortcut for creating a store def
pub
fn
store
(
tid
:
&
str
,
address
:
Expression
,
value
:
Expression
)
->
Term
<
Def
>
{
Term
{
tid
:
Tid
::
new
(
tid
),
term
:
Def
::
Store
{
address
,
value
},
}
}
}
/// ## Helper functions for building jmps
#[cfg(test)]
impl
Jmp
{
/// Shortcut for creating a call
pub
fn
call
(
tid
:
&
str
,
target_tid
:
&
str
,
return_tid
:
Option
<&
str
>
)
->
Term
<
Jmp
>
{
let
return_tid
=
return_tid
.map
(|
tid_name
|
Tid
::
new
(
tid_name
));
Term
{
tid
:
Tid
::
new
(
tid
),
term
:
Jmp
::
Call
{
target
:
Tid
::
new
(
target_tid
),
return_
:
return_tid
,
},
}
}
/// Shortcut for creating a branch
pub
fn
branch
(
tid
:
&
str
,
target_tid
:
&
str
)
->
Term
<
Jmp
>
{
Term
{
tid
:
Tid
::
new
(
tid
),
term
:
Jmp
::
Branch
(
Tid
::
new
(
target_tid
)),
}
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/term/builder_high_lvl.rs
0 → 100644
View file @
decc1254
//! This module contains the implementations of various builder functions for
//! the higher intermediate representation [Project](crate::intermediate_representation::Expression),
//! [Program](crate::intermediate_representation::Expression)
//! and [RuntimeMemoryImage](crate::intermediate_representation::Expression).
#[cfg(test)]
use
crate
::
utils
::
binary
::
MemorySegment
;
#[cfg(test)]
use
crate
::{
intermediate_representation
::
*
,
variable
};
#[cfg(test)]
use
std
::
collections
::{
BTreeMap
,
BTreeSet
};
#[cfg(test)]
impl
RuntimeMemoryImage
{
/// Creates a mock runtime memory image with: byte series, strings and format strings.
pub
fn
mock
()
->
RuntimeMemoryImage
{
RuntimeMemoryImage
{
memory_segments
:
vec!
[
MemorySegment
{
bytes
:
[
0xb0u8
,
0xb1
,
0xb2
,
0xb3
,
0xb4
]
.to_vec
(),
base_address
:
0x1000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
MemorySegment
{
bytes
:
[
0u8
;
8
]
.to_vec
(),
base_address
:
0x2000
,
read_flag
:
true
,
write_flag
:
true
,
execute_flag
:
false
,
},
// Contains the Hello World string at byte 3002.
MemorySegment
{
bytes
:
[
0x01
,
0x02
,
0x48
,
0x65
,
0x6c
,
0x6c
,
0x6f
,
0x20
,
0x57
,
0x6f
,
0x72
,
0x6c
,
0x64
,
0x00
,
]
.to_vec
(),
base_address
:
0x3000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
MemorySegment
{
bytes
:
[
0x02
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
]
.to_vec
(),
base_address
:
0x4000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
// Contains strings: '/dev/sd%c%d' and 'cat %s'
MemorySegment
{
bytes
:
[
0x2f
,
0x64
,
0x65
,
0x76
,
0x2f
,
0x73
,
0x64
,
0x25
,
0x63
,
0x25
,
0x64
,
0x00
,
0x63
,
0x61
,
0x74
,
0x20
,
0x25
,
0x73
,
0x00
,
]
.to_vec
(),
base_address
:
0x5000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
// Contains string: 'cat %s %s %s %s' starting at the first byte.
MemorySegment
{
bytes
:
[
0x63
,
0x61
,
0x74
,
0x20
,
0x25
,
0x73
,
0x20
,
0x25
,
0x73
,
0x20
,
0x25
,
0x73
,
0x20
,
0x25
,
0x73
,
0x00
,
]
.to_vec
(),
base_address
:
0x6000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
// Contains string: 'str1 str2 str3 str4'
MemorySegment
{
bytes
:
[
0x73
,
0x74
,
0x72
,
0x31
,
0x20
,
0x73
,
0x74
,
0x72
,
0x32
,
0x20
,
0x73
,
0x74
,
0x72
,
0x33
,
0x20
,
0x73
,
0x74
,
0x72
,
0x34
,
0x00
,
]
.to_vec
(),
base_address
:
0x7000
,
read_flag
:
true
,
write_flag
:
false
,
execute_flag
:
false
,
},
],
is_little_endian
:
true
,
}
}
}
#[cfg(test)]
impl
Program
{
fn
add_extern_symbols_to_program
(
a
:
Vec
<
(
Tid
,
ExternSymbol
)
>
)
->
Program
{
Program
{
subs
:
BTreeMap
::
new
(),
extern_symbols
:
BTreeMap
::
from_iter
(
a
),
entry_points
:
BTreeSet
::
new
(),
address_base_offset
:
0x1000u64
,
}
}
/// Returns Program with malloc, free and other_function
pub
fn
mock_x64
()
->
Program
{
let
malloc
=
ExternSymbol
::
create_extern_symbol
(
"malloc"
,
CallingConvention
::
mock_x64
(),
Some
(
Datatype
::
Integer
),
Some
(
Datatype
::
Pointer
),
);
let
free
=
ExternSymbol
::
create_extern_symbol
(
"free"
,
CallingConvention
::
mock_x64
(),
Some
(
Datatype
::
Pointer
),
None
,
);
let
other_function
=
ExternSymbol
::
create_extern_symbol
(
"other_function"
,
CallingConvention
::
mock_x64
(),
None
,
None
,
);
Program
::
add_extern_symbols_to_program
(
vec!
[
(
malloc
.tid
.clone
(),
malloc
),
(
free
.tid
.clone
(),
free
),
(
other_function
.tid
.clone
(),
other_function
),
])
}
/// Returns Program with malloc, free and other_function
pub
fn
mock_arm32
()
->
Program
{
let
malloc
=
ExternSymbol
::
create_extern_symbol
(
"malloc"
,
CallingConvention
::
mock_arm32
(),
Some
(
Datatype
::
Integer
),
Some
(
Datatype
::
Pointer
),
);
let
free
=
ExternSymbol
::
create_extern_symbol
(
"free"
,
CallingConvention
::
mock_arm32
(),
Some
(
Datatype
::
Pointer
),
None
,
);
let
other_function
=
ExternSymbol
::
create_extern_symbol
(
"other_function"
,
CallingConvention
::
mock_arm32
(),
None
,
None
,
);
Program
::
add_extern_symbols_to_program
(
vec!
[
(
malloc
.tid
.clone
(),
malloc
),
(
free
.tid
.clone
(),
free
),
(
other_function
.tid
.clone
(),
other_function
),
])
}
}
#[cfg(test)]
impl
Project
{
/// Returns project with x64 calling convention and mocked program.
pub
fn
mock_x64
()
->
Project
{
let
mut
none_cconv_register
:
Vec
<
Variable
>
=
vec!
[
"RAX"
,
"RBX"
,
"RSP"
,
"RBP"
,
"R10"
,
"R11"
,
"R12"
,
"R13"
,
"R14"
,
"R15"
,
]
.into_iter
()
.map
(|
name
|
variable!
(
format!
(
"{name}:8"
)))
.collect
();
let
mut
integer_register
=
CallingConvention
::
mock_x64
()
.integer_parameter_register
;
integer_register
.append
(
&
mut
none_cconv_register
);
let
calling_conventions
:
BTreeMap
<
String
,
CallingConvention
>
=
BTreeMap
::
from
([(
"__stdcall"
.to_string
(),
CallingConvention
::
mock_x64
())]);
Project
{
program
:
Term
{
tid
:
Tid
::
new
(
"program_tid"
),
term
:
Program
::
mock_x64
(),
},
cpu_architecture
:
"x86_64"
.to_string
(),
stack_pointer_register
:
variable!
(
"RSP:8"
),
calling_conventions
,
register_set
:
integer_register
.iter
()
.cloned
()
.collect
(),
datatype_properties
:
DatatypeProperties
::
mock_x64
(),
runtime_memory_image
:
RuntimeMemoryImage
::
mock
(),
}
}
pub
fn
mock_arm32
()
->
Project
{
let
none_cconv_4byte_register
:
Vec
<
Variable
>
=
vec!
[
"r12"
,
"r14"
,
"r15"
]
.into_iter
()
.map
(|
name
|
variable!
(
format!
(
"{name}:4"
)))
.collect
();
let
none_cconv_16byte_register
:
Vec
<
Variable
>
=
vec!
[
"q0"
,
"q1"
,
"q2"
,
"q3"
,
"q8"
,
"q9"
,
"q10"
,
"q11"
,
"q12"
,
"q13"
,
"q14"
,
"q15"
,
]
.into_iter
()
.map
(|
name
|
variable!
(
format!
(
"{name}:16"
)))
.collect
();
let
callee_saved_register
=
CallingConvention
::
mock_arm32
()
.callee_saved_register
;
let
integer_register
=
CallingConvention
::
mock_arm32
()
.integer_parameter_register
.into_iter
()
.chain
(
none_cconv_4byte_register
)
.chain
(
none_cconv_16byte_register
)
.chain
(
callee_saved_register
);
Project
{
program
:
Term
{
tid
:
Tid
::
new
(
"program_tid"
),
term
:
Program
::
mock_arm32
(),
},
cpu_architecture
:
"arm32"
.to_string
(),
stack_pointer_register
:
variable!
(
"sp:4"
),
calling_conventions
:
BTreeMap
::
from
([(
"__stdcall"
.to_string
(),
CallingConvention
::
mock_arm32
(),
)]),
register_set
:
integer_register
.collect
(),
datatype_properties
:
DatatypeProperties
::
mock_arm32
(),
runtime_memory_image
:
RuntimeMemoryImage
::
mock
(),
}
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/term/builder_low_lvl.rs
0 → 100644
View file @
decc1254
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/variable.rs
View file @
decc1254
...
@@ -29,18 +29,3 @@ impl Display for Variable {
...
@@ -29,18 +29,3 @@ impl Display for Variable {
Ok
(())
Ok
(())
}
}
}
}
#[cfg(test)]
mod
tests
{
use
super
::
*
;
impl
Variable
{
pub
fn
mock
(
name
:
impl
ToString
,
size_in_bytes
:
impl
Into
<
ByteSize
>
)
->
Variable
{
Variable
{
name
:
name
.to_string
(),
size
:
size_in_bytes
.into
(),
is_temp
:
false
,
}
}
}
}
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/pcode/subregister_substitution/tests.rs
View file @
decc1254
use
crate
::
intermediate_representation
::
CastOpType
;
use
super
::
*
;
use
super
::
*
;
use
crate
::{
def
,
expr
,
intermediate_representation
::
*
,
variable
};
struct
Setup
<
'a
>
{
struct
Setup
<
'a
>
{
register_map
:
HashMap
<&
'a
String
,
&
'a
RegisterProperties
>
,
register_map
:
HashMap
<&
'a
String
,
&
'a
RegisterProperties
>
,
...
@@ -61,24 +60,24 @@ impl<'a> Setup<'a> {
...
@@ -61,24 +60,24 @@ impl<'a> Setup<'a> {
},
},
int_sub_expr
:
Expression
::
BinOp
{
int_sub_expr
:
Expression
::
BinOp
{
op
:
BinOpType
::
IntSub
,
op
:
BinOpType
::
IntSub
,
lhs
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"EAX"
,
4
)
)),
lhs
:
Box
::
new
(
expr!
(
"EAX:4"
)),
rhs
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"ECX"
,
4
)
)),
rhs
:
Box
::
new
(
expr!
(
"ECX:4"
)),
},
},
int_sub_subpiece_expr
:
Expression
::
BinOp
{
int_sub_subpiece_expr
:
Expression
::
BinOp
{
op
:
BinOpType
::
IntSub
,
op
:
BinOpType
::
IntSub
,
lhs
:
Box
::
new
(
Expression
::
Subpiece
{
lhs
:
Box
::
new
(
Expression
::
Subpiece
{
low_byte
:
ByteSize
::
new
(
0
),
low_byte
:
ByteSize
::
new
(
0
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
arg
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"RAX"
,
8
)
)),
arg
:
Box
::
new
(
expr!
(
"RAX:8"
)),
}),
}),
rhs
:
Box
::
new
(
Expression
::
Subpiece
{
rhs
:
Box
::
new
(
Expression
::
Subpiece
{
low_byte
:
ByteSize
::
new
(
0
),
low_byte
:
ByteSize
::
new
(
0
),
size
:
ByteSize
::
new
(
4
),
size
:
ByteSize
::
new
(
4
),
arg
:
Box
::
new
(
Expression
::
Var
(
Variable
::
mock
(
"RCX"
,
8
)
)),
arg
:
Box
::
new
(
expr!
(
"RCX:8"
)),
}),
}),
},
},
eax_variable
:
Expression
::
Var
(
Variable
::
mock
(
"EAX"
,
4
)
),
eax_variable
:
expr!
(
"EAX:4"
),
rax_variable
:
Expression
::
Var
(
Variable
::
mock
(
"RAX"
,
8
)
),
rax_variable
:
expr!
(
"RAX:8"
),
}
}
}
}
}
}
...
@@ -244,58 +243,34 @@ fn piecing_or_zero_extending() {
...
@@ -244,58 +243,34 @@ fn piecing_or_zero_extending() {
register_map
.insert
(
&
setup
.rcx_name
,
&
setup
.rcx_register
);
register_map
.insert
(
&
setup
.rcx_name
,
&
setup
.rcx_register
);
register_map
.insert
(
&
setup
.ah_name
,
&
setup
.ah_register
);
register_map
.insert
(
&
setup
.ah_name
,
&
setup
.ah_register
);
let
eax_assign
=
Term
{
let
eax_assign
=
def!
[
"eax_assign: EAX:4 = 0:4"
];
tid
:
Tid
::
new
(
"eax_assign"
),
let
load_to_eax
=
def!
[
"load_to_eax: EAX:4 := Load from 0:8"
];
term
:
Def
::
Assign
{
let
ah_assign
=
def!
[
"ah_assign: AH:1 = 0:1"
];
var
:
Variable
::
mock
(
"EAX"
,
4
),
value
:
Expression
::
const_from_i32
(
0
),
},
};
let
load_to_eax
=
Term
{
tid
:
Tid
::
new
(
"load_to_eax"
),
term
:
Def
::
Load
{
var
:
Variable
::
mock
(
"EAX"
,
4
),
address
:
Expression
::
const_from_i64
(
0
),
},
};
let
ah_assign
=
Term
{
tid
:
Tid
::
new
(
"ah_assign"
),
term
:
Def
::
Assign
{
var
:
Variable
::
mock
(
"AH"
,
1
),
value
:
Expression
::
Const
(
Bitvector
::
from_i8
(
0
)),
},
};
let
zext_eax_to_rax
=
Term
{
let
zext_eax_to_rax
=
Term
{
tid
:
Tid
::
new
(
"zext_eax_to_rax"
),
tid
:
Tid
::
new
(
"zext_eax_to_rax"
),
term
:
Def
::
Assign
{
term
:
Def
::
Assign
{
var
:
Variable
::
mock
(
"RAX"
,
8
),
var
:
variable!
(
"RAX:8"
),
value
:
Expression
::
cast
(
setup
.eax_variable
.clone
(),
CastOpType
::
IntZExt
),
value
:
Expression
::
cast
(
setup
.eax_variable
.clone
(),
CastOpType
::
IntZExt
),
},
},
};
};
let
zext_ah_to_eax
=
Term
{
let
zext_ah_to_eax
=
Term
{
tid
:
Tid
::
new
(
"zext_ah_to_eax"
),
tid
:
Tid
::
new
(
"zext_ah_to_eax"
),
term
:
Def
::
Assign
{
term
:
Def
::
Assign
{
var
:
Variable
::
mock
(
"EAX"
,
4
),
var
:
variable!
(
"EAX:4"
),
value
:
Expression
::
cast
(
value
:
Expression
::
cast
(
expr!
(
"AH:1"
),
CastOpType
::
IntZExt
),
Expression
::
Var
(
Variable
::
mock
(
"AH"
,
1
)),
CastOpType
::
IntZExt
,
),
},
},
};
};
let
zext_ah_to_rax
=
Term
{
let
zext_ah_to_rax
=
Term
{
tid
:
Tid
::
new
(
"zext_ah_to_rax"
),
tid
:
Tid
::
new
(
"zext_ah_to_rax"
),
term
:
Def
::
Assign
{
term
:
Def
::
Assign
{
var
:
Variable
::
mock
(
"RAX"
,
8
),
var
:
variable!
(
"RAX:8"
),
value
:
Expression
::
cast
(
value
:
Expression
::
cast
(
expr!
(
"AH:1"
),
CastOpType
::
IntZExt
),
Expression
::
Var
(
Variable
::
mock
(
"AH"
,
1
)),
CastOpType
::
IntZExt
,
),
},
},
};
};
let
zext_eax_to_rcx
=
Term
{
let
zext_eax_to_rcx
=
Term
{
tid
:
Tid
::
new
(
"zext_eax_to_rcx"
),
tid
:
Tid
::
new
(
"zext_eax_to_rcx"
),
term
:
Def
::
Assign
{
term
:
Def
::
Assign
{
var
:
Variable
::
mock
(
"RCX"
,
8
),
var
:
variable!
(
"RCX:8"
),
value
:
Expression
::
cast
(
setup
.eax_variable
.clone
(),
CastOpType
::
IntZExt
),
value
:
Expression
::
cast
(
setup
.eax_variable
.clone
(),
CastOpType
::
IntZExt
),
},
},
};
};
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/utils/arguments/tests.rs
View file @
decc1254
use
std
::
collections
::
BTreeSet
;
use
std
::
collections
::
BTreeSet
;
use
crate
::{
use
crate
::{
abstract_domain
::
IntervalDomain
,
expr
,
intermediate_representation
::
*
,
variable
};
abstract_domain
::
IntervalDomain
,
intermediate_representation
::{
Bitvector
,
Tid
},
};
use
super
::
*
;
use
super
::
*
;
fn
mock_pi_state
()
->
PointerInferenceState
{
fn
mock_pi_state
()
->
PointerInferenceState
{
PointerInferenceState
::
new
(
PointerInferenceState
::
new
(
&
variable!
(
"RSP:8"
),
Tid
::
new
(
"func"
),
BTreeSet
::
new
())
&
Variable
::
mock
(
"RSP"
,
8
as
u64
),
Tid
::
new
(
"func"
),
BTreeSet
::
new
(),
)
}
}
#[test]
#[test]
...
@@ -24,20 +17,14 @@ fn test_get_variable_parameters() {
...
@@ -24,20 +17,14 @@ fn test_get_variable_parameters() {
format_string_index_map
.insert
(
"sprintf"
.to_string
(),
1
);
format_string_index_map
.insert
(
"sprintf"
.to_string
(),
1
);
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"5000"
)
.unwrap
();
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"5000"
)
.unwrap
();
pi_state
.set_register
(
pi_state
.set_register
(
&
Variable
::
mock
(
"RSI"
,
8
as
u64
),
&
variable!
(
"RSI:8"
),
IntervalDomain
::
new
(
global_address
.clone
(),
global_address
)
.into
(),
IntervalDomain
::
new
(
global_address
.clone
(),
global_address
)
.into
(),
);
);
let
project
=
Project
::
mock_x64
();
let
project
=
Project
::
mock_x64
();
let
mut
output
:
Vec
<
Arg
>
=
Vec
::
new
();
let
mut
output
:
Vec
<
Arg
>
=
Vec
::
new
();
output
.push
(
Arg
::
from_var
(
output
.push
(
Arg
::
from_var
(
variable!
(
"RDX:8"
),
Some
(
Datatype
::
Char
)));
Variable
::
mock
(
"RDX"
,
8
),
output
.push
(
Arg
::
from_var
(
variable!
(
"RCX:8"
),
Some
(
Datatype
::
Integer
)));
Some
(
Datatype
::
Char
),
));
output
.push
(
Arg
::
from_var
(
Variable
::
mock
(
"RCX"
,
8
),
Some
(
Datatype
::
Integer
),
));
assert_eq!
(
assert_eq!
(
output
,
output
,
...
@@ -50,14 +37,11 @@ fn test_get_variable_parameters() {
...
@@ -50,14 +37,11 @@ fn test_get_variable_parameters() {
.unwrap
()
.unwrap
()
);
);
output
=
vec!
[
Arg
::
from_var
(
output
=
vec!
[
Arg
::
from_var
(
variable!
(
"RDX:8"
),
Some
(
Datatype
::
Pointer
))];
Variable
::
mock
(
"RDX"
,
8
),
Some
(
Datatype
::
Pointer
),
)];
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"500c"
)
.unwrap
();
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"500c"
)
.unwrap
();
pi_state
.set_register
(
pi_state
.set_register
(
&
Variable
::
mock
(
"RSI"
,
8
as
u64
),
&
variable!
(
"RSI:8"
),
IntervalDomain
::
new
(
global_address
.clone
(),
global_address
)
.into
(),
IntervalDomain
::
new
(
global_address
.clone
(),
global_address
)
.into
(),
);
);
...
@@ -81,7 +65,7 @@ fn test_get_input_format_string() {
...
@@ -81,7 +65,7 @@ fn test_get_input_format_string() {
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"3002"
)
.unwrap
();
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"3002"
)
.unwrap
();
pi_state
.set_register
(
pi_state
.set_register
(
&
Variable
::
mock
(
"RSI"
,
8
as
u64
),
&
variable!
(
"RSI:8"
),
IntervalDomain
::
new
(
global_address
.clone
(),
global_address
)
.into
(),
IntervalDomain
::
new
(
global_address
.clone
(),
global_address
)
.into
(),
);
);
...
@@ -199,19 +183,15 @@ fn test_calculate_parameter_locations() {
...
@@ -199,19 +183,15 @@ fn test_calculate_parameter_locations() {
let
mut
expected_args
=
vec!
[
let
mut
expected_args
=
vec!
[
Arg
::
Register
{
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"RDX"
,
ByteSize
::
new
(
8
))
),
expr
:
expr!
(
"RDX:8"
),
data_type
:
Some
(
Datatype
::
Integer
),
data_type
:
Some
(
Datatype
::
Integer
),
},
},
Arg
::
Register
{
Arg
::
Register
{
expr
:
Expression
::
subpiece
(
expr
:
Expression
::
subpiece
(
expr!
(
"ZMM0:64"
),
ByteSize
::
new
(
0
),
ByteSize
::
new
(
8
)),
Expression
::
Var
(
Variable
::
mock
(
"ZMM0"
,
64
)),
ByteSize
::
new
(
0
),
ByteSize
::
new
(
8
),
),
data_type
:
Some
(
Datatype
::
Double
),
data_type
:
Some
(
Datatype
::
Double
),
},
},
Arg
::
Register
{
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"RCX"
,
ByteSize
::
new
(
8
))
),
expr
:
expr!
(
"RCX:8"
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
},
},
];
];
...
@@ -227,15 +207,15 @@ fn test_calculate_parameter_locations() {
...
@@ -227,15 +207,15 @@ fn test_calculate_parameter_locations() {
parameters
.push
((
"s"
.to_string
()
.into
(),
ByteSize
::
new
(
8
)));
parameters
.push
((
"s"
.to_string
()
.into
(),
ByteSize
::
new
(
8
)));
expected_args
.push
(
Arg
::
Register
{
expected_args
.push
(
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"R8"
,
ByteSize
::
new
(
8
))
),
expr
:
expr!
(
"R8:8"
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
});
});
expected_args
.push
(
Arg
::
Register
{
expected_args
.push
(
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"R9"
,
ByteSize
::
new
(
8
))
),
expr
:
expr!
(
"R9:8"
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
});
});
expected_args
.push
(
Arg
::
Stack
{
expected_args
.push
(
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"RSP"
,
8
))
.plus_const
(
8
),
address
:
expr!
(
"RSP:8 + 8:8"
),
size
:
ByteSize
::
new
(
8
),
size
:
ByteSize
::
new
(
8
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
});
});
...
@@ -251,15 +231,10 @@ fn test_calculate_parameter_locations() {
...
@@ -251,15 +231,10 @@ fn test_calculate_parameter_locations() {
fn
test_create_stack_arg
()
{
fn
test_create_stack_arg
()
{
assert_eq!
(
assert_eq!
(
Arg
::
Stack
{
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"RSP"
,
8
))
.plus_const
(
8
),
address
:
expr!
(
"RSP:8 + 8:8"
),
size
:
ByteSize
::
new
(
8
),
size
:
ByteSize
::
new
(
8
),
data_type
:
Some
(
Datatype
::
Pointer
),
data_type
:
Some
(
Datatype
::
Pointer
),
},
},
create_stack_arg
(
create_stack_arg
(
ByteSize
::
new
(
8
),
8
,
Datatype
::
Pointer
,
&
variable!
(
"RSP:8"
)),
ByteSize
::
new
(
8
),
8
,
Datatype
::
Pointer
,
&
Variable
::
mock
(
"RSP"
,
8
)
),
)
)
}
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment