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
0662acda
Unverified
Commit
0662acda
authored
Feb 07, 2022
by
van den Bosch
Committed by
GitHub
Feb 07, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Test reorganization (#285)
parent
19eac24e
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
139 additions
and
74 deletions
+139
-74
tests.rs
...cker_lib/src/analysis/function_signature/context/tests.rs
+3
-3
tests.rs
...hecker_lib/src/analysis/function_signature/state/tests.rs
+1
-1
tests.rs
...checker_lib/src/analysis/pointer_inference/state/tests.rs
+1
-1
cwe_134.rs
src/cwe_checker_lib/src/checkers/cwe_134.rs
+1
-1
sub.rs
src/cwe_checker_lib/src/intermediate_representation/sub.rs
+93
-31
tests.rs
src/cwe_checker_lib/src/utils/arguments/tests.rs
+39
-36
binary.rs
src/cwe_checker_lib/src/utils/binary.rs
+1
-1
No files found.
src/cwe_checker_lib/src/analysis/function_signature/context/tests.rs
View file @
0662acda
...
...
@@ -4,7 +4,7 @@ use std::collections::HashSet;
#[test]
fn
test_compute_return_values_of_call
()
{
let
project
=
Project
::
mock_empty
();
let
cconv
=
CallingConvention
::
mock
();
let
cconv
=
CallingConvention
::
mock
_x64
();
let
graph
=
crate
::
analysis
::
graph
::
get_program_cfg
(
&
project
.program
,
HashSet
::
new
());
let
context
=
Context
::
new
(
&
project
,
&
graph
);
...
...
@@ -25,7 +25,7 @@ fn test_compute_return_values_of_call() {
AbstractIdentifier
::
new_from_var
(
Tid
::
new
(
"call_tid"
),
&
Variable
::
mock
(
"RAX"
,
8
)),
Bitvector
::
from_i64
(
0
)
.into
(),
);
assert_eq!
(
return_values
.iter
()
.len
(),
1
);
assert_eq!
(
return_values
.iter
()
.len
(),
3
);
assert_eq!
(
return_values
[
0
],
(
&
Variable
::
mock
(
"RAX"
,
8
),
expected_val
));
// Test returning a known value.
let
param_ref
=
DataDomain
::
from_target
(
...
...
@@ -39,6 +39,6 @@ fn test_compute_return_values_of_call() {
);
let
return_values
=
context
.compute_return_values_of_call
(
&
mut
caller_state
,
&
callee_state
,
&
cconv
,
&
call
);
assert_eq!
(
return_values
.iter
()
.len
(),
1
);
assert_eq!
(
return_values
.iter
()
.len
(),
3
);
assert_eq!
(
return_values
[
0
],
(
&
Variable
::
mock
(
"RAX"
,
8
),
expected_val
));
}
src/cwe_checker_lib/src/analysis/function_signature/state/tests.rs
View file @
0662acda
...
...
@@ -15,7 +15,7 @@ impl State {
State
::
new
(
&
Tid
::
new
(
tid_name
),
&
Variable
::
mock
(
"RSP"
,
8
),
&
CallingConvention
::
mock
(),
&
CallingConvention
::
mock
_x64
(),
)
}
}
...
...
src/cwe_checker_lib/src/analysis/pointer_inference/state/tests.rs
View file @
0662acda
...
...
@@ -338,7 +338,7 @@ fn merge_callee_stack_to_caller_stack() {
fn
remove_and_restore_callee_saved_register
()
{
let
mut
state
=
State
::
new
(
&
register
(
"RSP"
),
Tid
::
new
(
"func_tid"
));
let
value
:
Data
=
Bitvector
::
from_u64
(
42
)
.into
();
let
cconv
=
CallingConvention
::
mock
();
let
cconv
=
CallingConvention
::
mock
_x64
();
state
.set_register
(
&
register
(
"RBP"
),
value
.clone
());
state
.set_register
(
&
register
(
"RAX"
),
value
.clone
());
...
...
src/cwe_checker_lib/src/checkers/cwe_134.rs
View file @
0662acda
...
...
@@ -211,7 +211,7 @@ pub mod tests {
project
.program.term.entry_points
.insert
(
Tid
::
new
(
"func"
));
project
.calling_conventions
.insert
(
"__stdcall"
.to_string
(),
CallingConvention
::
mock
());
.insert
(
"__stdcall"
.to_string
(),
CallingConvention
::
mock
_x64
());
project
}
...
...
src/cwe_checker_lib/src/intermediate_representation/sub.rs
View file @
0662acda
...
...
@@ -213,45 +213,108 @@ mod tests {
}
}
}
/// 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
{
pub
fn
mock
()
->
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
)],
float_parameter_register
:
vec!
[
Expression
::
Var
(
Variable
::
mock
(
"XMMO"
,
16
))],
integer_return_register
:
vec!
[
Variable
::
mock
(
"RAX"
,
8
)],
float_return_register
:
vec!
[],
callee_saved_register
:
vec!
[
Variable
::
mock
(
"RBP"
,
8
)],
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
)],
float_parameter_register
:
vec!
[
Expression
::
Var
(
Variable
::
mock
(
"d0"
,
8
))],
integer_return_register
:
vec!
[
Variable
::
mock
(
"r0"
,
4
)],
float_return_register
:
vec!
[],
callee_saved_register
:
vec!
[
Variable
::
mock
(
"r4"
,
4
)],
}
}
pub
fn
mock_with_parameter_registers
(
integer_parameter_register
:
Vec
<
Variable
>
,
float_parameter_register
:
Vec
<
Variable
>
,
)
->
CallingConvention
{
let
float_parameter_register
=
float_parameter_register
.into_iter
()
.map
(
Expression
::
Var
)
.collect
();
CallingConvention
{
name
:
"__stdcall"
.to_string
(),
// so that the mock is useable as standard calling convention in tests
integer_parameter_register
,
float_parameter_register
,
integer_return_register
:
vec!
[
Variable
::
mock
(
"RAX"
,
8
)],
float_return_register
:
vec!
[],
callee_saved_register
:
vec!
[
Variable
::
mock
(
"RBP"
,
8
)],
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
),
],
}
}
}
...
...
@@ -301,7 +364,6 @@ mod tests {
}
pub
fn
mock_arm32
()
->
ExternSymbol
{
// There is also the mock_standard_arm32() method. Only on of the two should exist!
ExternSymbol
{
tid
:
Tid
::
new
(
"mock_symbol"
),
addresses
:
vec!
[
"UNKNOWN"
.to_string
()],
...
...
src/cwe_checker_lib/src/utils/arguments/tests.rs
View file @
0662acda
...
...
@@ -9,36 +9,32 @@ fn mock_pi_state() -> PointerInferenceState {
}
#[test]
/// Tests extraction of format string parameters '/dev/sd%c%d' and 'cat %s'.
fn
test_get_variable_parameters
()
{
let
mem_image
=
RuntimeMemoryImage
::
mock
();
let
mut
pi_state
=
mock_pi_state
();
let
sprintf_symbol
=
ExternSymbol
::
mock_string
();
let
mut
format_string_index_map
:
HashMap
<
String
,
usize
>
=
HashMap
::
new
();
format_string_index_map
.insert
(
"sprintf"
.to_string
(),
0
);
format_string_index_map
.insert
(
"sprintf"
.to_string
(),
1
);
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"5000"
)
.unwrap
();
pi_state
.set_register
(
&
Variable
::
mock
(
"R
D
I"
,
8
as
u64
),
&
Variable
::
mock
(
"R
S
I"
,
8
as
u64
),
IntervalDomain
::
new
(
global_address
.clone
(),
global_address
)
.into
(),
);
let
mut
project
=
Project
::
mock_empty
();
let
cconv
=
CallingConvention
::
mock_with_parameter_registers
(
vec!
[
Variable
::
mock
(
"RDI"
,
8
)],
vec!
[
Variable
::
mock
(
"XMM0"
,
16
)],
);
let
cconv
=
CallingConvention
::
mock_x64
();
project
.calling_conventions
=
BTreeMap
::
from_iter
([(
cconv
.name
.clone
(),
cconv
)]);
let
mut
output
:
Vec
<
Arg
>
=
Vec
::
new
();
output
.push
(
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"RSP"
,
8
))
.plus_const
(
8
),
size
:
ByteSize
::
new
(
4
),
data_type
:
Some
(
Datatype
::
Char
),
});
output
.push
(
Arg
::
from_var
(
Variable
::
mock
(
"RDX"
,
8
),
Some
(
Datatype
::
Char
),
));
output
.push
(
Arg
::
from_var
(
Variable
::
mock
(
"RCX"
,
8
),
Some
(
Datatype
::
Integer
),
));
output
.push
(
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"RSP"
,
8
))
.plus_const
(
12
),
size
:
ByteSize
::
new
(
4
),
data_type
:
Some
(
Datatype
::
Integer
),
});
assert_eq!
(
output
,
get_variable_parameters
(
...
...
@@ -51,15 +47,14 @@ fn test_get_variable_parameters() {
.unwrap
()
);
output
=
vec!
[
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"RSP"
,
8
))
.plus_const
(
8
),
size
:
ByteSize
::
new
(
8
),
data_type
:
Some
(
Datatype
::
Pointer
),
}];
output
=
vec!
[
Arg
::
from_var
(
Variable
::
mock
(
"RDX"
,
8
),
Some
(
Datatype
::
Pointer
),
)];
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"500c"
)
.unwrap
();
pi_state
.set_register
(
&
Variable
::
mock
(
"R
D
I"
,
8
as
u64
),
&
Variable
::
mock
(
"R
S
I"
,
8
as
u64
),
IntervalDomain
::
new
(
global_address
.clone
(),
global_address
)
.into
(),
);
...
...
@@ -164,16 +159,9 @@ fn test_parse_format_string_parameters() {
}
#[test]
/// Tests tracking of parameters according to format string
fn
test_calculate_parameter_locations
()
{
let
cconv
=
CallingConvention
::
mock_with_parameter_registers
(
vec!
[
Variable
::
mock
(
"RDI"
,
8
),
Variable
::
mock
(
"RSI"
,
8
),
Variable
::
mock
(
"R8"
,
8
),
Variable
::
mock
(
"R9"
,
8
),
],
vec!
[
Variable
::
mock
(
"XMM0"
,
16
)],
);
let
cconv
=
CallingConvention
::
mock_x64
();
let
format_string_index
:
usize
=
1
;
let
mut
parameters
:
Vec
<
(
Datatype
,
ByteSize
)
>
=
Vec
::
new
();
parameters
.push
((
"d"
.to_string
()
.into
(),
ByteSize
::
new
(
8
)));
...
...
@@ -182,20 +170,24 @@ fn test_calculate_parameter_locations() {
let
mut
expected_args
=
vec!
[
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"R
8
"
,
ByteSize
::
new
(
8
))),
expr
:
Expression
::
Var
(
Variable
::
mock
(
"R
DX
"
,
ByteSize
::
new
(
8
))),
data_type
:
Some
(
Datatype
::
Integer
),
},
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"XMM0"
,
ByteSize
::
new
(
16
))),
expr
:
Expression
::
subpiece
(
Expression
::
Var
(
Variable
::
mock
(
"ZMM0"
,
64
)),
ByteSize
::
new
(
0
),
ByteSize
::
new
(
8
),
),
data_type
:
Some
(
Datatype
::
Double
),
},
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"R
9
"
,
ByteSize
::
new
(
8
))),
expr
:
Expression
::
Var
(
Variable
::
mock
(
"R
CX
"
,
ByteSize
::
new
(
8
))),
data_type
:
Some
(
Datatype
::
Pointer
),
},
];
// Test Case 1: The string parameter is still written in the R
9
register since 'f' is contained in the float register.
// Test Case 1: The string parameter is still written in the R
CX
register since 'f' is contained in the float register.
assert_eq!
(
expected_args
,
calculate_parameter_locations
(
...
...
@@ -208,13 +200,24 @@ fn test_calculate_parameter_locations() {
);
parameters
.push
((
"s"
.to_string
()
.into
(),
ByteSize
::
new
(
8
)));
parameters
.push
((
"s"
.to_string
()
.into
(),
ByteSize
::
new
(
8
)));
parameters
.push
((
"s"
.to_string
()
.into
(),
ByteSize
::
new
(
8
)));
expected_args
.push
(
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"R8"
,
ByteSize
::
new
(
8
))),
data_type
:
Some
(
Datatype
::
Pointer
),
});
expected_args
.push
(
Arg
::
Register
{
expr
:
Expression
::
Var
(
Variable
::
mock
(
"R9"
,
ByteSize
::
new
(
8
))),
data_type
:
Some
(
Datatype
::
Pointer
),
});
expected_args
.push
(
Arg
::
Stack
{
address
:
Expression
::
Var
(
Variable
::
mock
(
"RSP"
,
8
))
.plus_const
(
8
),
size
:
ByteSize
::
new
(
8
),
data_type
:
Some
(
Datatype
::
Pointer
),
});
// Test Case 2:
A second string parameter does not fit into the registers anymore and
is written into the stack.
// Test Case 2:
Three further string parameter does not fit into the registers anymore and one
is written into the stack.
assert_eq!
(
expected_args
,
calculate_parameter_locations
(
...
...
src/cwe_checker_lib/src/utils/binary.rs
View file @
0662acda
...
...
@@ -407,7 +407,7 @@ pub mod tests {
use
super
::
*
;
impl
RuntimeMemoryImage
{
/// Create
a mock runtime memory image for unit test
s.
/// Create
s a mock runtime memory image with: byte series, strings and format string
s.
pub
fn
mock
()
->
RuntimeMemoryImage
{
RuntimeMemoryImage
{
memory_segments
:
vec!
[
...
...
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