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
29b2e1a0
Unverified
Commit
29b2e1a0
authored
Jul 06, 2021
by
Melvin Klimke
Committed by
GitHub
Jul 06, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add optional data type param to arg (#198)
parent
094e9643
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
109 additions
and
34 deletions
+109
-34
tests.rs
...ecker_lib/src/analysis/pointer_inference/context/tests.rs
+4
-1
access_handling.rs
...b/src/analysis/pointer_inference/state/access_handling.rs
+2
-2
mod.rs
...e_checker_lib/src/analysis/pointer_inference/state/mod.rs
+2
-2
tests.rs
...checker_lib/src/analysis/pointer_inference/state/tests.rs
+1
-0
context.rs
src/cwe_checker_lib/src/checkers/cwe_476/context.rs
+3
-3
state.rs
src/cwe_checker_lib/src/checkers/cwe_476/state.rs
+7
-3
parameter_detection.rs
...er_lib/src/checkers/cwe_78/context/parameter_detection.rs
+5
-3
tests.rs
.../src/checkers/cwe_78/context/parameter_detection/tests.rs
+11
-2
tests.rs
src/cwe_checker_lib/src/checkers/cwe_78/context/tests.rs
+4
-1
mod.rs
src/cwe_checker_lib/src/checkers/cwe_78/state/mod.rs
+2
-2
tests.rs
src/cwe_checker_lib/src/checkers/cwe_78/state/tests.rs
+4
-1
mod.rs
src/cwe_checker_lib/src/intermediate_representation/mod.rs
+23
-0
term.rs
src/cwe_checker_lib/src/intermediate_representation/term.rs
+14
-4
term.rs
src/cwe_checker_lib/src/pcode/term.rs
+5
-1
arguments.rs
src/cwe_checker_lib/src/utils/arguments.rs
+9
-5
tests.rs
src/cwe_checker_lib/src/utils/arguments/tests.rs
+13
-4
No files found.
src/cwe_checker_lib/src/analysis/pointer_inference/context/tests.rs
View file @
29b2e1a0
...
...
@@ -15,7 +15,10 @@ fn new_id(time: &str, reg_name: &str) -> AbstractIdentifier {
}
fn
mock_extern_symbol
(
name
:
&
str
)
->
ExternSymbol
{
let
arg
=
Arg
::
Register
(
register
(
"RDX"
));
let
arg
=
Arg
::
Register
{
var
:
register
(
"RDX"
),
data_type
:
None
,
};
ExternSymbol
{
tid
:
Tid
::
new
(
"extern_"
.to_string
()
+
name
),
addresses
:
vec!
[],
...
...
src/cwe_checker_lib/src/analysis/pointer_inference/state/access_handling.rs
View file @
29b2e1a0
...
...
@@ -238,8 +238,8 @@ impl State {
global_memory
:
&
RuntimeMemoryImage
,
)
->
Result
<
Data
,
Error
>
{
match
parameter
{
Arg
::
Register
(
var
)
=>
Ok
(
self
.eval
(
&
Expression
::
Var
(
var
.clone
()))),
Arg
::
Stack
{
offset
,
size
}
=>
self
.load_value
(
Arg
::
Register
{
var
,
..
}
=>
Ok
(
self
.eval
(
&
Expression
::
Var
(
var
.clone
()))),
Arg
::
Stack
{
offset
,
size
,
..
}
=>
self
.load_value
(
&
Expression
::
Var
(
stack_pointer
.clone
())
.plus_const
(
*
offset
),
*
size
,
global_memory
,
...
...
src/cwe_checker_lib/src/analysis/pointer_inference/state/mod.rs
View file @
29b2e1a0
...
...
@@ -95,8 +95,8 @@ impl State {
let
mut
result_log
=
Ok
(());
for
arg
in
&
extern_call
.parameters
{
match
arg
{
Arg
::
Register
(
_
)
=>
(),
Arg
::
Stack
{
offset
,
size
}
=>
{
Arg
::
Register
{
..
}
=>
(),
Arg
::
Stack
{
offset
,
size
,
..
}
=>
{
let
data_top
=
Data
::
new_top
(
*
size
);
let
location_expression
=
Expression
::
Var
(
stack_pointer_register
.clone
())
.plus_const
(
*
offset
);
...
...
src/cwe_checker_lib/src/analysis/pointer_inference/state/tests.rs
View file @
29b2e1a0
...
...
@@ -290,6 +290,7 @@ fn clear_parameters_on_the_stack_on_extern_calls() {
let
stack_param
=
Arg
::
Stack
{
offset
:
8
,
size
:
ByteSize
::
new
(
8
),
data_type
:
None
,
};
let
extern_symbol
=
ExternSymbol
{
tid
:
Tid
::
new
(
"symbol"
),
...
...
src/cwe_checker_lib/src/checkers/cwe_476/context.rs
View file @
29b2e1a0
...
...
@@ -184,7 +184,7 @@ impl<'a> Context<'a> {
)
->
bool
{
// First check for taint directly in parameter registers (we don't need a pointer inference state for that)
for
parameter
in
extern_symbol
.parameters
.iter
()
{
if
let
Arg
::
Register
(
var
)
=
parameter
{
if
let
Arg
::
Register
{
var
,
..
}
=
parameter
{
if
state
.eval
(
&
Expression
::
Var
(
var
.clone
()))
.is_tainted
()
{
return
true
;
}
...
...
@@ -196,13 +196,13 @@ impl<'a> Context<'a> {
// Check stack parameters and collect referenced memory object that need to be checked for taint.
for
parameter
in
extern_symbol
.parameters
.iter
()
{
match
parameter
{
Arg
::
Register
(
var
)
=>
{
Arg
::
Register
{
var
,
..
}
=>
{
let
data
=
pi_state
.eval
(
&
Expression
::
Var
(
var
.clone
()));
if
state
.check_if_address_points_to_taint
(
data
,
pi_state
)
{
return
true
;
}
}
Arg
::
Stack
{
offset
,
size
}
=>
{
Arg
::
Stack
{
offset
,
size
,
..
}
=>
{
let
stack_address
=
pi_state
.eval
(
&
Expression
::
Var
(
self
.project.stack_pointer_register
.clone
())
.plus_const
(
*
offset
),
...
...
src/cwe_checker_lib/src/checkers/cwe_476/state.rs
View file @
29b2e1a0
...
...
@@ -92,12 +92,12 @@ impl State {
};
for
return_arg
in
taint_source
.return_values
.iter
()
{
match
return_arg
{
Arg
::
Register
(
var
)
=>
{
Arg
::
Register
{
var
,
..
}
=>
{
state
.register_taint
.insert
(
var
.clone
(),
Taint
::
Tainted
(
var
.size
));
}
Arg
::
Stack
{
offset
,
size
}
=>
{
Arg
::
Stack
{
offset
,
size
,
..
}
=>
{
if
let
Some
(
pi_state
)
=
pi_state
{
let
address_exp
=
Expression
::
Var
(
stack_pointer_register
.clone
())
.plus_const
(
*
offset
);
...
...
@@ -395,10 +395,14 @@ mod tests {
}
pub
fn
mock_with_pi_state
()
->
(
State
,
PointerInferenceState
)
{
let
arg1
=
Arg
::
Register
(
register
(
"RAX"
));
let
arg1
=
Arg
::
Register
{
var
:
register
(
"RAX"
),
data_type
:
None
,
};
let
arg2
=
Arg
::
Stack
{
offset
:
0
,
size
:
ByteSize
::
new
(
8
),
data_type
:
None
,
};
let
pi_state
=
PointerInferenceState
::
new
(
&
register
(
"RSP"
),
Tid
::
new
(
"func"
));
let
symbol
=
ExternSymbol
{
...
...
src/cwe_checker_lib/src/checkers/cwe_78/context/parameter_detection.rs
View file @
29b2e1a0
...
...
@@ -74,7 +74,7 @@ impl<'a> Context<'a> {
.pointer_inference_results
.get_node_value
(
call_source_node
)
{
if
let
Ok
(
parameters
)
=
arguments
::
get_variable_
number_
parameters
(
if
let
Ok
(
parameters
)
=
arguments
::
get_variable_parameters
(
self
.project
,
pi_state
,
user_input_symbol
,
...
...
@@ -228,7 +228,7 @@ impl<'a> Context<'a> {
if
self
.is_relevant_string_function_call
(
string_symbol
,
pi_state
,
&
mut
new_state
)
{
let
mut
parameters
=
string_symbol
.parameters
.clone
();
if
string_symbol
.has_var_args
{
if
let
Ok
(
args
)
=
arguments
::
get_variable_
number_
parameters
(
if
let
Ok
(
args
)
=
arguments
::
get_variable_parameters
(
self
.project
,
pi_state
,
string_symbol
,
...
...
@@ -272,7 +272,9 @@ impl<'a> Context<'a> {
)
{
for
parameter
in
parameters
.iter
()
{
match
parameter
{
Arg
::
Register
(
var
)
=>
state
.set_register_taint
(
var
,
Taint
::
Tainted
(
var
.size
)),
Arg
::
Register
{
var
,
..
}
=>
{
state
.set_register_taint
(
var
,
Taint
::
Tainted
(
var
.size
))
}
Arg
::
Stack
{
size
,
..
}
=>
{
if
let
Ok
(
address
)
=
pi_state
.eval_parameter_arg
(
parameter
,
...
...
src/cwe_checker_lib/src/checkers/cwe_78/context/parameter_detection/tests.rs
View file @
29b2e1a0
...
...
@@ -246,6 +246,7 @@ fn processing_scanf() {
let
string_arg
=
Arg
::
Stack
{
offset
:
0
,
size
:
ByteSize
::
new
(
8
),
data_type
:
None
,
};
let
(
cwe_sender
,
cwe_receiver
)
=
crossbeam_channel
::
unbounded
::
<
CweWarning
>
();
...
...
@@ -307,6 +308,7 @@ fn processing_sscanf() {
let
string_arg
=
Arg
::
Stack
{
offset
:
0
,
size
:
ByteSize
::
new
(
8
),
data_type
:
None
,
};
let
mem_image
=
RuntimeMemoryImage
::
mock
();
...
...
@@ -352,7 +354,10 @@ fn processing_sscanf() {
&
mut
setup
.state
,
&
setup
.pi_state
,
vec!
[
string_arg
],
&
Arg
::
Register
(
rdi_reg
),
&
Arg
::
Register
{
var
:
rdi_reg
,
data_type
:
None
,
},
);
assert
!
(
setup
...
...
@@ -368,10 +373,14 @@ fn tainting_function_arguments() {
let
mut
setup
=
Setup
::
new
();
let
rdi_reg
=
Variable
::
mock
(
"RDI"
,
8
);
let
args
=
vec!
[
Arg
::
Register
(
rdi_reg
.clone
()),
Arg
::
Register
{
var
:
rdi_reg
.clone
(),
data_type
:
None
,
},
Arg
::
Stack
{
offset
:
24
,
size
:
ByteSize
::
from
(
8
),
data_type
:
None
,
},
];
...
...
src/cwe_checker_lib/src/checkers/cwe_78/context/tests.rs
View file @
29b2e1a0
...
...
@@ -284,7 +284,10 @@ fn first_param_pointing_to_memory_taint() {
&
mem_image
,
);
let
arg
=
Arg
::
Register
(
rdi_reg
);
let
arg
=
Arg
::
Register
{
var
:
rdi_reg
,
data_type
:
None
,
};
assert_eq!
(
context
.first_param_points_to_memory_taint
(
&
setup
.pi_state
,
&
mut
setup
.state
,
&
arg
),
true
...
...
src/cwe_checker_lib/src/checkers/cwe_78/state/mod.rs
View file @
29b2e1a0
...
...
@@ -108,12 +108,12 @@ impl State {
};
for
parameter
in
taint_source
.parameters
.iter
()
{
match
parameter
{
Arg
::
Register
(
var
)
=>
{
Arg
::
Register
{
var
,
..
}
=>
{
state
.register_taint
.insert
(
var
.clone
(),
Taint
::
Tainted
(
var
.size
));
}
Arg
::
Stack
{
offset
,
size
}
=>
{
Arg
::
Stack
{
offset
,
size
,
..
}
=>
{
if
let
Some
(
pi_state
)
=
pi_state
{
let
address_exp
=
Expression
::
Var
(
stack_pointer_register
.clone
())
.plus_const
(
*
offset
);
...
...
src/cwe_checker_lib/src/checkers/cwe_78/state/tests.rs
View file @
29b2e1a0
...
...
@@ -25,7 +25,10 @@ fn bv(value: i64) -> ValueDomain {
impl
State
{
pub
fn
mock_with_pi_state
()
->
(
State
,
PointerInferenceState
)
{
let
arg
=
Arg
::
Register
(
Variable
::
mock
(
"RAX"
,
8
as
u64
));
let
arg
=
Arg
::
Register
{
var
:
Variable
::
mock
(
"RAX"
,
8
as
u64
),
data_type
:
None
,
};
let
pi_state
=
PointerInferenceState
::
new
(
&
Variable
::
mock
(
"RSP"
,
8
as
u64
),
Tid
::
new
(
"func"
));
let
symbol
=
extern_symbol
(
"system"
,
vec!
[
arg
],
false
);
...
...
src/cwe_checker_lib/src/intermediate_representation/mod.rs
View file @
29b2e1a0
...
...
@@ -110,6 +110,29 @@ pub struct DatatypeProperties {
pub
short_size
:
ByteSize
,
}
/// C/C++ data types.
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
enum
Datatype
{
/// C char data type
Char
,
/// C double data type
Double
,
/// C float data type
Float
,
/// C integer data type
Integer
,
/// C long double data type
LongDouble
,
/// C long long data type
LongLong
,
/// C long data type
Long
,
/// C pointer data type
Pointer
,
/// C short data type
Short
,
}
#[cfg(test)]
mod
tests
{
use
apint
::
BitWidth
;
...
...
src/cwe_checker_lib/src/intermediate_representation/term.rs
View file @
29b2e1a0
use
super
::{
ByteSize
,
CastOpType
,
DatatypeProperties
,
Expression
,
Variable
};
use
super
::{
ByteSize
,
CastOpType
,
Datatype
,
Datatype
Properties
,
Expression
,
Variable
};
use
crate
::
prelude
::
*
;
use
crate
::
utils
::
log
::
LogMessage
;
use
std
::
collections
::
HashSet
;
...
...
@@ -455,7 +455,12 @@ pub struct Sub {
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
enum
Arg
{
/// The argument is passed in the given register
Register
(
Variable
),
Register
{
/// The variable object representing the register.
var
:
Variable
,
/// An optional data type indicator.
data_type
:
Option
<
Datatype
>
,
},
/// The argument is passed on the stack.
/// It is positioned at the given offset (in bytes) relative to the stack pointer on function entry
/// and has the given size.
...
...
@@ -465,6 +470,8 @@ pub enum Arg {
offset
:
i64
,
/// The size in bytes of the argument.
size
:
ByteSize
,
/// An optional data type indicator.
data_type
:
Option
<
Datatype
>
,
},
}
...
...
@@ -497,7 +504,7 @@ impl ExternSymbol {
pub
fn
get_unique_return_register
(
&
self
)
->
Result
<&
Variable
,
Error
>
{
if
self
.return_values
.len
()
==
1
{
match
self
.return_values
[
0
]
{
Arg
::
Register
(
ref
var
)
=>
Ok
(
var
),
Arg
::
Register
{
ref
var
,
..
}
=>
Ok
(
var
),
Arg
::
Stack
{
..
}
=>
Err
(
anyhow!
(
"Return value is passed on the stack"
)),
}
}
else
{
...
...
@@ -814,7 +821,10 @@ mod tests {
impl
Arg
{
pub
fn
mock_register
(
name
:
impl
ToString
,
size_in_bytes
:
impl
Into
<
ByteSize
>
)
->
Arg
{
Arg
::
Register
(
Variable
::
mock
(
name
.to_string
(),
size_in_bytes
))
Arg
::
Register
{
var
:
Variable
::
mock
(
name
.to_string
(),
size_in_bytes
),
data_type
:
None
,
}
}
}
...
...
src/cwe_checker_lib/src/pcode/term.rs
View file @
29b2e1a0
...
...
@@ -524,7 +524,10 @@ impl ExternSymbol {
}
for
arg
in
symbol
.arguments
.iter
()
{
let
ir_arg
=
if
let
Some
(
var
)
=
arg
.var
.clone
()
{
IrArg
::
Register
(
var
.into
())
IrArg
::
Register
{
var
:
var
.into
(),
data_type
:
None
,
}
}
else
if
let
Some
(
expr
)
=
arg
.location
.clone
()
{
if
expr
.mnemonic
==
ExpressionType
::
LOAD
{
IrArg
::
Stack
{
...
...
@@ -539,6 +542,7 @@ impl ExternSymbol {
)
.unwrap
(),
size
:
expr
.input0
.unwrap
()
.size
,
data_type
:
None
,
}
}
else
{
panic!
()
...
...
src/cwe_checker_lib/src/utils/arguments.rs
View file @
29b2e1a0
...
...
@@ -2,7 +2,7 @@
use
std
::
collections
::
HashMap
;
use
crate
::
prelude
::
*
;
use
crate
::
{
intermediate_representation
::
Datatype
,
prelude
::
*
}
;
use
regex
::
Regex
;
...
...
@@ -22,7 +22,7 @@ pub fn get_return_registers_from_symbol(symbol: &ExternSymbol) -> Vec<String> {
.return_values
.iter
()
.filter_map
(|
ret
|
match
ret
{
Arg
::
Register
(
var
)
=>
Some
(
var
.name
.clone
()),
Arg
::
Register
{
var
,
..
}
=>
Some
(
var
.name
.clone
()),
_
=>
None
,
})
.collect
::
<
Vec
<
String
>>
()
...
...
@@ -117,7 +117,7 @@ pub fn map_format_specifier_to_bytesize(
}
/// Returns an argument vector of detected variable parameters if they are of type string.
pub
fn
get_variable_
number_
parameters
(
pub
fn
get_variable_parameters
(
project
:
&
Project
,
pi_state
:
&
PointerInferenceState
,
extern_symbol
:
&
ExternSymbol
,
...
...
@@ -209,16 +209,20 @@ pub fn create_string_stack_arg(size: ByteSize, stack_offset: i64) -> Arg {
Arg
::
Stack
{
offset
:
stack_offset
,
size
,
data_type
:
Some
(
Datatype
::
Pointer
),
}
}
/// Creates a string register parameter given a register name.
pub
fn
create_string_register_arg
(
size
:
ByteSize
,
register_name
:
String
)
->
Arg
{
Arg
::
Register
(
Variable
{
Arg
::
Register
{
var
:
Variable
{
name
:
register_name
,
size
,
is_temp
:
false
,
})
},
data_type
:
Some
(
Datatype
::
Pointer
),
}
}
/// Checks whether the format specifier is of type int.
...
...
src/cwe_checker_lib/src/utils/arguments/tests.rs
View file @
29b2e1a0
...
...
@@ -36,7 +36,7 @@ fn test_get_variable_number_parameters() {
let
mut
output
:
Vec
<
Arg
>
=
Vec
::
new
();
assert_eq!
(
output
,
get_variable_
number_
parameters
(
get_variable_parameters
(
&
project
,
&
pi_state
,
&
sprintf_symbol
,
...
...
@@ -49,6 +49,7 @@ fn test_get_variable_number_parameters() {
output
.push
(
Arg
::
Stack
{
offset
:
0
,
size
:
ByteSize
::
new
(
8
),
data_type
:
Some
(
Datatype
::
Pointer
),
});
let
global_address
=
Bitvector
::
from_str_radix
(
16
,
"500c"
)
.unwrap
();
...
...
@@ -59,7 +60,7 @@ fn test_get_variable_number_parameters() {
assert_eq!
(
output
,
get_variable_
number_
parameters
(
get_variable_parameters
(
&
project
,
&
pi_state
,
&
sprintf_symbol
,
...
...
@@ -187,7 +188,10 @@ fn test_calculate_parameter_locations() {
parameters
.push
((
"f"
.to_string
(),
ByteSize
::
new
(
8
)));
parameters
.push
((
"s"
.to_string
(),
ByteSize
::
new
(
4
)));
let
mut
expected_args
=
vec!
[
Arg
::
Register
(
Variable
::
mock
(
"R9"
,
ByteSize
::
new
(
8
)))];
let
mut
expected_args
=
vec!
[
Arg
::
Register
{
var
:
Variable
::
mock
(
"R9"
,
ByteSize
::
new
(
8
)),
data_type
:
Some
(
Datatype
::
Pointer
),
}];
// Test Case 1: The string parameter is still written in the R9 register since 'f' is contained in the float register.
assert_eq!
(
...
...
@@ -199,6 +203,7 @@ fn test_calculate_parameter_locations() {
expected_args
.push
(
Arg
::
Stack
{
offset
:
0
,
size
:
ByteSize
::
new
(
4
),
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.
...
...
@@ -214,6 +219,7 @@ fn test_create_string_stack_arg() {
Arg
::
Stack
{
size
:
ByteSize
::
new
(
8
),
offset
:
8
,
data_type
:
Some
(
Datatype
::
Pointer
),
},
create_string_stack_arg
(
ByteSize
::
new
(
8
),
8
),
)
...
...
@@ -222,7 +228,10 @@ fn test_create_string_stack_arg() {
#[test]
fn
test_create_string_register_arg
()
{
assert_eq!
(
Arg
::
Register
(
Variable
::
mock
(
"R9"
,
ByteSize
::
new
(
8
))),
Arg
::
Register
{
var
:
Variable
::
mock
(
"R9"
,
ByteSize
::
new
(
8
)),
data_type
:
Some
(
Datatype
::
Pointer
),
},
create_string_register_arg
(
ByteSize
::
new
(
8
),
"R9"
.to_string
()),
);
}
...
...
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