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
933a929c
Unverified
Commit
933a929c
authored
3 years ago
by
James Shaker
Committed by
GitHub
3 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed issue #250 by using correct calling convention. (#269)
parent
74976f0d
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
88 additions
and
12 deletions
+88
-12
Makefile
Makefile
+1
-1
tests.rs
...b/src/analysis/backward_interprocedural_fixpoint/tests.rs
+2
-0
mod.rs
...checker_lib/src/analysis/dead_variable_elimination/mod.rs
+1
-0
forward_interprocedural_fixpoint.rs
...cker_lib/src/analysis/forward_interprocedural_fixpoint.rs
+12
-4
context.rs
...we_checker_lib/src/analysis/function_signature/context.rs
+2
-0
graph.rs
src/cwe_checker_lib/src/analysis/graph.rs
+3
-0
tests.rs
...ecker_lib/src/analysis/pointer_inference/context/tests.rs
+6
-1
trait_impls.rs
...lib/src/analysis/pointer_inference/context/trait_impls.rs
+10
-2
trait_impls.rs
...ib/src/analysis/string_abstraction/context/trait_impls.rs
+2
-0
tests.rs
.../analysis/string_abstraction/context/trait_impls/tests.rs
+2
-0
context.rs
src/cwe_checker_lib/src/checkers/cwe_476/context.rs
+8
-1
project.rs
...we_checker_lib/src/intermediate_representation/project.rs
+14
-0
block_duplication_normalization.rs
...representation/project/block_duplication_normalization.rs
+1
-0
sub.rs
src/cwe_checker_lib/src/intermediate_representation/sub.rs
+3
-0
term.rs
src/cwe_checker_lib/src/pcode/term.rs
+4
-0
TermCreator.java
src/ghidra/p_code_extractor/internal/TermCreator.java
+5
-1
Sub.java
src/ghidra/p_code_extractor/term/Sub.java
+10
-0
lib.rs
test/src/lib.rs
+2
-2
No files found.
Makefile
View file @
933a929c
...
...
@@ -21,7 +21,7 @@ test:
echo
"Acceptance test binaries not found. Please see test/artificial_samples/Readme.md for build instructions."
;
\
exit
-1
;
\
fi
cargo
test
--no-fail-fast
-p
acceptance_tests_ghidra
--
--show-output
--ignored
cargo
test
--no-fail-fast
-p
acceptance_tests_ghidra
--
--show-output
--ignored
--test-threads
1
compile_test_files
:
cd test
/artificial_samples
\
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/backward_interprocedural_fixpoint/tests.rs
View file @
933a929c
...
...
@@ -89,6 +89,7 @@ fn mock_program() -> Term<Program> {
term
:
Sub
{
name
:
"sub1"
.to_string
(),
blocks
:
vec!
[
sub1_blk1
,
sub1_blk2
],
calling_convention
:
None
,
},
};
let
cond_jump
=
Jmp
::
CBranch
{
...
...
@@ -124,6 +125,7 @@ fn mock_program() -> Term<Program> {
term
:
Sub
{
name
:
"sub2"
.to_string
(),
blocks
:
vec!
[
sub2_blk1
,
sub2_blk2
],
calling_convention
:
None
,
},
};
let
program
=
Term
{
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/dead_variable_elimination/mod.rs
View file @
933a929c
...
...
@@ -160,6 +160,7 @@ mod tests {
term
:
Sub
{
name
:
"sub"
.to_string
(),
blocks
:
vec!
[
block
],
calling_convention
:
None
,
},
};
let
mut
project
=
Project
::
mock_empty
();
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/forward_interprocedural_fixpoint.rs
View file @
933a929c
...
...
@@ -57,6 +57,7 @@ pub trait Context<'a> {
value
:
&
Self
::
Value
,
call
:
&
Term
<
Jmp
>
,
target
:
&
Node
,
calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
Self
::
Value
>
;
/// Transition function for return instructions.
...
...
@@ -68,6 +69,7 @@ pub trait Context<'a> {
value_before_call
:
Option
<&
Self
::
Value
>
,
call_term
:
&
Term
<
Jmp
>
,
return_term
:
&
Term
<
Jmp
>
,
calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
Self
::
Value
>
;
/// Transition function for calls to functions not contained in the binary.
...
...
@@ -163,7 +165,12 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
Edge
::
CallCombine
(
_
)
=>
Some
(
Self
::
NodeValue
::
Value
(
node_value
.unwrap_value
()
.clone
())),
Edge
::
Call
(
call
)
=>
self
.context
.update_call
(
node_value
.unwrap_value
(),
call
,
&
graph
[
end_node
])
.update_call
(
node_value
.unwrap_value
(),
call
,
&
graph
[
end_node
],
&
graph
[
end_node
]
.get_sub
()
.term.calling_convention
,
)
.map
(
NodeValue
::
Value
),
Edge
::
CrCallStub
=>
Some
(
NodeValue
::
CallFlowCombinator
{
call_stub
:
Some
(
node_value
.unwrap_value
()
.clone
()),
...
...
@@ -179,11 +186,11 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
call_stub
,
interprocedural_flow
,
}
=>
{
let
return_from_block
=
match
graph
.node_weight
(
start_node
)
{
let
(
return_from_block
,
return_from_sub
)
=
match
graph
.node_weight
(
start_node
)
{
Some
(
Node
::
CallReturn
{
call
:
_
,
return_
:
(
return_from_block
,
_
),
})
=>
return_from_block
,
return_
:
(
return_from_block
,
return_from_sub
),
})
=>
(
return_from_block
,
return_from_sub
)
,
_
=>
panic!
(
"Malformed Control flow graph"
),
};
let
return_from_jmp
=
&
return_from_block
.term.jmps
[
0
];
...
...
@@ -193,6 +200,7 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
call_stub
.as_ref
(),
call_term
,
return_from_jmp
,
&
return_from_sub
.term.calling_convention
,
)
.map
(
NodeValue
::
Value
)
}
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/function_signature/context.rs
View file @
933a929c
...
...
@@ -176,6 +176,7 @@ impl<'a> forward_interprocedural_fixpoint::Context<'a> for Context<'a> {
_state
:
&
State
,
_call
:
&
Term
<
Jmp
>
,
_target
:
&
crate
::
analysis
::
graph
::
Node
,
_calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
State
>
{
// No knowledge is transferred from the caller to the callee.
None
...
...
@@ -215,6 +216,7 @@ impl<'a> forward_interprocedural_fixpoint::Context<'a> for Context<'a> {
state_before_call
:
Option
<&
State
>
,
call_term
:
&
Term
<
Jmp
>
,
_return_term
:
&
Term
<
Jmp
>
,
_calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
State
>
{
if
state
.is_none
()
||
state_before_call
.is_none
()
{
return
None
;
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/graph.rs
View file @
933a929c
...
...
@@ -538,6 +538,7 @@ mod tests {
term
:
Sub
{
name
:
"sub1"
.to_string
(),
blocks
:
vec!
[
sub1_blk1
,
sub1_blk2
],
calling_convention
:
None
,
},
};
let
cond_jump
=
Jmp
::
CBranch
{
...
...
@@ -573,6 +574,7 @@ mod tests {
term
:
Sub
{
name
:
"sub2"
.to_string
(),
blocks
:
vec!
[
sub2_blk1
,
sub2_blk2
],
calling_convention
:
None
,
},
};
let
program
=
Term
{
...
...
@@ -617,6 +619,7 @@ mod tests {
term
:
Sub
{
name
:
"sub"
.to_string
(),
blocks
:
vec!
[
blk_term
],
calling_convention
:
None
,
},
};
let
mut
program
=
Program
::
mock_empty
();
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/pointer_inference/context/tests.rs
View file @
933a929c
...
...
@@ -167,11 +167,14 @@ fn context_problem_implementation() {
term
:
Sub
{
name
:
"caller_sub"
.into
(),
blocks
:
vec!
[
target_block
.clone
()],
calling_convention
:
None
,
},
};
let
target_node
=
crate
::
analysis
::
graph
::
Node
::
BlkStart
(
&
target_block
,
&
sub
);
let
call
=
call_term
(
"func"
);
let
mut
callee_state
=
context
.update_call
(
&
state
,
&
call
,
&
target_node
)
.unwrap
();
let
mut
callee_state
=
context
.update_call
(
&
state
,
&
call
,
&
target_node
,
&
None
)
.unwrap
();
assert_eq!
(
callee_state
.stack_id
,
new_id
(
"func"
,
"RSP"
));
assert_eq!
(
callee_state
.caller_stack_ids
.len
(),
1
);
assert_eq!
(
...
...
@@ -208,6 +211,7 @@ fn context_problem_implementation() {
Some
(
&
state
),
&
call
,
&
return_term
(
"return_target"
),
&
None
,
)
.unwrap
();
assert_eq!
(
return_state
.stack_id
,
new_id
(
"main"
,
"RSP"
));
...
...
@@ -354,6 +358,7 @@ fn update_return() {
Some
(
&
state_before_call
),
&
call_term
(
"callee"
),
&
return_term
(
"return_target"
),
&
None
,
)
.unwrap
();
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/pointer_inference/context/trait_impls.rs
View file @
933a929c
...
...
@@ -120,6 +120,7 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
state
:
&
State
,
call_term
:
&
Term
<
Jmp
>
,
_target_node
:
&
crate
::
analysis
::
graph
::
Node
,
calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
State
>
{
if
let
Jmp
::
Call
{
target
:
ref
callee_tid
,
...
...
@@ -143,7 +144,10 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
// Remove callee-saved register, since the callee should not use their values anyway.
// This should prevent recursive references to all stack frames in the call tree
// since the source for it, the stack frame base pointer, is callee-saved.
if
let
Some
(
cconv
)
=
self
.project
.get_standard_calling_convention
()
{
if
let
Some
(
cconv
)
=
self
.project
.get_specific_calling_convention
(
calling_convention
)
{
// Note that this may lead to analysis errors if the function uses another calling convention.
callee_state
.remove_callee_saved_register
(
cconv
);
}
...
...
@@ -209,6 +213,7 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
state_before_call
:
Option
<&
State
>
,
call_term
:
&
Term
<
Jmp
>
,
return_term
:
&
Term
<
Jmp
>
,
calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
State
>
{
// TODO: For the long term we may have to replace the IDs representing callers with something
// that identifies the edge of the call and not just the callsite.
...
...
@@ -280,7 +285,10 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
state_after_return
.readd_caller_objects
(
state_before_call
);
if
let
Some
(
cconv
)
=
self
.project
.get_standard_calling_convention
()
{
if
let
Some
(
cconv
)
=
self
.project
.get_specific_calling_convention
(
calling_convention
)
{
// Restore information about callee-saved register from the caller state.
// TODO: Implement some kind of check to ensure that the callee adheres to the given calling convention!
// The current workaround should be reasonably exact for programs written in C,
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/context/trait_impls.rs
View file @
933a929c
...
...
@@ -91,6 +91,7 @@ impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>>
_state
:
&
State
<
T
>
,
_call
:
&
Term
<
Jmp
>
,
_target
:
&
crate
::
analysis
::
graph
::
Node
,
_calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
State
<
T
>>
{
None
}
...
...
@@ -101,6 +102,7 @@ impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>>
state_before_call
:
Option
<&
State
<
T
>>
,
_call_term
:
&
Term
<
Jmp
>
,
_return_term
:
&
Term
<
Jmp
>
,
_calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
State
<
T
>>
{
if
let
Some
(
state
)
=
state_before_call
{
let
mut
new_state
=
state
.clone
();
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/analysis/string_abstraction/context/trait_impls/tests.rs
View file @
933a929c
...
...
@@ -189,6 +189,7 @@ fn test_update_return() {
None
,
&
Jmp
::
branch
(
"start1"
,
"end1"
),
&
Jmp
::
branch
(
"start2"
,
"end2"
),
&
None
,
);
assert_eq!
(
None
,
new_state
);
...
...
@@ -200,6 +201,7 @@ fn test_update_return() {
Some
(
&
setup
.state_before_call
),
&
Jmp
::
branch
(
"start1"
,
"end1"
),
&
Jmp
::
branch
(
"start2"
,
"end2"
),
&
None
,
)
.unwrap
();
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/checkers/cwe_476/context.rs
View file @
933a929c
...
...
@@ -260,7 +260,13 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
/// Generate a CWE warning if taint may be contained in the function parameters.
/// Always returns `None` so that the analysis stays intraprocedural.
fn
update_call
(
&
self
,
state
:
&
State
,
call
:
&
Term
<
Jmp
>
,
_target
:
&
Node
)
->
Option
<
Self
::
Value
>
{
fn
update_call
(
&
self
,
state
:
&
State
,
call
:
&
Term
<
Jmp
>
,
_target
:
&
Node
,
_calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
Self
::
Value
>
{
let
pi_state_option
=
self
.get_current_pointer_inference_state
(
state
,
&
call
.tid
);
if
state
.check_generic_function_params_for_taint
(
self
.project
,
pi_state_option
.as_ref
())
{
self
.generate_cwe_warning
(
&
call
.tid
);
...
...
@@ -390,6 +396,7 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
state_before_call
:
Option
<&
State
>
,
call_term
:
&
Term
<
Jmp
>
,
return_term
:
&
Term
<
Jmp
>
,
_calling_convention
:
&
Option
<
String
>
,
)
->
Option
<
State
>
{
if
let
Some
(
state
)
=
state_before_return
{
// If taint is returned, generate a CWE warning
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/project.rs
View file @
933a929c
...
...
@@ -39,6 +39,19 @@ impl Project {
.or_else
(||
self
.calling_conventions
.get
(
"__cdecl"
))
}
/// Try to find a specific calling convention in the list of calling conventions in the project.
/// If not given a calling convention (i.e. given `None`) then falls back to `get_standard_calling_convention`
pub
fn
get_specific_calling_convention
(
&
self
,
cconv_name_opt
:
&
Option
<
String
>
,
)
->
Option
<&
CallingConvention
>
{
if
let
Some
(
cconv_name
)
=
cconv_name_opt
{
self
.calling_conventions
.get
(
cconv_name
)
}
else
{
self
.get_standard_calling_convention
()
}
}
/// Return the calling convention associated to the given extern symbol.
/// If the extern symbol has no annotated calling convention
/// then return the standard calling convention of the project instead.
...
...
@@ -140,6 +153,7 @@ impl Project {
indirect_jmp_targets
:
Vec
::
new
(),
},
}],
calling_convention
:
None
,
},
};
self
.program
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/project/block_duplication_normalization.rs
View file @
933a929c
...
...
@@ -232,6 +232,7 @@ mod tests {
term
:
Sub
{
name
:
sub_name
.to_string
(),
blocks
,
calling_convention
:
None
,
},
}
}
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/sub.rs
View file @
933a929c
...
...
@@ -13,6 +13,8 @@ pub struct Sub {
/// The basic blocks belonging to the subroutine.
/// The first block is also the entry point of the subroutine.
pub
blocks
:
Vec
<
Term
<
Blk
>>
,
/// The calling convention used to call if known
pub
calling_convention
:
Option
<
String
>
,
}
/// A parameter or return argument of a function.
...
...
@@ -206,6 +208,7 @@ mod tests {
term
:
Sub
{
name
:
name
.to_string
(),
blocks
:
Vec
::
new
(),
calling_convention
:
None
,
},
}
}
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/pcode/term.rs
View file @
933a929c
...
...
@@ -337,6 +337,9 @@ pub struct Sub {
///
/// Note that the first block of the array may *not* be the function entry point!
pub
blocks
:
Vec
<
Term
<
Blk
>>
,
/// The calling convention used (as reported by Ghidra, i.e. this may not be correct).
pub
calling_convention
:
Option
<
String
>
,
}
impl
Term
<
Sub
>
{
...
...
@@ -376,6 +379,7 @@ impl Term<Sub> {
term
:
IrSub
{
name
:
self
.term.name
,
blocks
,
calling_convention
:
self
.term.calling_convention
,
},
}
}
...
...
This diff is collapsed.
Click to expand it.
src/ghidra/p_code_extractor/internal/TermCreator.java
View file @
933a929c
...
...
@@ -43,7 +43,11 @@ public class TermCreator {
* Creates a Sub Term with an unique TID consisting of the prefix sub and its entry address.
*/
public
static
Term
<
Sub
>
createSubTerm
(
Function
func
)
{
return
new
Term
<
Sub
>(
HelperFunctions
.
functionEntryPoints
.
get
(
func
.
getEntryPoint
().
toString
()),
new
Sub
(
func
.
getName
(),
func
.
getBody
()));
Sub
subInTerm
=
new
Sub
(
func
.
getName
(),
func
.
getBody
());
if
(
func
.
getCallingConvention
()
!=
null
)
{
subInTerm
.
setCallingConvention
(
func
.
getCallingConvention
().
toString
());
}
return
new
Term
<
Sub
>(
HelperFunctions
.
functionEntryPoints
.
get
(
func
.
getEntryPoint
().
toString
()),
subInTerm
);
}
...
...
This diff is collapsed.
Click to expand it.
src/ghidra/p_code_extractor/term/Sub.java
View file @
933a929c
...
...
@@ -12,6 +12,8 @@ public class Sub {
private
AddressSetView
addresses
;
@SerializedName
(
"blocks"
)
private
ArrayList
<
Term
<
Blk
>>
blocks
;
@SerializedName
(
"calling_convention"
)
private
String
callingConvention
;
public
Sub
()
{
}
...
...
@@ -54,4 +56,12 @@ public class Sub {
public
void
setAddresses
(
AddressSetView
addresses
)
{
this
.
addresses
=
addresses
;
}
public
String
getCallingConvention
()
{
return
this
.
callingConvention
;
}
public
void
setCallingConvention
(
String
callingConvention
)
{
this
.
callingConvention
=
callingConvention
;
}
}
This diff is collapsed.
Click to expand it.
test/src/lib.rs
View file @
933a929c
...
...
@@ -434,7 +434,7 @@ mod tests {
// We would need knowledge about alignment guarantees for the stack pointer at the start of main() to fix this.
mark_skipped
(
&
mut
tests
,
"x86"
,
"gcc"
);
mark_
compiler_skipped
(
&
mut
tests
,
"mingw32-gcc"
);
// TODO: Check reason for failure!
mark_
skipped
(
&
mut
tests
,
"x86"
,
"mingw32-gcc"
);
// TODO: Check reason for failure! Probably same as above?
for
test_case
in
tests
{
let
num_expected_occurences
=
2
;
...
...
@@ -462,7 +462,7 @@ mod tests {
// We would need knowledge about alignment guarantees for the stack pointer at the start of main() to fix this.
mark_skipped
(
&
mut
tests
,
"x86"
,
"gcc"
);
mark_
compiler_skipped
(
&
mut
tests
,
"mingw32-gcc"
);
// TODO: Check reason for failure!
mark_
skipped
(
&
mut
tests
,
"x86"
,
"mingw32-gcc"
);
// TODO: Check reason for failure! Probably same as above?
for
test_case
in
tests
{
let
num_expected_occurences
=
1
;
...
...
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