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
809b7ca8
Unverified
Commit
809b7ca8
authored
Jan 08, 2021
by
Melvin Klimke
Committed by
GitHub
Jan 08, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Backward analysis trait (#123)
parent
95566833
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
786 additions
and
141 deletions
+786
-141
mock_context.rs
...nalysis/backward_interprocedural_fixpoint/mock_context.rs
+126
-0
mod.rs
..._rs/src/analysis/backward_interprocedural_fixpoint/mod.rs
+250
-0
tests.rs
...s/src/analysis/backward_interprocedural_fixpoint/tests.rs
+303
-0
forward_interprocedural_fixpoint.rs
...ecker_rs/src/analysis/forward_interprocedural_fixpoint.rs
+38
-121
interprocedural_fixpoint_generic.rs
...ecker_rs/src/analysis/interprocedural_fixpoint_generic.rs
+44
-0
mod.rs
cwe_checker_rs/src/analysis/mod.rs
+3
-1
tests.rs
...hecker_rs/src/analysis/pointer_inference/context/tests.rs
+2
-2
trait_impls.rs
..._rs/src/analysis/pointer_inference/context/trait_impls.rs
+1
-1
mod.rs
cwe_checker_rs/src/analysis/pointer_inference/mod.rs
+12
-9
cwe_476.rs
cwe_checker_rs/src/checkers/cwe_476.rs
+4
-4
context.rs
cwe_checker_rs/src/checkers/cwe_476/context.rs
+3
-3
No files found.
cwe_checker_rs/src/analysis/backward_interprocedural_fixpoint/mock_context.rs
0 → 100644
View file @
809b7ca8
use
super
::
*
;
use
crate
::
analysis
::
graph
::
Graph
;
use
petgraph
::
graph
::
NodeIndex
;
use
std
::
collections
::{
HashMap
,
HashSet
};
/// Identifier for BlkStart and BlkEnd nodes
#[derive(Clone,
PartialEq,
Eq,
Hash)]
pub
enum
StartEnd
{
Start
,
End
,
}
/// A simple mock context, only containing the program cfg
#[derive(Clone)]
pub
struct
Context
<
'a
>
{
pub
graph
:
Graph
<
'a
>
,
pub
tid_to_node_index
:
HashMap
<
(
Tid
,
Tid
,
StartEnd
),
NodeIndex
>
,
}
impl
<
'a
>
Context
<
'a
>
{
pub
fn
new
(
project
:
&
'a
Project
)
->
Self
{
let
mut
graph
=
crate
::
analysis
::
graph
::
get_program_cfg
(
&
project
.program
,
HashSet
::
new
());
graph
.reverse
();
let
mut
tid_to_node_index
:
HashMap
<
(
Tid
,
Tid
,
StartEnd
),
NodeIndex
>
=
HashMap
::
new
();
for
node
in
graph
.node_indices
()
{
let
node_value
=
graph
.node_weight
(
node
)
.unwrap
();
match
node_value
{
Node
::
BlkStart
{
0
:
block
,
1
:
subroutine
,
}
=>
{
tid_to_node_index
.insert
(
(
subroutine
.tid
.clone
(),
block
.tid
.clone
(),
StartEnd
::
Start
),
node
,
);
}
Node
::
BlkEnd
{
0
:
block
,
1
:
subroutine
,
}
=>
{
tid_to_node_index
.insert
(
(
subroutine
.tid
.clone
(),
block
.tid
.clone
(),
StartEnd
::
End
),
node
,
);
}
_
=>
(),
}
}
Context
{
graph
,
tid_to_node_index
,
}
}
}
impl
<
'a
>
crate
::
analysis
::
backward_interprocedural_fixpoint
::
Context
<
'a
>
for
Context
<
'a
>
{
type
Value
=
u64
;
fn
get_graph
(
&
self
)
->
&
Graph
<
'a
>
{
&
self
.graph
}
/// Take the minimum of two values when merging
fn
merge
(
&
self
,
val1
:
&
u64
,
val2
:
&
u64
)
->
u64
{
std
::
cmp
::
min
(
*
val1
,
*
val2
)
}
/// Increase the Def count when parsing one
fn
update_def
(
&
self
,
val
:
&
u64
,
_def
:
&
Term
<
Def
>
)
->
Option
<
u64
>
{
let
updated_value
=
*
val
+
1
;
Some
(
updated_value
)
}
/// Simply copy the value at the jumpsite
fn
update_jumpsite
(
&
self
,
value_after_jump
:
&
u64
,
_jump
:
&
Term
<
Jmp
>
,
_untaken_conditional
:
Option
<&
Term
<
Jmp
>>
,
_jumpsite
:
&
Term
<
Blk
>
,
)
->
Option
<
u64
>
{
Some
(
*
value_after_jump
)
}
/// Merge two values at the callsite if both exist
/// If there is only one, simply copy it
fn
update_callsite
(
&
self
,
target_value
:
Option
<&
u64
>
,
return_value
:
Option
<&
u64
>
,
_call
:
&
Term
<
Jmp
>
,
_return_
:
&
Term
<
Jmp
>
,
)
->
Option
<
u64
>
{
match
(
target_value
,
return_value
)
{
(
Some
(
call
),
Some
(
fall
))
=>
Some
(
self
.merge
(
call
,
fall
)),
(
Some
(
call
),
_
)
=>
Some
(
*
call
),
(
_
,
Some
(
fall
))
=>
Some
(
*
fall
),
_
=>
panic!
(
"No values to merge at callsite!"
),
}
}
/// Simply copy the value
fn
split_call_stub
(
&
self
,
combined_value
:
&
u64
)
->
Option
<
u64
>
{
Some
(
*
combined_value
)
}
/// Simply copy the value
fn
split_return_stub
(
&
self
,
combined_value
:
&
u64
)
->
Option
<
u64
>
{
Some
(
*
combined_value
)
}
/// Simply copy the value
fn
update_call_stub
(
&
self
,
value_after_call
:
&
u64
,
_call
:
&
Term
<
Jmp
>
)
->
Option
<
u64
>
{
Some
(
*
value_after_call
)
}
/// Simply copy the value
fn
specialize_conditional
(
&
self
,
value_after_jump
:
&
u64
,
_condition
:
&
Expression
,
_is_true
:
bool
,
)
->
Option
<
u64
>
{
Some
(
*
value_after_jump
)
}
}
cwe_checker_rs/src/analysis/backward_interprocedural_fixpoint/mod.rs
0 → 100644
View file @
809b7ca8
//! Creating and computing backward interprocedural fixpoint problems.
//!
//! # General notes
//!
//! This module supports computation of fixpoint problems on the control flow graphs generated by the `graph` module.
//!
//!
//! To compute a generalized fixpoint problem,
//! first construct a context object implementing the `Context`trait.
//! Use it to construct a `Computation` object.
//! The `Computation` object provides the necessary methods for the actual fixpoint computation.
use
super
::
fixpoint
::
Context
as
GeneralFPContext
;
use
super
::
graph
::
*
;
use
super
::
interprocedural_fixpoint_generic
::
*
;
use
crate
::
intermediate_representation
::
*
;
use
petgraph
::
graph
::
EdgeIndex
;
use
std
::
marker
::
PhantomData
;
/// The context for an backward interprocedural fixpoint computation.
///
/// Basically, a `Context` object needs to contain a reference to the actual graph,
/// a method for merging node values,
/// and methods for computing the edge transitions for each different edge type.
///
/// All trait methods have access to the FixpointProblem structure, so that context informations are accessible through it.
///
/// All edge transition functions can return `None` to indicate that no information flows through the edge.
/// For example, this can be used to indicate edges that can never been taken.
pub
trait
Context
<
'a
>
{
type
Value
:
PartialEq
+
Eq
+
Clone
;
/// Get a reference to the graph that the fixpoint is computed on.
/// The return value is expected to be the reversed CFG.
fn
get_graph
(
&
self
)
->
&
Graph
<
'a
>
;
/// Merge two node values.
fn
merge
(
&
self
,
value1
:
&
Self
::
Value
,
value2
:
&
Self
::
Value
)
->
Self
::
Value
;
/// Transition function for `Def` terms.
/// The transition function for a basic block is computed
/// by iteratively applying this function to the starting value for each `Def` term in the basic block.
/// The iteration short-circuits and returns `None` if `update_def` returns `None` at any point.
fn
update_def
(
&
self
,
value
:
&
Self
::
Value
,
def
:
&
Term
<
Def
>
)
->
Option
<
Self
::
Value
>
;
/// Transition function for (conditional and unconditional) `Jmp` terms.
fn
update_jumpsite
(
&
self
,
value_after_jump
:
&
Self
::
Value
,
jump
:
&
Term
<
Jmp
>
,
untaken_conditional
:
Option
<&
Term
<
Jmp
>>
,
jumpsite
:
&
Term
<
Blk
>
,
)
->
Option
<
Self
::
Value
>
;
/// Transition function for in-program calls.
/// The target value is coming in via the call edge from the BlkStart node of the called subroutine and
/// the return_value is coming in via the call stub edge from the returned-to node of the caller
fn
update_callsite
(
&
self
,
target_value
:
Option
<&
Self
::
Value
>
,
return_value
:
Option
<&
Self
::
Value
>
,
call
:
&
Term
<
Jmp
>
,
return_
:
&
Term
<
Jmp
>
,
)
->
Option
<
Self
::
Value
>
;
/// Transition function for call stub split.
/// Has access to the value at the ReturnCombine node and
/// decides which data is transferred along the Call Stub Edge.
fn
split_call_stub
(
&
self
,
combined_value
:
&
Self
::
Value
)
->
Option
<
Self
::
Value
>
;
/// Transition function for return stub split.
/// Has access to the value at the ReturnCombine node and
/// decides which data is transferred along the Return Stub Edge.
fn
split_return_stub
(
&
self
,
combined_value
:
&
Self
::
Value
)
->
Option
<
Self
::
Value
>
;
/// Transition function for calls to functions not contained in the binary.
/// The corresponding edge goes from the callsite to the returned-to block.
fn
update_call_stub
(
&
self
,
value_after_call
:
&
Self
::
Value
,
call
:
&
Term
<
Jmp
>
,
)
->
Option
<
Self
::
Value
>
;
/// This function is used to refine the value using the information on which branch was taken on a conditional jump.
fn
specialize_conditional
(
&
self
,
value_after_jump
:
&
Self
::
Value
,
condition
:
&
Expression
,
is_true
:
bool
,
)
->
Option
<
Self
::
Value
>
;
}
impl
<
'a
,
T
:
Context
<
'a
>>
GeneralFPContext
for
GeneralizedContext
<
'a
,
T
>
{
type
EdgeLabel
=
Edge
<
'a
>
;
type
NodeLabel
=
Node
<
'a
>
;
type
NodeValue
=
NodeValue
<
T
::
Value
>
;
/// Get a reference to the underlying graph.
fn
get_graph
(
&
self
)
->
&
Graph
<
'a
>
{
self
.context
.get_graph
()
}
/// Merge two values using the merge function from the interprocedural context object.
fn
merge
(
&
self
,
val1
:
&
Self
::
NodeValue
,
val2
:
&
Self
::
NodeValue
)
->
Self
::
NodeValue
{
use
NodeValue
::
*
;
match
(
val1
,
val2
)
{
(
Value
(
value1
),
Value
(
value2
))
=>
Value
(
self
.context
.merge
(
value1
,
value2
)),
(
CallFlowCombinator
{
call_stub
:
call1
,
interprocedural_flow
:
target1
,
},
CallFlowCombinator
{
call_stub
:
call2
,
interprocedural_flow
:
target2
,
},
)
=>
CallFlowCombinator
{
call_stub
:
merge_option
(
call1
,
call2
,
|
v1
,
v2
|
self
.context
.merge
(
v1
,
v2
)),
interprocedural_flow
:
merge_option
(
target1
,
target2
,
|
v1
,
v2
|
{
self
.context
.merge
(
v1
,
v2
)
}),
},
_
=>
panic!
(
"Malformed CFG in fixpoint computation"
),
}
}
/// Backward edge transition function.
/// Applies the transition functions from the interprocedural context object
/// corresponding to the type of the provided edge.
fn
update_edge
(
&
self
,
node_value
:
&
Self
::
NodeValue
,
edge
:
EdgeIndex
,
)
->
Option
<
Self
::
NodeValue
>
{
let
graph
=
self
.context
.get_graph
();
let
(
start_node
,
end_node
)
=
graph
.edge_endpoints
(
edge
)
.unwrap
();
match
graph
.edge_weight
(
edge
)
.unwrap
()
{
// Added rev() function to iterator to iterate backwards over the definitions
Edge
::
Block
=>
{
let
block_term
=
graph
.node_weight
(
start_node
)
.unwrap
()
.get_block
();
let
value
=
node_value
.unwrap_value
();
let
defs
=
&
block_term
.term.defs
;
let
end_val
=
defs
.iter
()
.rev
()
.try_fold
(
value
.clone
(),
|
accum
,
def
|
{
self
.context
.update_def
(
&
accum
,
def
)
});
end_val
.map
(
NodeValue
::
Value
)
}
Edge
::
ReturnCombine
(
_
)
=>
{
Some
(
Self
::
NodeValue
::
Value
(
node_value
.unwrap_value
()
.clone
()))
}
// The Call Edge value is added to the CallSourceCombinator.
// The end node will be the callsite node and the node_value parameter is the value at the
// called subroutine's BlkStart node
Edge
::
Call
(
_
)
=>
Some
(
NodeValue
::
CallFlowCombinator
{
call_stub
:
None
,
interprocedural_flow
:
Some
(
node_value
.unwrap_value
()
.clone
()),
}),
// The CallStub Edge value is added to the CallSourceCombinator
// The user has the ability to split the node value at the BlkStart return to node
// to only send specific data along the CallStub Edge to the callsite
Edge
::
CRCallStub
=>
Some
(
NodeValue
::
CallFlowCombinator
{
call_stub
:
self
.context
.split_call_stub
(
node_value
.unwrap_value
()),
interprocedural_flow
:
None
,
}),
// The user has the ability to split the node value at the BlkStart return node
// to only send specific data along the ReturnStub Edge to the last BlkEnd node called subroutine
Edge
::
CRReturnStub
=>
self
.context
.split_return_stub
(
node_value
.unwrap_value
())
.map
(
NodeValue
::
Value
),
// The CallCombine Edge merges the values coming in from the CallStub Edge and Call Edge
// It also gives the user access to the call and return term.
Edge
::
CallCombine
(
return_term
)
=>
match
node_value
{
NodeValue
::
Value
(
_
)
=>
panic!
(
"Unexpected interprocedural fixpoint graph state"
),
NodeValue
::
CallFlowCombinator
{
call_stub
,
interprocedural_flow
,
}
=>
{
let
call_block
=
match
graph
.node_weight
(
start_node
)
{
Some
(
Node
::
CallSource
{
source
:
(
call_block
,
..
),
target
:
_
,
})
=>
call_block
,
_
=>
panic!
(
"Malformed Control flow graph"
),
};
let
call_term
=
&
call_block
.term.jmps
[
0
];
match
self
.context
.update_callsite
(
interprocedural_flow
.as_ref
(),
call_stub
.as_ref
(),
call_term
,
return_term
,
)
{
Some
(
val
)
=>
Some
(
NodeValue
::
Value
(
val
)),
None
=>
None
,
}
}
},
Edge
::
ExternCallStub
(
call
)
=>
self
.context
.update_call_stub
(
node_value
.unwrap_value
(),
call
)
.map
(
NodeValue
::
Value
),
Edge
::
Jump
(
jump
,
untaken_conditional
)
=>
self
.context
.update_jumpsite
(
node_value
.unwrap_value
(),
jump
,
*
untaken_conditional
,
graph
[
end_node
]
.get_block
(),
)
.map
(
NodeValue
::
Value
),
}
}
}
/// This struct is a wrapper to create a general fixpoint context out of an interprocedural fixpoint context.
pub
struct
GeneralizedContext
<
'a
,
T
:
Context
<
'a
>>
{
context
:
T
,
_phantom_graph_reference
:
PhantomData
<
Graph
<
'a
>>
,
}
impl
<
'a
,
T
:
Context
<
'a
>>
GeneralizedContext
<
'a
,
T
>
{
/// Create a new generalized context out of an interprocedural context object.
pub
fn
new
(
context
:
T
)
->
Self
{
GeneralizedContext
{
context
,
_phantom_graph_reference
:
PhantomData
,
}
}
pub
fn
get_context
(
&
self
)
->
&
T
{
&
self
.context
}
}
/// Generate a new computation from the corresponding context and an optional default value for nodes.
pub
fn
create_computation
<
'a
,
T
:
Context
<
'a
>>
(
problem
:
T
,
default_value
:
Option
<
T
::
Value
>
,
)
->
super
::
fixpoint
::
Computation
<
GeneralizedContext
<
'a
,
T
>>
{
let
generalized_problem
=
GeneralizedContext
::
new
(
problem
);
super
::
fixpoint
::
Computation
::
new
(
generalized_problem
,
default_value
.map
(
NodeValue
::
Value
))
}
#[cfg(test)]
pub
mod
tests
;
#[cfg(test)]
pub
mod
mock_context
;
cwe_checker_rs/src/analysis/backward_interprocedural_fixpoint/tests.rs
0 → 100644
View file @
809b7ca8
use
crate
::{
bil
::
Bitvector
,
intermediate_representation
::
*
};
use
super
::{
create_computation
,
mock_context
,
NodeValue
};
use
mock_context
::
Context
;
use
mock_context
::
StartEnd
;
fn
mock_program
()
->
Term
<
Program
>
{
let
var
=
Variable
{
name
:
String
::
from
(
"RAX"
),
size
:
ByteSize
::
new
(
8
),
is_temp
:
false
,
};
let
value
=
Expression
::
UnOp
{
op
:
UnOpType
::
IntNegate
,
arg
:
Box
::
new
(
Expression
::
Var
(
var
.clone
())),
};
let
def_term1
=
Term
{
tid
:
Tid
::
new
(
"def1"
.to_string
()),
term
:
Def
::
Assign
{
var
:
var
.clone
(),
value
:
value
.clone
(),
},
};
let
def_term2
=
Term
{
tid
:
Tid
::
new
(
"def2"
.to_string
()),
term
:
Def
::
Assign
{
var
:
var
.clone
(),
value
:
value
.clone
(),
},
};
let
def_term3
=
Term
{
tid
:
Tid
::
new
(
"def3"
.to_string
()),
term
:
Def
::
Assign
{
var
:
var
.clone
(),
value
:
value
.clone
(),
},
};
let
def_term4
=
Term
{
tid
:
Tid
::
new
(
"def4"
.to_string
()),
term
:
Def
::
Assign
{
var
:
var
.clone
(),
value
:
value
.clone
(),
},
};
let
def_term5
=
Term
{
tid
:
Tid
::
new
(
"def5"
.to_string
()),
term
:
Def
::
Assign
{
var
:
var
.clone
(),
value
:
value
.clone
(),
},
};
let
call_term
=
Term
{
tid
:
Tid
::
new
(
"call"
.to_string
()),
term
:
Jmp
::
Call
{
target
:
Tid
::
new
(
"sub2"
),
return_
:
Some
(
Tid
::
new
(
"sub1_blk2"
)),
},
};
let
return_term
=
Term
{
tid
:
Tid
::
new
(
"return"
.to_string
()),
term
:
Jmp
::
Return
(
Expression
::
Const
(
Bitvector
::
zero
(
64
.into
()))),
// The return term does not matter
};
let
jmp
=
Jmp
::
Branch
(
Tid
::
new
(
"sub1_blk1"
));
let
jmp_term
=
Term
{
tid
:
Tid
::
new
(
"jump"
),
term
:
jmp
,
};
let
sub1_blk1
=
Term
{
tid
:
Tid
::
new
(
"sub1_blk1"
),
term
:
Blk
{
defs
:
vec!
[
def_term1
],
jmps
:
vec!
[
call_term
],
},
};
let
sub1_blk2
=
Term
{
tid
:
Tid
::
new
(
"sub1_blk2"
),
term
:
Blk
{
defs
:
vec!
[
def_term5
],
jmps
:
vec!
[
jmp_term
],
},
};
let
sub1
=
Term
{
tid
:
Tid
::
new
(
"sub1"
),
term
:
Sub
{
name
:
"sub1"
.to_string
(),
blocks
:
vec!
[
sub1_blk1
,
sub1_blk2
],
},
};
let
cond_jump
=
Jmp
::
CBranch
{
target
:
Tid
::
new
(
"sub1_blk1"
),
condition
:
Expression
::
Const
(
Bitvector
::
from_u8
(
0
)),
};
let
cond_jump_term
=
Term
{
tid
:
Tid
::
new
(
"cond_jump"
),
term
:
cond_jump
,
};
let
jump_term_2
=
Term
{
tid
:
Tid
::
new
(
"jump2"
),
term
:
Jmp
::
Branch
(
Tid
::
new
(
"sub2_blk2"
)),
};
let
sub2_blk1
=
Term
{
tid
:
Tid
::
new
(
"sub2_blk1"
),
term
:
Blk
{
defs
:
vec!
[
def_term2
,
def_term3
],
jmps
:
vec!
[
cond_jump_term
,
jump_term_2
],
},
};
let
sub2_blk2
=
Term
{
tid
:
Tid
::
new
(
"sub2_blk2"
),
term
:
Blk
{
defs
:
vec!
[
def_term4
],
jmps
:
vec!
[
return_term
],
},
};
let
sub2
=
Term
{
tid
:
Tid
::
new
(
"sub2"
),
term
:
Sub
{
name
:
"sub2"
.to_string
(),
blocks
:
vec!
[
sub2_blk1
,
sub2_blk2
],
},
};
let
program
=
Term
{
tid
:
Tid
::
new
(
"program"
),
term
:
Program
{
subs
:
vec!
[
sub1
,
sub2
],
extern_symbols
:
Vec
::
new
(),
entry_points
:
Vec
::
new
(),
},
};
program
}
#[test]
fn
backward_fixpoint
()
{
let
project
=
Project
{
program
:
mock_program
(),
cpu_architecture
:
String
::
from
(
"x86"
),
stack_pointer_register
:
Variable
{
name
:
String
::
from
(
"RSP"
),
size
:
ByteSize
::
new
(
8
),
is_temp
:
false
,
},
calling_conventions
:
Vec
::
new
(),
};
let
mock_con
=
Context
::
new
(
&
project
);
let
mut
computation
=
create_computation
(
mock_con
.clone
(),
None
);
computation
.set_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub1"
),
Tid
::
new
(
"sub1_blk1"
),
StartEnd
::
Start
))
.unwrap
(),
NodeValue
::
Value
(
0
),
);
computation
.compute_with_max_steps
(
100
);
// The fixpoint values of all 12 BlockStart/BlockEnd nodes are compared with their expected value
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub1"
),
Tid
::
new
(
"sub1_blk1"
),
StartEnd
::
Start
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
0
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub1"
),
Tid
::
new
(
"sub1_blk1"
),
StartEnd
::
End
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
1
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub1"
),
Tid
::
new
(
"sub1_blk2"
),
StartEnd
::
Start
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
1
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub1"
),
Tid
::
new
(
"sub1_blk2"
),
StartEnd
::
End
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
0
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub2"
),
Tid
::
new
(
"sub2_blk1"
),
StartEnd
::
Start
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
4
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub2"
),
Tid
::
new
(
"sub2_blk1"
),
StartEnd
::
End
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
2
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub2"
),
Tid
::
new
(
"sub2_blk2"
),
StartEnd
::
Start
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
2
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub2"
),
Tid
::
new
(
"sub2_blk2"
),
StartEnd
::
End
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
1
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub2"
),
Tid
::
new
(
"sub1_blk1"
),
StartEnd
::
Start
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
5
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub2"
),
Tid
::
new
(
"sub1_blk1"
),
StartEnd
::
End
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
4
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub2"
),
Tid
::
new
(
"sub1_blk2"
),
StartEnd
::
Start
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
6
as
u64
);
assert_eq!
(
*
computation
.get_node_value
(
*
mock_con
.tid_to_node_index
.get
(
&
(
Tid
::
new
(
"sub2"
),
Tid
::
new
(
"sub1_blk2"
),
StartEnd
::
End
))
.unwrap
()
)
.unwrap
()
.unwrap_value
(),
5
as
u64
);
}
cwe_checker_rs/src/analysis/interprocedural_fixpoint.rs
→
cwe_checker_rs/src/analysis/
forward_
interprocedural_fixpoint.rs
View file @
809b7ca8
//! Creating and computing interprocedural fixpoint problems.
//! Creating and computing
forward
interprocedural fixpoint problems.
//!
//!
//! # General notes
//! # General notes
//!
//!
//! This module supports computation of fixpoint problems on the control flow graphs generated by the `graph` module.
//! This module supports computation of fixpoint problems on the control flow graphs generated by the `graph` module.
//! As of this writing, only forward analyses are possible,
//! backward analyses are not yet implemented.
//!
//!
//! To compute a generalized fixpoint problem,
//! To compute a generalized fixpoint problem,
//! first construct a context object implementing the `Context`trait.
//! first construct a context object implementing the `Context`trait.
...
@@ -13,27 +11,11 @@
...
@@ -13,27 +11,11 @@
use
super
::
fixpoint
::
Context
as
GeneralFPContext
;
use
super
::
fixpoint
::
Context
as
GeneralFPContext
;
use
super
::
graph
::
*
;
use
super
::
graph
::
*
;
use
super
::
interprocedural_fixpoint_generic
::
*
;
use
crate
::
intermediate_representation
::
*
;
use
crate
::
intermediate_representation
::
*
;
use
crate
::
prelude
::
*
;
use
petgraph
::
graph
::
EdgeIndex
;
use
fnv
::
FnvHashMap
;
use
petgraph
::
graph
::{
EdgeIndex
,
NodeIndex
};
use
std
::
marker
::
PhantomData
;
use
std
::
marker
::
PhantomData
;
#[derive(PartialEq,
Eq,
Serialize,
Deserialize)]
pub
enum
NodeValue
<
T
:
PartialEq
+
Eq
>
{
Value
(
T
),
CallReturnCombinator
{
call
:
Option
<
T
>
,
return_
:
Option
<
T
>
},
}
impl
<
T
:
PartialEq
+
Eq
>
NodeValue
<
T
>
{
pub
fn
unwrap_value
(
&
self
)
->
&
T
{
match
self
{
NodeValue
::
Value
(
value
)
=>
value
,
_
=>
panic!
(
"Unexpected node value type"
),
}
}
}
/// The context for an interprocedural fixpoint computation.
/// The context for an interprocedural fixpoint computation.
///
///
/// Basically, a `Context` object needs to contain a reference to the actual graph,
/// Basically, a `Context` object needs to contain a reference to the actual graph,
...
@@ -101,7 +83,7 @@ pub trait Context<'a> {
...
@@ -101,7 +83,7 @@ pub trait Context<'a> {
}
}
/// This struct is a wrapper to create a general fixpoint context out of an interprocedural fixpoint context.
/// This struct is a wrapper to create a general fixpoint context out of an interprocedural fixpoint context.
struct
GeneralizedContext
<
'a
,
T
:
Context
<
'a
>>
{
pub
struct
GeneralizedContext
<
'a
,
T
:
Context
<
'a
>>
{
context
:
T
,
context
:
T
,
_phantom_graph_reference
:
PhantomData
<
Graph
<
'a
>>
,
_phantom_graph_reference
:
PhantomData
<
Graph
<
'a
>>
,
}
}
...
@@ -114,6 +96,10 @@ impl<'a, T: Context<'a>> GeneralizedContext<'a, T> {
...
@@ -114,6 +96,10 @@ impl<'a, T: Context<'a>> GeneralizedContext<'a, T> {
_phantom_graph_reference
:
PhantomData
,
_phantom_graph_reference
:
PhantomData
,
}
}
}
}
pub
fn
get_context
(
&
self
)
->
&
T
{
&
self
.context
}
}
}
impl
<
'a
,
T
:
Context
<
'a
>>
GeneralFPContext
for
GeneralizedContext
<
'a
,
T
>
{
impl
<
'a
,
T
:
Context
<
'a
>>
GeneralFPContext
for
GeneralizedContext
<
'a
,
T
>
{
...
@@ -132,17 +118,19 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
...
@@ -132,17 +118,19 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
match
(
val1
,
val2
)
{
match
(
val1
,
val2
)
{
(
Value
(
value1
),
Value
(
value2
))
=>
Value
(
self
.context
.merge
(
value1
,
value2
)),
(
Value
(
value1
),
Value
(
value2
))
=>
Value
(
self
.context
.merge
(
value1
,
value2
)),
(
(
Call
Return
Combinator
{
Call
Flow
Combinator
{
call
:
call1
,
call
_stub
:
call1
,
return_
:
return1
,
interprocedural_flow
:
return1
,
},
},
Call
Return
Combinator
{
Call
Flow
Combinator
{
call
:
call2
,
call
_stub
:
call2
,
return_
:
return2
,
interprocedural_flow
:
return2
,
},
},
)
=>
CallReturnCombinator
{
)
=>
CallFlowCombinator
{
call
:
merge_option
(
call1
,
call2
,
|
v1
,
v2
|
self
.context
.merge
(
v1
,
v2
)),
call_stub
:
merge_option
(
call1
,
call2
,
|
v1
,
v2
|
self
.context
.merge
(
v1
,
v2
)),
return_
:
merge_option
(
return1
,
return2
,
|
v1
,
v2
|
self
.context
.merge
(
v1
,
v2
)),
interprocedural_flow
:
merge_option
(
return1
,
return2
,
|
v1
,
v2
|
{
self
.context
.merge
(
v1
,
v2
)
}),
},
},
_
=>
panic!
(
"Malformed CFG in fixpoint computation"
),
_
=>
panic!
(
"Malformed CFG in fixpoint computation"
),
}
}
...
@@ -174,17 +162,20 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
...
@@ -174,17 +162,20 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
.context
.context
.update_call
(
node_value
.unwrap_value
(),
call
,
&
graph
[
end_node
])
.update_call
(
node_value
.unwrap_value
(),
call
,
&
graph
[
end_node
])
.map
(
NodeValue
::
Value
),
.map
(
NodeValue
::
Value
),
Edge
::
CRCallStub
=>
Some
(
NodeValue
::
Call
Return
Combinator
{
Edge
::
CRCallStub
=>
Some
(
NodeValue
::
Call
Flow
Combinator
{
call
:
Some
(
node_value
.unwrap_value
()
.clone
()),
call
_stub
:
Some
(
node_value
.unwrap_value
()
.clone
()),
return_
:
None
,
interprocedural_flow
:
None
,
}),
}),
Edge
::
CRReturnStub
=>
Some
(
NodeValue
::
Call
Return
Combinator
{
Edge
::
CRReturnStub
=>
Some
(
NodeValue
::
Call
Flow
Combinator
{
call
:
None
,
call
_stub
:
None
,
return_
:
Some
(
node_value
.unwrap_value
()
.clone
()),
interprocedural_flow
:
Some
(
node_value
.unwrap_value
()
.clone
()),
}),
}),
Edge
::
ReturnCombine
(
call_term
)
=>
match
node_value
{
Edge
::
ReturnCombine
(
call_term
)
=>
match
node_value
{
NodeValue
::
Value
(
_
)
=>
panic!
(
"Unexpected interprocedural fixpoint graph state"
),
NodeValue
::
Value
(
_
)
=>
panic!
(
"Unexpected interprocedural fixpoint graph state"
),
NodeValue
::
CallReturnCombinator
{
call
,
return_
}
=>
{
NodeValue
::
CallFlowCombinator
{
call_stub
,
interprocedural_flow
,
}
=>
{
let
return_from_block
=
match
graph
.node_weight
(
start_node
)
{
let
return_from_block
=
match
graph
.node_weight
(
start_node
)
{
Some
(
Node
::
CallReturn
{
Some
(
Node
::
CallReturn
{
call
:
_
,
call
:
_
,
...
@@ -194,8 +185,8 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
...
@@ -194,8 +185,8 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
};
};
let
return_from_jmp
=
&
return_from_block
.term.jmps
[
0
];
let
return_from_jmp
=
&
return_from_block
.term.jmps
[
0
];
match
self
.context
.update_return
(
match
self
.context
.update_return
(
return_
.as_ref
(),
interprocedural_flow
.as_ref
(),
call
.as_ref
(),
call
_stub
.as_ref
(),
call_term
,
call_term
,
return_from_jmp
,
return_from_jmp
,
)
{
)
{
...
@@ -221,85 +212,11 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
...
@@ -221,85 +212,11 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
}
}
}
}
/// An intermediate result of an interprocedural fixpoint computation.
/// Generate a new computation from the corresponding context and an optional default value for nodes.
///
pub
fn
create_computation
<
'a
,
T
:
Context
<
'a
>>
(
/// The usage instructions are identical to the usage of the general fixpoint computation object,
problem
:
T
,
/// except that you need to provide an interprocedural context object instead of a general one.
default_value
:
Option
<
T
::
Value
>
,
pub
struct
Computation
<
'a
,
T
:
Context
<
'a
>>
{
)
->
super
::
fixpoint
::
Computation
<
GeneralizedContext
<
'a
,
T
>>
{
generalized_computation
:
super
::
fixpoint
::
Computation
<
GeneralizedContext
<
'a
,
T
>>
,
let
generalized_problem
=
GeneralizedContext
::
new
(
problem
);
}
super
::
fixpoint
::
Computation
::
new
(
generalized_problem
,
default_value
.map
(
NodeValue
::
Value
))
impl
<
'a
,
T
:
Context
<
'a
>>
Computation
<
'a
,
T
>
{
/// Generate a new computation from the corresponding context and an optional default value for nodes.
pub
fn
new
(
problem
:
T
,
default_value
:
Option
<
T
::
Value
>
)
->
Self
{
let
generalized_problem
=
GeneralizedContext
::
new
(
problem
);
let
computation
=
super
::
fixpoint
::
Computation
::
new
(
generalized_problem
,
default_value
.map
(
NodeValue
::
Value
),
);
Computation
{
generalized_computation
:
computation
,
}
}
/// Compute the fixpoint.
/// Note that this function does not terminate if the fixpoint algorithm does not stabilize.
pub
fn
compute
(
&
mut
self
)
{
self
.generalized_computation
.compute
()
}
/// Compute the fixpoint while updating each node at most max_steps times.
/// Note that the result may not be a stabilized fixpoint, but only an intermediate result of a fixpoint computation.
pub
fn
compute_with_max_steps
(
&
mut
self
,
max_steps
:
u64
)
{
self
.generalized_computation
.compute_with_max_steps
(
max_steps
)
}
/// Get the value of a node.
pub
fn
get_node_value
(
&
self
,
node
:
NodeIndex
)
->
Option
<&
NodeValue
<
T
::
Value
>>
{
self
.generalized_computation
.get_node_value
(
node
)
}
/// Set the value of a node and mark the node as not yet stabilized
pub
fn
set_node_value
(
&
mut
self
,
node
:
NodeIndex
,
value
:
NodeValue
<
T
::
Value
>
)
{
self
.generalized_computation
.set_node_value
(
node
,
value
)
}
/// Get a reference to the internal map where one can look up the current values of all nodes
pub
fn
node_values
(
&
self
)
->
&
FnvHashMap
<
NodeIndex
,
NodeValue
<
T
::
Value
>>
{
self
.generalized_computation
.node_values
()
}
/// Get a reference to the underlying graph
pub
fn
get_graph
(
&
self
)
->
&
Graph
{
self
.generalized_computation
.get_graph
()
}
/// Get a reference to the underlying context object
pub
fn
get_context
(
&
self
)
->
&
T
{
&
self
.generalized_computation
.get_context
()
.context
}
/// Returns `True` if the computation has stabilized, i.e. the internal worklist is empty.
pub
fn
has_stabilized
(
&
self
)
->
bool
{
self
.generalized_computation
.has_stabilized
()
}
/// Return a list of all nodes which are marked as not-stabilized
pub
fn
get_worklist
(
&
self
)
->
Vec
<
NodeIndex
>
{
self
.generalized_computation
.get_worklist
()
}
}
/// Helper function to merge to values wrapped in `Option<..>`.
/// Merges `(Some(x), None)` to `Some(x)`.
fn
merge_option
<
T
:
Clone
,
F
>
(
opt1
:
&
Option
<
T
>
,
opt2
:
&
Option
<
T
>
,
merge
:
F
)
->
Option
<
T
>
where
F
:
Fn
(
&
T
,
&
T
)
->
T
,
{
match
(
opt1
,
opt2
)
{
(
Some
(
value1
),
Some
(
value2
))
=>
Some
(
merge
(
value1
,
value2
)),
(
Some
(
value
),
None
)
|
(
None
,
Some
(
value
))
=>
Some
(
value
.clone
()),
(
None
,
None
)
=>
None
,
}
}
}
cwe_checker_rs/src/analysis/interprocedural_fixpoint_generic.rs
0 → 100644
View file @
809b7ca8
use
crate
::
prelude
::
*
;
/// NodeValue that can either be a single abstract value or a
/// composition of the abstract value computed following an interprocedural
/// call in the graph and of the abstract value when the call is not taken.
/// The CallFlowCombinator then allows for a merge of the values computed
/// over both paths.
///
/// The call_stub value will either be transferred from the callsite to the return site
/// in a forward analysis or the other way around in a backward analysis.
///
/// The interprocedural_flow value will either be transferred from the end of the called subroutine
/// to the return site in case of a forward analysis or from the beginning of the called subroutine
/// to the callsite in a backward analysis.
#[derive(PartialEq,
Eq,
Serialize,
Deserialize)]
pub
enum
NodeValue
<
T
:
PartialEq
+
Eq
>
{
Value
(
T
),
CallFlowCombinator
{
call_stub
:
Option
<
T
>
,
interprocedural_flow
:
Option
<
T
>
,
},
}
impl
<
T
:
PartialEq
+
Eq
>
NodeValue
<
T
>
{
pub
fn
unwrap_value
(
&
self
)
->
&
T
{
match
self
{
NodeValue
::
Value
(
value
)
=>
value
,
_
=>
panic!
(
"Unexpected node value type"
),
}
}
}
/// Helper function to merge to values wrapped in `Option<..>`.
/// Merges `(Some(x), None)` to `Some(x)`.
pub
fn
merge_option
<
T
:
Clone
,
F
>
(
opt1
:
&
Option
<
T
>
,
opt2
:
&
Option
<
T
>
,
merge
:
F
)
->
Option
<
T
>
where
F
:
Fn
(
&
T
,
&
T
)
->
T
,
{
match
(
opt1
,
opt2
)
{
(
Some
(
value1
),
Some
(
value2
))
=>
Some
(
merge
(
value1
,
value2
)),
(
Some
(
value
),
None
)
|
(
None
,
Some
(
value
))
=>
Some
(
value
.clone
()),
(
None
,
None
)
=>
None
,
}
}
cwe_checker_rs/src/analysis/mod.rs
View file @
809b7ca8
pub
mod
backward_interprocedural_fixpoint
;
pub
mod
fixpoint
;
pub
mod
fixpoint
;
pub
mod
forward_interprocedural_fixpoint
;
pub
mod
graph
;
pub
mod
graph
;
pub
mod
interprocedural_fixpoint
;
pub
mod
interprocedural_fixpoint
_generic
;
pub
mod
pointer_inference
;
pub
mod
pointer_inference
;
cwe_checker_rs/src/analysis/pointer_inference/context/tests.rs
View file @
809b7ca8
...
@@ -103,7 +103,7 @@ fn mock_project() -> (Project, Config) {
...
@@ -103,7 +103,7 @@ fn mock_project() -> (Project, Config) {
#[test]
#[test]
fn
context_problem_implementation
()
{
fn
context_problem_implementation
()
{
use
crate
::
analysis
::
interprocedural_fixpoint
::
Context
as
IpFpContext
;
use
crate
::
analysis
::
forward_
interprocedural_fixpoint
::
Context
as
IpFpContext
;
use
crate
::
analysis
::
pointer_inference
::
Data
;
use
crate
::
analysis
::
pointer_inference
::
Data
;
use
Expression
::
*
;
use
Expression
::
*
;
...
@@ -266,7 +266,7 @@ fn context_problem_implementation() {
...
@@ -266,7 +266,7 @@ fn context_problem_implementation() {
#[test]
#[test]
fn
update_return
()
{
fn
update_return
()
{
use
crate
::
analysis
::
interprocedural_fixpoint
::
Context
as
IpFpContext
;
use
crate
::
analysis
::
forward_
interprocedural_fixpoint
::
Context
as
IpFpContext
;
use
crate
::
analysis
::
pointer_inference
::
object
::
ObjectType
;
use
crate
::
analysis
::
pointer_inference
::
object
::
ObjectType
;
use
crate
::
analysis
::
pointer_inference
::
Data
;
use
crate
::
analysis
::
pointer_inference
::
Data
;
let
(
project
,
config
)
=
mock_project
();
let
(
project
,
config
)
=
mock_project
();
...
...
cwe_checker_rs/src/analysis/pointer_inference/context/trait_impls.rs
View file @
809b7ca8
use
super
::
*
;
use
super
::
*
;
impl
<
'a
>
crate
::
analysis
::
interprocedural_fixpoint
::
Context
<
'a
>
for
Context
<
'a
>
{
impl
<
'a
>
crate
::
analysis
::
forward_
interprocedural_fixpoint
::
Context
<
'a
>
for
Context
<
'a
>
{
type
Value
=
State
;
type
Value
=
State
;
/// Get the underlying graph on which the analysis operates.
/// Get the underlying graph on which the analysis operates.
...
...
cwe_checker_rs/src/analysis/pointer_inference/mod.rs
View file @
809b7ca8
...
@@ -13,7 +13,9 @@
...
@@ -13,7 +13,9 @@
//!
//!
//! See the `Config` struct for configurable analysis parameters.
//! See the `Config` struct for configurable analysis parameters.
use
super
::
interprocedural_fixpoint
::{
Computation
,
NodeValue
};
use
super
::
fixpoint
::
Computation
;
use
super
::
forward_interprocedural_fixpoint
::
GeneralizedContext
;
use
super
::
interprocedural_fixpoint_generic
::
NodeValue
;
use
crate
::
abstract_domain
::{
BitvectorDomain
,
DataDomain
};
use
crate
::
abstract_domain
::{
BitvectorDomain
,
DataDomain
};
use
crate
::
analysis
::
graph
::{
Graph
,
Node
};
use
crate
::
analysis
::
graph
::{
Graph
,
Node
};
use
crate
::
intermediate_representation
::
*
;
use
crate
::
intermediate_representation
::
*
;
...
@@ -59,7 +61,7 @@ pub struct Config {
...
@@ -59,7 +61,7 @@ pub struct Config {
/// A wrapper struct for the pointer inference computation object.
/// A wrapper struct for the pointer inference computation object.
pub
struct
PointerInference
<
'a
>
{
pub
struct
PointerInference
<
'a
>
{
computation
:
Computation
<
'a
,
Context
<
'a
>>
,
computation
:
Computation
<
GeneralizedContext
<
'a
,
Context
<
'a
>
>>
,
log_collector
:
crossbeam_channel
::
Sender
<
LogThreadMsg
>
,
log_collector
:
crossbeam_channel
::
Sender
<
LogThreadMsg
>
,
pub
collected_logs
:
(
Vec
<
LogMessage
>
,
Vec
<
CweWarning
>
),
pub
collected_logs
:
(
Vec
<
LogMessage
>
,
Vec
<
CweWarning
>
),
}
}
...
@@ -107,7 +109,7 @@ impl<'a> PointerInference<'a> {
...
@@ -107,7 +109,7 @@ impl<'a> PointerInference<'a> {
})
})
.collect
();
.collect
();
let
mut
fixpoint_computation
=
let
mut
fixpoint_computation
=
super
::
interprocedural_fixpoint
::
Computation
::
new
(
context
,
None
);
super
::
forward_interprocedural_fixpoint
::
create_computation
(
context
,
None
);
let
_
=
log_sender
.send
(
LogThreadMsg
::
Log
(
LogMessage
::
new_debug
(
format!
(
let
_
=
log_sender
.send
(
LogThreadMsg
::
Log
(
LogMessage
::
new_debug
(
format!
(
"Pointer Inference: Adding {} entry points"
,
"Pointer Inference: Adding {} entry points"
,
entry_sub_to_entry_node_map
.len
()
entry_sub_to_entry_node_map
.len
()
...
@@ -115,7 +117,7 @@ impl<'a> PointerInference<'a> {
...
@@ -115,7 +117,7 @@ impl<'a> PointerInference<'a> {
for
(
sub_tid
,
start_node_index
)
in
entry_sub_to_entry_node_map
.into_iter
()
{
for
(
sub_tid
,
start_node_index
)
in
entry_sub_to_entry_node_map
.into_iter
()
{
fixpoint_computation
.set_node_value
(
fixpoint_computation
.set_node_value
(
start_node_index
,
start_node_index
,
super
::
interprocedural_fixpoint
::
NodeValue
::
Value
(
State
::
new
(
super
::
interprocedural_fixpoint
_generic
::
NodeValue
::
Value
(
State
::
new
(
&
project
.stack_pointer_register
,
&
project
.stack_pointer_register
,
sub_tid
,
sub_tid
,
)),
)),
...
@@ -175,7 +177,7 @@ impl<'a> PointerInference<'a> {
...
@@ -175,7 +177,7 @@ impl<'a> PointerInference<'a> {
}
}
pub
fn
get_context
(
&
self
)
->
&
Context
{
pub
fn
get_context
(
&
self
)
->
&
Context
{
self
.computation
.get_context
()
self
.computation
.get_context
()
.get_context
()
}
}
pub
fn
get_node_value
(
&
self
,
node_id
:
NodeIndex
)
->
Option
<&
NodeValue
<
State
>>
{
pub
fn
get_node_value
(
&
self
,
node_id
:
NodeIndex
)
->
Option
<&
NodeValue
<
State
>>
{
...
@@ -235,7 +237,7 @@ impl<'a> PointerInference<'a> {
...
@@ -235,7 +237,7 @@ impl<'a> PointerInference<'a> {
.clone
();
.clone
();
self
.computation
.set_node_value
(
self
.computation
.set_node_value
(
entry
,
entry
,
super
::
interprocedural_fixpoint
::
NodeValue
::
Value
(
State
::
new
(
super
::
interprocedural_fixpoint
_generic
::
NodeValue
::
Value
(
State
::
new
(
&
project
.stack_pointer_register
,
&
project
.stack_pointer_register
,
sub_tid
,
sub_tid
,
)),
)),
...
@@ -363,9 +365,10 @@ impl<'a> PointerInference<'a> {
...
@@ -363,9 +365,10 @@ impl<'a> PointerInference<'a> {
}
}
Node
::
CallReturn
{
call
,
return_
}
=>
{
Node
::
CallReturn
{
call
,
return_
}
=>
{
let
(
call_state
,
return_state
)
=
match
node_value
{
let
(
call_state
,
return_state
)
=
match
node_value
{
NodeValue
::
CallReturnCombinator
{
call
,
return_
}
=>
{
NodeValue
::
CallFlowCombinator
{
(
call
.is_some
(),
return_
.is_some
())
call_stub
,
}
interprocedural_flow
,
}
=>
(
call_stub
.is_some
(),
interprocedural_flow
.is_some
()),
_
=>
panic!
(),
_
=>
panic!
(),
};
};
println!
(
println!
(
...
...
cwe_checker_rs/src/checkers/cwe_476.rs
View file @
809b7ca8
...
@@ -36,10 +36,10 @@
...
@@ -36,10 +36,10 @@
//! - For functions with more than one return value we do not distinguish between
//! - For functions with more than one return value we do not distinguish between
//! the return values.
//! the return values.
use
crate
::
analysis
::
forward_interprocedural_fixpoint
::
create_computation
;
use
crate
::
analysis
::
forward_interprocedural_fixpoint
::
Context
as
_
;
use
crate
::
analysis
::
graph
::{
Edge
,
Node
};
use
crate
::
analysis
::
graph
::{
Edge
,
Node
};
use
crate
::
analysis
::
interprocedural_fixpoint
::
Computation
;
use
crate
::
analysis
::
interprocedural_fixpoint_generic
::
NodeValue
;
use
crate
::
analysis
::
interprocedural_fixpoint
::
Context
as
_
;
use
crate
::
analysis
::
interprocedural_fixpoint
::
NodeValue
;
use
crate
::
intermediate_representation
::
*
;
use
crate
::
intermediate_representation
::
*
;
use
crate
::
prelude
::
*
;
use
crate
::
prelude
::
*
;
use
crate
::
utils
::
log
::{
CweWarning
,
LogMessage
};
use
crate
::
utils
::
log
::{
CweWarning
,
LogMessage
};
...
@@ -102,7 +102,7 @@ pub fn check_cwe(
...
@@ -102,7 +102,7 @@ pub fn check_cwe(
Some
(
NodeValue
::
Value
(
val
))
=>
Some
(
val
.clone
()),
Some
(
NodeValue
::
Value
(
val
))
=>
Some
(
val
.clone
()),
_
=>
None
,
_
=>
None
,
};
};
let
mut
computation
=
Computation
::
new
(
context
,
None
);
let
mut
computation
=
create_computation
(
context
,
None
);
computation
.set_node_value
(
computation
.set_node_value
(
node
,
node
,
NodeValue
::
Value
(
State
::
new
(
NodeValue
::
Value
(
State
::
new
(
...
...
cwe_checker_rs/src/checkers/cwe_476/context.rs
View file @
809b7ca8
...
@@ -2,9 +2,9 @@ use super::State;
...
@@ -2,9 +2,9 @@ use super::State;
use
super
::
Taint
;
use
super
::
Taint
;
use
super
::
CWE_MODULE
;
use
super
::
CWE_MODULE
;
use
crate
::
abstract_domain
::
AbstractDomain
;
use
crate
::
abstract_domain
::
AbstractDomain
;
use
crate
::
analysis
::
forward_interprocedural_fixpoint
::
Context
as
_
;
use
crate
::
analysis
::
graph
::{
Graph
,
Node
};
use
crate
::
analysis
::
graph
::{
Graph
,
Node
};
use
crate
::
analysis
::
interprocedural_fixpoint
::
Context
as
_
;
use
crate
::
analysis
::
interprocedural_fixpoint_generic
::
NodeValue
;
use
crate
::
analysis
::
interprocedural_fixpoint
::
NodeValue
;
use
crate
::
analysis
::
pointer_inference
::
PointerInference
as
PointerInferenceComputation
;
use
crate
::
analysis
::
pointer_inference
::
PointerInference
as
PointerInferenceComputation
;
use
crate
::
analysis
::
pointer_inference
::
State
as
PointerInferenceState
;
use
crate
::
analysis
::
pointer_inference
::
State
as
PointerInferenceState
;
use
crate
::
intermediate_representation
::
*
;
use
crate
::
intermediate_representation
::
*
;
...
@@ -251,7 +251,7 @@ impl<'a> Context<'a> {
...
@@ -251,7 +251,7 @@ impl<'a> Context<'a> {
}
}
}
}
impl
<
'a
>
crate
::
analysis
::
interprocedural_fixpoint
::
Context
<
'a
>
for
Context
<
'a
>
{
impl
<
'a
>
crate
::
analysis
::
forward_
interprocedural_fixpoint
::
Context
<
'a
>
for
Context
<
'a
>
{
type
Value
=
State
;
type
Value
=
State
;
/// Get the underlying graph of the fixpoint computation
/// Get the underlying graph of the fixpoint computation
...
...
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