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
0d2777b0
Unverified
Commit
0d2777b0
authored
Jul 30, 2020
by
Enkelmann
Committed by
GitHub
Jul 30, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Clippy and Rust fmt to CI-pipeline (#75)
parent
7e992eea
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
118 additions
and
200 deletions
+118
-200
.travis_run_tests.sh
.travis_run_tests.sh
+4
-1
Makefile
Makefile
+4
-0
Cargo.toml
cwe_checker_rs/Cargo.toml
+1
-0
graph.rs
cwe_checker_rs/src/analysis/graph.rs
+10
-15
interprocedural_fixpoint.rs
cwe_checker_rs/src/analysis/interprocedural_fixpoint.rs
+3
-3
mem_region.rs
cwe_checker_rs/src/analysis/mem_region.rs
+10
-12
context.rs
cwe_checker_rs/src/analysis/pointer_inference/context.rs
+11
-14
data.rs
cwe_checker_rs/src/analysis/pointer_inference/data.rs
+1
-1
identifier.rs
cwe_checker_rs/src/analysis/pointer_inference/identifier.rs
+6
-7
mod.rs
cwe_checker_rs/src/analysis/pointer_inference/mod.rs
+8
-13
object.rs
cwe_checker_rs/src/analysis/pointer_inference/object.rs
+5
-7
object_list.rs
cwe_checker_rs/src/analysis/pointer_inference/object_list.rs
+18
-21
state.rs
cwe_checker_rs/src/analysis/pointer_inference/state.rs
+13
-14
analysis.rs
cwe_checker_rs/src/ffi/analysis.rs
+4
-4
serde.rs
cwe_checker_rs/src/ffi/serde.rs
+19
-23
symbol.rs
cwe_checker_rs/src/term/symbol.rs
+1
-1
fast_cmp_arc.rs
cwe_checker_rs/src/utils/fast_cmp_arc.rs
+0
-63
mod.rs
cwe_checker_rs/src/utils/mod.rs
+0
-1
No files found.
.travis_run_tests.sh
View file @
0d2777b0
#!/bin/bash
docker run
--rm
-t
cwe-checker cargo
test
&&
docker run
--rm
-t
cwe-checker dune runtest
&&
pytest
docker run
--rm
-t
cwe-checker make codestyle-check
\
&&
docker run
--rm
-t
cwe-checker cargo
test
\
&&
docker run
--rm
-t
cwe-checker dune runtest
\
&&
pytest
Makefile
View file @
0d2777b0
...
...
@@ -18,6 +18,10 @@ test:
cd test
/artificial_samples
;
scons
;
cd
../..
pytest
-v
--ignore
=
_build
codestyle-check
:
cargo fmt
--
--check
cargo clippy
--
-D
clippy::all
clean
:
cargo clean
rm
-f
src/libcwe_checker_rs.a
...
...
cwe_checker_rs/Cargo.toml
View file @
0d2777b0
...
...
@@ -14,6 +14,7 @@ petgraph = { version = "0.5", features = ["default", "serde-1"] }
fnv
=
"1.0"
# a faster hash function for small keys like integers
anyhow
=
"1.0"
# for easy error types
crossbeam-channel
=
"0.4"
derive_more
=
"0.99"
[lib]
name
=
"cwe_checker_rs"
...
...
cwe_checker_rs/src/analysis/graph.rs
View file @
0d2777b0
...
...
@@ -95,7 +95,7 @@ impl<'a> GraphBuilder<'a> {
/// add all subs to the jump targets so that call instructions can be linked to the starting block of the corresponding sub.
fn
add_subs_to_jump_targets
(
&
mut
self
)
{
for
sub
in
self
.program.term.subs
.iter
()
{
if
sub
.term.blocks
.len
()
>
0
{
if
!
sub
.term.blocks
.is_empty
()
{
let
start_block
=
&
sub
.term.blocks
[
0
];
let
target_index
=
self
.jump_targets
[
&
start_block
.tid
];
self
.jump_targets
.insert
(
sub
.tid
.clone
(),
target_index
);
...
...
@@ -140,7 +140,7 @@ impl<'a> GraphBuilder<'a> {
self
.return_addresses
.entry
(
target_tid
.clone
())
.and_modify
(|
vec
|
vec
.push
((
source
,
return_index
)))
.or_insert
(
vec!
[(
source
,
return_index
)]);
.or_insert
_with
(||
vec!
[(
source
,
return_index
)]);
}
// TODO: Non-returning calls and tail calls both have no return target in BAP.
// Thus we need to distinguish them somehow to correctly handle tail calls.
...
...
@@ -189,8 +189,7 @@ impl<'a> GraphBuilder<'a> {
.term
.jmps
.iter
()
.filter
(|
jump
|
matches!
(
jump
.term.kind
,
JmpKind
::
Call
(
_
)))
.next
()
.find
(|
jump
|
matches!
(
jump
.term.kind
,
JmpKind
::
Call
(
_
)))
.unwrap
();
let
cr_combine_node
=
self
.graph
.add_node
(
Node
::
CallReturn
(
call_block
));
self
.graph
...
...
@@ -210,8 +209,7 @@ impl<'a> GraphBuilder<'a> {
.term
.jmps
.iter
()
.find
(|
jmp
|
matches!
(
jmp
.term.kind
,
JmpKind
::
Return
(
_
)))
.is_some
()
.any
(|
jmp
|
matches!
(
jmp
.term.kind
,
JmpKind
::
Return
(
_
)))
{
let
return_from_node
=
self
.jump_targets
[
&
block
.tid
]
.
1
;
self
.add_call_return_node_and_edges
(
sub
,
return_from_node
);
...
...
@@ -242,7 +240,7 @@ impl<'a> GraphBuilder<'a> {
/// This function builds the interprocedural control flow graph for a program term.
pub
fn
get_program_cfg
(
program
:
&
Term
<
Program
>
,
extern_subs
:
HashSet
<
Tid
>
)
->
Graph
{
let
builder
=
GraphBuilder
::
new
(
program
,
extern_subs
);
return
builder
.build
();
builder
.build
()
}
/// For a given set of block TIDs generate a map from the TIDs to the indices of the BlkStart and BlkEnd nodes
...
...
@@ -255,17 +253,14 @@ pub fn get_indices_of_block_nodes<'a, I: Iterator<Item = &'a Tid>>(
let
mut
tid_to_indices_map
=
HashMap
::
new
();
for
node_index
in
graph
.node_indices
()
{
if
let
Some
(
tid
)
=
tids
.get
(
&
graph
[
node_index
]
.get_block
()
.tid
)
{
match
graph
[
node_index
]
{
Node
::
BlkStart
(
_block_term
)
=>
{
let
start_index
=
node_index
;
let
end_index
=
graph
.neighbors
(
start_index
)
.next
()
.unwrap
();
tid_to_indices_map
.insert
(
tid
.clone
(),
(
start_index
,
end_index
));
}
_
=>
(),
if
let
Node
::
BlkStart
(
_block_term
)
=
graph
[
node_index
]
{
let
start_index
=
node_index
;
let
end_index
=
graph
.neighbors
(
start_index
)
.next
()
.unwrap
();
tid_to_indices_map
.insert
(
tid
.clone
(),
(
start_index
,
end_index
));
}
}
}
return
tid_to_indices_map
;
tid_to_indices_map
}
#[cfg(test)]
...
...
cwe_checker_rs/src/analysis/interprocedural_fixpoint.rs
View file @
0d2777b0
...
...
@@ -172,11 +172,11 @@ impl<'a, T: Problem<'a>> GeneralFPProblem for GeneralizedProblem<'a, T> {
Edge
::
ExternCallStub
(
call
)
=>
self
.problem
.update_call_stub
(
node_value
.unwrap_value
(),
call
)
.map
(
|
val
|
NodeValue
::
Value
(
val
)
),
.map
(
NodeValue
::
Value
),
Edge
::
Jump
(
jump
,
untaken_conditional
)
=>
self
.problem
.update_jump
(
node_value
.unwrap_value
(),
jump
,
*
untaken_conditional
)
.map
(
|
val
|
NodeValue
::
Value
(
val
)
),
.map
(
NodeValue
::
Value
),
}
}
}
...
...
@@ -192,7 +192,7 @@ impl<'a, T: Problem<'a>> Computation<'a, T> {
let
generalized_problem
=
GeneralizedProblem
::
new
(
problem
);
let
computation
=
super
::
fixpoint
::
Computation
::
new
(
generalized_problem
,
default_value
.map
(
|
val
|
NodeValue
::
Value
(
val
)
),
default_value
.map
(
NodeValue
::
Value
),
);
Computation
{
generalized_computation
:
computation
,
...
...
cwe_checker_rs/src/analysis/mem_region.rs
View file @
0d2777b0
...
...
@@ -21,8 +21,10 @@ Implementation needs is_top() to be a member function of the ValueDomain trait.
use
super
::
abstract_domain
::
*
;
use
crate
::
bil
::{
BitSize
,
Bitvector
};
use
apint
::{
Int
,
Width
};
use
derive_more
::
Deref
;
use
serde
::{
Deserialize
,
Serialize
};
use
std
::
collections
::
BTreeMap
;
use
std
::
ops
::
DerefMut
;
use
std
::
sync
::
Arc
;
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
...
...
@@ -31,21 +33,17 @@ struct Element<T> {
value
:
T
,
}
#[derive(Serialize,
Deserialize,
Debug,
Hash,
Clone)]
#[derive(Serialize,
Deserialize,
Debug,
Hash,
Clone,
PartialEq,
Eq,
Deref)]
#[deref(forward)]
pub
struct
MemRegion
<
T
:
AbstractDomain
+
ValueDomain
+
std
::
fmt
::
Debug
>
(
Arc
<
MemRegionData
<
T
>>
);
impl
<
T
:
AbstractDomain
+
ValueDomain
+
std
::
fmt
::
Debug
>
PartialEq
for
MemRegion
<
T
>
{
fn
eq
(
&
self
,
other
:
&
Self
)
->
bool
{
if
Arc
::
ptr_eq
(
&
self
.
0
,
&
other
.
0
)
{
true
}
else
{
self
.
0
==
other
.
0
}
impl
<
T
:
AbstractDomain
+
ValueDomain
+
std
::
fmt
::
Debug
>
DerefMut
for
MemRegion
<
T
>
{
fn
deref_mut
(
&
mut
self
)
->
&
mut
MemRegionData
<
T
>
{
Arc
::
make_mut
(
&
mut
self
.
0
)
}
}
impl
<
T
:
AbstractDomain
+
ValueDomain
+
std
::
fmt
::
Debug
>
Eq
for
MemRegion
<
T
>
{}
// TODO: most of the functions in this impl block should be moved to MemRegionData (or removed, if they are only thin wrappers).
impl
<
T
:
AbstractDomain
+
ValueDomain
+
std
::
fmt
::
Debug
>
MemRegion
<
T
>
{
pub
fn
new
(
address_bitsize
:
BitSize
)
->
Self
{
MemRegion
(
Arc
::
new
(
MemRegionData
::
new
(
address_bitsize
)))
...
...
@@ -90,7 +88,7 @@ impl<T: AbstractDomain + ValueDomain + std::fmt::Debug> MemRegion<T> {
/// An abstract domain representing a continuous region of memory. See the module level description for more.
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
struct
MemRegionData
<
T
:
AbstractDomain
+
ValueDomain
+
std
::
fmt
::
Debug
>
{
pub
struct
MemRegionData
<
T
:
AbstractDomain
+
ValueDomain
+
std
::
fmt
::
Debug
>
{
address_bitsize
:
BitSize
,
values
:
BTreeMap
<
i64
,
T
>
,
}
...
...
@@ -162,7 +160,7 @@ impl<T: AbstractDomain + ValueDomain + std::fmt::Debug> MemRegionData<T> {
}
}
let
bitsize
=
8
*
size
as
u16
;
return
T
::
new_top
(
bitsize
);
T
::
new_top
(
bitsize
)
}
/// Remove all elements intersecting the provided interval.
...
...
cwe_checker_rs/src/analysis/pointer_inference/context.rs
View file @
0d2777b0
...
...
@@ -166,7 +166,6 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
}
else
{
panic!
(
"Malformed control flow graph: Encountered call edge with a non-call jump term."
)
};
let
stack_offset_domain
=
self
.get_current_stack_offset
(
state
);
if
let
Label
::
Direct
(
ref
callee_tid
)
=
call
.target
{
let
callee_stack_id
=
AbstractIdentifier
::
new
(
...
...
@@ -177,7 +176,7 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
call_term
.tid
.clone
(),
AbstractLocation
::
from_var
(
&
self
.project.stack_pointer_register
)
.unwrap
(),
);
let
stack_offset_adjustment
=
s
tack_offset_domain
.clone
(
);
let
stack_offset_adjustment
=
s
elf
.get_current_stack_offset
(
state
);
let
address_bitsize
=
self
.project.stack_pointer_register
.bitsize
()
.unwrap
();
let
mut
callee_state
=
state
.clone
();
...
...
@@ -214,9 +213,7 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
);
// set the list of caller stack ids to only this caller id
callee_state
.caller_stack_ids
=
BTreeSet
::
new
();
callee_state
.caller_stack_ids
.insert
(
new_caller_stack_id
.clone
());
callee_state
.caller_stack_ids
.insert
(
new_caller_stack_id
);
// Remove non-referenced objects and objects, only the caller knows about, from the state.
callee_state
.ids_known_to_caller
=
BTreeSet
::
new
();
callee_state
.remove_unreferenced_objects
();
...
...
@@ -224,7 +221,7 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
callee_state
.ids_known_to_caller
=
callee_state
.memory
.get_all_object_ids
();
callee_state
.ids_known_to_caller
.remove
(
&
callee_stack_id
);
return
callee_state
;
callee_state
}
else
{
panic!
(
"Indirect call edges not yet supported."
)
// TODO: Support indirect call edges!
...
...
@@ -277,7 +274,7 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
state_after_return
.merge_callee_stack_to_caller_stack
(
callee_stack_id
,
original_caller_stack_id
,
&
(
-
stack_offset_on_call
.clone
()
),
&
(
-
stack_offset_on_call
),
);
state_after_return
.stack_id
=
original_caller_stack_id
.clone
();
state_after_return
.caller_stack_ids
=
state_before_call
.caller_stack_ids
.clone
();
...
...
@@ -382,11 +379,11 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
new_state
.set_register
(
return_register
,
pointer
.into
()),
Some
(
&
call
.tid
),
);
return
Some
(
new_state
);
Some
(
new_state
)
}
else
{
// We cannot track the new object, since we do not know where to store the pointer to it.
// TODO: Return a diagnostics message to the user here.
return
Some
(
new_state
);
Some
(
new_state
)
}
}
"free"
=>
{
...
...
@@ -412,16 +409,16 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
}
}
// TODO: add diagnostics for else case
new_state
.remove_unreferenced_objects
();
return
Some
(
new_state
);
Some
(
new_state
)
}
else
{
// TODO: add diagnostics message for the user here
return
Some
(
new_state
);
Some
(
new_state
)
}
}
Err
(
err
)
=>
{
// We do not know which memory object to free
self
.log_debug
(
Err
(
err
),
Some
(
&
call
.tid
));
return
Some
(
new_state
);
Some
(
new_state
)
}
}
}
...
...
@@ -431,7 +428,7 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
Some
(
&
call
.tid
),
);
let
mut
possible_referenced_ids
=
BTreeSet
::
new
();
if
extern_symbol
.arguments
.
len
()
==
0
{
if
extern_symbol
.arguments
.
is_empty
()
{
// TODO: We assume here that we do not know the parameters and approximate them by all parameter registers.
// This approximation is wrong if the function is known but has neither parameters nor return values.
// We need to somehow distinguish these two cases.
...
...
@@ -465,7 +462,7 @@ impl<'a> crate::analysis::interprocedural_fixpoint::Problem<'a> for Context<'a>
.memory
.mark_mem_object_as_untracked
(
id
,
&
possible_referenced_ids
);
}
return
Some
(
new_state
);
Some
(
new_state
)
}
}
}
else
{
...
...
cwe_checker_rs/src/analysis/pointer_inference/data.rs
View file @
0d2777b0
...
...
@@ -54,7 +54,7 @@ impl Data {
}
})
.collect
();
if
remaining_targets
.
len
()
==
0
{
if
remaining_targets
.
is_empty
()
{
*
self
=
Data
::
new_top
(
self
.bitsize
());
}
else
{
*
self
=
Data
::
Pointer
(
PointerDomain
::
with_targets
(
remaining_targets
));
...
...
cwe_checker_rs/src/analysis/pointer_inference/identifier.rs
View file @
0d2777b0
use
crate
::
bil
::
variable
::
*
;
use
crate
::
prelude
::
*
;
use
crate
::
utils
::
fast_cmp_arc
::
FastCmpArc
;
use
derive_more
::
Deref
;
use
std
::
sync
::
Arc
;
// TODO: Right now abstract locations are used as giving the location where a pointer to an object is located.
...
...
@@ -14,8 +14,10 @@ use std::sync::Arc;
/// The time identifier is given by a `Tid`.
/// If it is the Tid of a basic block, then it describes the point in time *before* execution of the first instruction in the block.
/// If it is the Tid of a Def or Jmp, then it describes the point in time *after* the execution of the Def or Jmp.
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
PartialOrd,
Ord)]
pub
struct
AbstractIdentifier
(
FastCmpArc
<
AbstractIdentifierData
>
);
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
PartialOrd,
Ord,
Deref)]
#[deref(forward)]
pub
struct
AbstractIdentifier
(
Arc
<
AbstractIdentifierData
>
);
/// The data contained in an abstract identifier
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
PartialOrd,
Ord)]
...
...
@@ -27,10 +29,7 @@ pub struct AbstractIdentifierData {
impl
AbstractIdentifier
{
/// create a new abstract identifier
pub
fn
new
(
time
:
Tid
,
location
:
AbstractLocation
)
->
AbstractIdentifier
{
AbstractIdentifier
(
FastCmpArc
(
Arc
::
new
(
AbstractIdentifierData
{
time
,
location
,
})))
AbstractIdentifier
(
Arc
::
new
(
AbstractIdentifierData
{
time
,
location
}))
}
}
...
...
cwe_checker_rs/src/analysis/pointer_inference/mod.rs
View file @
0d2777b0
...
...
@@ -55,7 +55,7 @@ impl<'a> PointerInference<'a> {
if
let
Some
((
start_node_index
,
_end_node_index
))
=
tid_to_graph_indices_map
.get
(
&
block_tid
)
{
Some
((
sub_tid
.clone
(),
start_node_index
.clone
()
))
Some
((
sub_tid
.clone
(),
*
start_node_index
))
}
else
{
None
}
...
...
@@ -147,8 +147,7 @@ impl<'a> PointerInference<'a> {
.term
.extern_symbols
.iter
()
.find
(|
symbol
|
symbol
.tid
==
sub
.tid
)
.is_some
()
.any
(|
symbol
|
symbol
.tid
==
sub
.tid
)
{
continue
;
// We ignore functions marked as extern symbols.
}
...
...
@@ -160,19 +159,15 @@ impl<'a> PointerInference<'a> {
let
mut
new_entry_points
=
Vec
::
new
();
for
(
node_id
,
node
)
in
graph
.node_references
()
{
if
let
Node
::
BlkStart
(
block
)
=
node
{
if
start_block_to_sub_map
.get
(
&
block
.tid
)
.is_some
()
&&
self
.computation
.get_node_value
(
node_id
)
.is_none
()
{
if
only_cfg_roots
if
!
(
start_block_to_sub_map
.get
(
&
block
.tid
)
.is_none
()
||
self
.computation
.get_node_value
(
node_id
)
.is_some
()
||
only_cfg_roots
&&
graph
.neighbors_directed
(
node_id
,
Direction
::
Incoming
)
.next
()
.is_none
()
{
new_entry_points
.push
(
node_id
);
}
else
if
!
only_cfg_roots
{
new_entry_points
.push
(
node_id
);
}
.is_some
())
{
new_entry_points
.push
(
node_id
);
}
}
}
...
...
cwe_checker_rs/src/analysis/pointer_inference/object.rs
View file @
0d2777b0
...
...
@@ -210,7 +210,7 @@ impl AbstractObjectInfo {
}
else
{
self
.memory
=
MemRegion
::
new
(
self
.memory
.get_address_bitsize
());
}
return
Ok
(());
Ok
(())
}
fn
get_all_possible_pointer_targets
(
&
self
)
->
BTreeSet
<
AbstractIdentifier
>
{
...
...
@@ -222,7 +222,7 @@ impl AbstractObjectInfo {
}
};
}
return
targets
;
targets
}
/// For pointer values replace an abstract identifier with another one and add the offset_adjustment to the pointer offsets.
...
...
@@ -245,11 +245,9 @@ impl AbstractObjectInfo {
pub
fn
set_state
(
&
mut
self
,
new_state
:
Option
<
ObjectState
>
)
{
if
self
.is_unique
{
self
.state
=
new_state
;
}
else
{
if
self
.state
!=
new_state
{
self
.state
=
None
;
}
// else don't change the state
}
}
else
if
self
.state
!=
new_state
{
self
.state
=
None
;
}
// else don't change the state
}
/// Remove the provided IDs from the target lists of all pointers in the memory object.
...
...
cwe_checker_rs/src/analysis/pointer_inference/object_list.rs
View file @
0d2777b0
...
...
@@ -55,7 +55,7 @@ impl AbstractObjectList {
}
}
}
return
false
;
false
}
/// Get the value at a given address.
...
...
@@ -87,7 +87,7 @@ impl AbstractObjectList {
break
;
}
}
merged_value
.ok_or
(
anyhow!
(
"Pointer without targets encountered."
))
merged_value
.ok_or
_else
(||
anyhow!
(
"Pointer without targets encountered."
))
}
}
}
...
...
@@ -102,7 +102,7 @@ impl AbstractObjectList {
for
(
id
,
_offset
)
in
pointer
.iter_targets
()
{
target_object_set
.insert
(
self
.ids
.get
(
id
)
.unwrap
()
.
0
);
}
if
target_object_set
.
len
()
==
0
{
if
target_object_set
.
is_empty
()
{
return
Err
(
anyhow!
(
"Pointer without targets encountered"
));
}
if
target_object_set
.len
()
==
1
{
...
...
@@ -170,7 +170,7 @@ impl AbstractObjectList {
let
mut
merged_objects
=
self
.objects
.clone
();
let
mut
merged_ids
=
self
.ids
.clone
();
for
(
other_id
,
(
other_index
,
other_offset
))
in
other
.ids
.iter
()
{
if
let
Some
((
index
,
offset
))
=
merged_ids
.get
(
&
other_id
)
.clone
()
{
if
let
Some
((
index
,
offset
))
=
merged_ids
.get
(
&
other_id
)
{
let
(
index
,
offset
)
=
(
*
index
,
offset
.clone
());
merged_ids
.insert
(
other_id
.clone
(),
(
index
,
offset
.merge
(
&
other_offset
)));
if
index
<
self
.objects
.len
()
{
...
...
@@ -322,24 +322,22 @@ impl AbstractObjectList {
}
Arc
::
make_mut
(
object
)
.set_state
(
None
);
}
}
else
{
if
let
Some
(
id
)
=
ids
.iter
()
.next
()
{
let
object
=
&
mut
self
.objects
[
self
.ids
[
&
id
]
.
0
];
if
let
AbstractObject
::
Memory
(
tracked_mem
)
=
Arc
::
deref
(
object
)
{
if
tracked_mem
.state
!=
Some
(
ObjectState
::
Alive
)
{
// Possible double free detected
// TODO: Check rate of false positives.
// If too high, only mark those with explicit dangling state.
possible_double_free_ids
.push
(
id
.clone
());
}
}
else
if
let
Some
(
id
)
=
ids
.iter
()
.next
()
{
let
object
=
&
mut
self
.objects
[
self
.ids
[
&
id
]
.
0
];
if
let
AbstractObject
::
Memory
(
tracked_mem
)
=
Arc
::
deref
(
object
)
{
if
tracked_mem
.state
!=
Some
(
ObjectState
::
Alive
)
{
// Possible double free detected
// TODO: Check rate of false positives.
// If too high, only mark those with explicit dangling state.
possible_double_free_ids
.push
(
id
.clone
());
}
Arc
::
make_mut
(
object
)
.set_state
(
Some
(
ObjectState
::
Dangling
));
}
Arc
::
make_mut
(
object
)
.set_state
(
Some
(
ObjectState
::
Dangling
));
}
if
possible_double_free_ids
.is_empty
()
{
return
Ok
(());
Ok
(())
}
else
{
return
Err
(
possible_double_free_ids
);
Err
(
possible_double_free_ids
)
}
}
...
...
@@ -380,11 +378,10 @@ impl AbstractObjectList {
}
}
let
mut
old_to_new_index_map
:
BTreeMap
<
usize
,
usize
>
=
BTreeMap
::
new
();
for
old_index
in
0
..
other_object_list
.objects
.len
()
{
if
objects_already_known
[
old_index
]
==
false
{
for
(
old_index
,
old_object
)
in
other_object_list
.objects
.iter
()
.enumerate
()
{
if
!
objects_already_known
[
old_index
]
{
old_to_new_index_map
.insert
(
old_index
,
self
.objects
.len
());
self
.objects
.push
(
other_object_list
.objects
[
old_index
]
.clone
());
self
.objects
.push
(
old_object
.clone
());
}
}
for
(
id
,
(
old_index
,
offset
))
in
other_object_list
.ids
.iter
()
{
...
...
cwe_checker_rs/src/analysis/pointer_inference/state.rs
View file @
0d2777b0
...
...
@@ -98,7 +98,7 @@ impl State {
}
Ok
(())
}
else
{
return
Err
(
anyhow!
(
"Variable is not a register type"
));
Err
(
anyhow!
(
"Variable is not a register type"
))
}
}
...
...
@@ -138,8 +138,7 @@ impl State {
.filter_map
(|(
register
,
value
)|
{
if
callee_saved_register_names
.iter
()
.find
(|
reg_name
|
**
reg_name
==
register
.name
)
.is_some
()
.any
(|
reg_name
|
**
reg_name
==
register
.name
)
{
Some
((
register
.clone
(),
value
.clone
()))
}
else
{
...
...
@@ -284,11 +283,11 @@ impl State {
// A more precise solution would write to every caller memory region separately,
// but would also need to check first whether the target memory region is unique or not.
self
.memory
.set_value
(
pointer
,
value
.clone
())
?
;
return
Ok
(());
Ok
(())
}
else
{
// TODO: Implement recognition of stores to global memory.
// Needs implementation of reads from global data first.
return
Err
(
anyhow!
(
"Memory write to non-pointer data"
));
Err
(
anyhow!
(
"Memory write to non-pointer data"
))
}
}
...
...
@@ -313,10 +312,10 @@ impl State {
size
,
}
=
store_exp
{
let
data
=
self
.eval
(
value
)
.unwrap_or
(
Data
::
new_top
(
*
size
));
let
data
=
self
.eval
(
value
)
.unwrap_or
_else
(|
_
|
Data
::
new_top
(
*
size
));
assert_eq!
(
data
.bitsize
(),
*
size
);
// TODO: At the moment, both memory and endianness are ignored. Change that!
return
self
.write_to_address
(
address
,
&
data
);
self
.write_to_address
(
address
,
&
data
)
}
else
{
panic!
(
"Expected store expression"
)
}
...
...
@@ -343,7 +342,7 @@ impl State {
}
}
// We only return the last error encountered.
re
turn
result_log
;
re
sult_log
}
/// merge two states
...
...
@@ -353,7 +352,7 @@ impl State {
for
(
register
,
other_value
)
in
other
.register
.iter
()
{
if
let
Some
(
value
)
=
self
.register
.get
(
register
)
{
let
merged_value
=
value
.merge
(
other_value
);
if
merged_value
.is_top
()
==
false
{
if
!
merged_value
.is_top
()
{
// We only have to keep non-top elements.
merged_register
.insert
(
register
.clone
(),
merged_value
);
}
...
...
@@ -393,7 +392,7 @@ impl State {
match
offset
{
BitvectorDomain
::
Value
(
offset_val
)
=>
{
if
offset_val
.try_to_i64
()
.unwrap
()
>=
0
&&
self
.caller_stack_ids
.len
()
>
0
&&
!
self
.caller_stack_ids
.is_empty
()
{
for
caller_id
in
self
.caller_stack_ids
.iter
()
{
new_targets
.add_target
(
caller_id
.clone
(),
offset
.clone
());
...
...
@@ -415,9 +414,9 @@ impl State {
new_targets
.add_target
(
id
.clone
(),
offset
.clone
());
}
}
return
Data
::
Pointer
(
new_targets
);
Data
::
Pointer
(
new_targets
)
}
else
{
return
address
.clone
();
address
.clone
()
}
}
...
...
@@ -486,7 +485,7 @@ impl State {
}
}
}
return
ids
;
ids
}
/// Merge the callee stack with the caller stack.
...
...
@@ -531,7 +530,7 @@ impl State {
.register
.clone
()
.into_iter
()
.filter
(|(
register
,
_value
)|
register
.is_temp
==
false
)
.filter
(|(
register
,
_value
)|
!
register
.is_temp
)
.collect
();
}
...
...
cwe_checker_rs/src/ffi/analysis.rs
View file @
0d2777b0
...
...
@@ -15,12 +15,12 @@ fn run_pointer_inference(program_jsonbuilder_val: ocaml::Value) -> (Vec<CweWarni
}
caml!
(
rs_run_pointer_inference
(
program_jsonbuilder_val
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
let
cwe_warnings_and_log
=
run_pointer_inference
(
program_jsonbuilder_val
);
let
cwe_warnings_and_log_json
=
serde_json
::
to_string
(
&
cwe_warnings_and_log
)
.unwrap
();
let
ocaml_string
=
ocaml
::
Str
::
from
(
&
cwe_warnings_and_log_json
as
&
str
);
ocaml
::
Value
::
from
(
ocaml_string
)
})
;
})
});
fn
run_pointer_inference_and_print_debug
(
program_jsonbuilder_val
:
ocaml
::
Value
)
{
...
...
@@ -33,8 +33,8 @@ fn run_pointer_inference_and_print_debug(program_jsonbuilder_val: ocaml::Value)
}
caml!
(
rs_run_pointer_inference_and_print_debug
(
program_jsonbuilder_val
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
run_pointer_inference_and_print_debug
(
program_jsonbuilder_val
);
ocaml
::
Value
::
unit
()
})
;
})
});
cwe_checker_rs/src/ffi/serde.rs
View file @
0d2777b0
...
...
@@ -73,10 +73,10 @@ impl From<&JsonBuilder> for serde_json::Value {
}
caml!
(
rs_finalize_json_builder
(
builder_val
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
JsonBuilder
::
ocaml_finalize
(
builder_val
);
ocaml
::
Value
::
unit
()
})
;
})
});
/// Build JsonBuilder::Null as Ocaml value
...
...
@@ -85,9 +85,9 @@ fn build_serde_null() -> ocaml::Value {
}
caml!
(
rs_build_serde_null
(
_unit
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
build_serde_null
()
})
;
})
});
/// Build JsonBuilder::Bool as Ocaml value
...
...
@@ -97,9 +97,9 @@ fn build_serde_bool(bool_val: ocaml::Value) -> ocaml::Value {
}
caml!
(
rs_build_serde_bool
(
bool_val
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
build_serde_bool
(
bool_val
)
})
;
})
});
/// Build JsonBuilder::Number as Ocaml value
...
...
@@ -109,9 +109,9 @@ fn build_serde_number(num: ocaml::Value) -> ocaml::Value {
}
caml!
(
rs_build_serde_number
(
number
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
build_serde_number
(
number
)
})
;
})
});
/// Build JsonBuilder::Object representing a bitvector from a string generated by `Bitvector.to_string` in Ocaml
...
...
@@ -127,7 +127,7 @@ fn build_serde_bitvector(bitvector_string_val: ocaml::Value) -> ocaml::Value {
if
number_slice
.starts_with
(
"0x"
)
{
number_slice
=
&
number_slice
[
2
..
];
}
while
number_slice
.len
()
>
0
{
while
!
number_slice
.is_empty
()
{
if
number_slice
.len
()
>
16
{
let
digit
=
u64
::
from_str_radix
(
&
number_slice
[(
number_slice
.len
()
-
16
)
..
],
16
)
.expect
(
"Bitvector value parsing failed"
);
...
...
@@ -151,18 +151,14 @@ fn build_serde_bitvector(bitvector_string_val: ocaml::Value) -> ocaml::Value {
(
"digits"
.to_string
(),
Rc
::
new
(
JsonBuilder
::
Array
(
num_list
))),
(
"width"
.to_string
(),
Rc
::
new
(
JsonBuilder
::
Array
(
width_list
))),
]);
// TODO: remove deserialization check
let
check_serde
=
serde_json
::
to_string
(
&
serde_json
::
Value
::
from
(
&
result
))
.unwrap
();
let
_bitv
:
apint
::
ApInt
=
serde_json
::
from_str
(
&
check_serde
)
.expect
(
&
format!
(
"Invalid value generated: {}"
,
check_serde
));
result
.to_ocaml
()
}
caml!
(
rs_build_serde_bitvector
(
bitvector_string
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
build_serde_bitvector
(
bitvector_string
)
})
;
})
});
/// Build JsonBuilder::String as Ocaml value
...
...
@@ -172,9 +168,9 @@ fn build_serde_string(string_val: ocaml::Value) -> ocaml::Value {
}
caml!
(
rs_build_serde_string
(
string_val
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
build_serde_string
(
string_val
)
})
;
})
});
/// Build JsonBuilder::Array as Ocaml value from an Ocaml list
...
...
@@ -189,9 +185,9 @@ fn build_serde_array_from_list(list_val: ocaml::Value) -> ocaml::Value {
}
caml!
(
rs_build_serde_array_from_list
(
list_val
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
build_serde_array_from_list
(
list_val
)
})
;
})
});
/// Build JsonBuilder::Object as Ocaml value from an Ocaml list of tuples
...
...
@@ -217,9 +213,9 @@ fn build_serde_object(tuple_list_val: ocaml::Value) -> ocaml::Value {
}
caml!
(
rs_build_serde_object
(
tuple_list_val
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
build_serde_object
(
tuple_list_val
)
})
;
})
});
/// Get the Json string corresponding to a JsonBuilder object and return it as an Ocaml value.
...
...
@@ -230,7 +226,7 @@ fn get_json_string(builder_val: ocaml::Value) -> ocaml::Value {
}
caml!
(
rs_convert_json_to_string
(
builder_val
)
{
return
failwith_on_panic
(
||
{
failwith_on_panic
(
||
{
get_json_string
(
builder_val
)
})
;
})
});
cwe_checker_rs/src/term/symbol.rs
View file @
0d2777b0
...
...
@@ -29,7 +29,7 @@ impl ExternSymbol {
}
match
&
return_args
[
0
]
.location
{
Expression
::
Var
(
var
)
=>
Ok
(
var
),
_
=>
Err
(
anyhow!
(
"Return location is not a register"
))
?
,
_
=>
Err
(
anyhow!
(
"Return location is not a register"
)),
}
}
...
...
cwe_checker_rs/src/utils/fast_cmp_arc.rs
deleted
100644 → 0
View file @
7e992eea
use
crate
::
analysis
::
abstract_domain
::
AbstractDomain
;
use
crate
::
prelude
::
*
;
use
std
::
ops
::{
Deref
,
DerefMut
};
use
std
::
sync
::
Arc
;
// TODO: This is a helper not only for abstract domains! It needs its own source file!
#[derive(Serialize,
Deserialize,
Debug,
Hash,
Clone)]
pub
struct
FastCmpArc
<
T
>
(
pub
Arc
<
T
>
);
impl
<
T
:
PartialEq
+
Eq
>
PartialEq
for
FastCmpArc
<
T
>
{
fn
eq
(
&
self
,
other
:
&
Self
)
->
bool
{
if
Arc
::
ptr_eq
(
&
self
.
0
,
&
other
.
0
)
{
true
}
else
{
self
.
0
.eq
(
&
other
.
0
)
}
}
}
impl
<
T
:
Eq
>
Eq
for
FastCmpArc
<
T
>
{}
impl
<
T
:
AbstractDomain
+
Clone
>
AbstractDomain
for
FastCmpArc
<
T
>
{
fn
top
(
&
self
)
->
Self
{
FastCmpArc
(
Arc
::
new
(
self
.
0
.top
()))
}
fn
merge
(
&
self
,
other
:
&
Self
)
->
Self
{
if
Arc
::
ptr_eq
(
&
self
.
0
,
&
other
.
0
)
{
self
.clone
()
}
else
{
FastCmpArc
(
Arc
::
new
(
self
.
0
.merge
(
&
other
.
0
)))
}
}
}
impl
<
T
:
PartialOrd
+
Ord
>
PartialOrd
for
FastCmpArc
<
T
>
{
fn
partial_cmp
(
&
self
,
other
:
&
Self
)
->
Option
<
std
::
cmp
::
Ordering
>
{
Some
(
self
.cmp
(
other
))
}
}
impl
<
T
:
PartialOrd
+
Ord
>
Ord
for
FastCmpArc
<
T
>
{
fn
cmp
(
&
self
,
other
:
&
Self
)
->
std
::
cmp
::
Ordering
{
if
Arc
::
ptr_eq
(
&
self
.
0
,
&
other
.
0
)
{
std
::
cmp
::
Ordering
::
Equal
}
else
{
self
.
0
.cmp
(
&
other
.
0
)
}
}
}
impl
<
T
>
Deref
for
FastCmpArc
<
T
>
{
type
Target
=
T
;
fn
deref
(
&
self
)
->
&
T
{
&
self
.
0
}
}
impl
<
T
:
Clone
>
DerefMut
for
FastCmpArc
<
T
>
{
fn
deref_mut
(
&
mut
self
)
->
&
mut
T
{
Arc
::
make_mut
(
&
mut
self
.
0
)
}
}
cwe_checker_rs/src/utils/mod.rs
View file @
0d2777b0
pub
mod
fast_cmp_arc
;
pub
mod
log
;
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