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-gitdep
cwe_checker
Commits
4b6ca3be
Commit
4b6ca3be
authored
4 years ago
by
Enkelmann
Committed by
Enkelmann
4 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support basic blocks that are contained in more than one function.
parent
c585d9de
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
175 additions
and
93 deletions
+175
-93
graph.rs
cwe_checker_rs/src/analysis/graph.rs
+133
-76
interprocedural_fixpoint.rs
cwe_checker_rs/src/analysis/interprocedural_fixpoint.rs
+4
-1
tests.rs
...hecker_rs/src/analysis/pointer_inference/context/tests.rs
+8
-1
mod.rs
cwe_checker_rs/src/analysis/pointer_inference/mod.rs
+16
-14
object_list.rs
cwe_checker_rs/src/analysis/pointer_inference/object_list.rs
+1
-1
term.rs
cwe_checker_rs/src/intermediate_representation/term.rs
+13
-0
No files found.
cwe_checker_rs/src/analysis/graph.rs
View file @
4b6ca3be
...
...
@@ -52,13 +52,18 @@ pub type Graph<'a> = DiGraph<Node<'a>, Edge<'a>>;
/// Each node carries a pointer to its associated block with it.
/// For `CallReturn`nodes the associated blocks are both the callsite block (containing the call instruction)
/// and the returning-from block (containing the return instruction).
///
/// Basic blocks are allowed to be contained in more than one `Sub`.
/// In the control flow graph such basic blocks occur once per subroutine they are contained in.
/// For this reason, the nodes also carry a pointer to the corresponding subroutine with them
/// to allow unambigous node identification.
#[derive(Serialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
pub
enum
Node
<
'a
>
{
BlkStart
(
&
'a
Term
<
Blk
>
),
BlkEnd
(
&
'a
Term
<
Blk
>
),
BlkStart
(
&
'a
Term
<
Blk
>
,
&
'a
Term
<
Sub
>
),
BlkEnd
(
&
'a
Term
<
Blk
>
,
&
'a
Term
<
Sub
>
),
CallReturn
{
call
:
&
'a
Term
<
Blk
>
,
return_
:
&
'a
Term
<
Blk
>
,
call
:
(
&
'a
Term
<
Blk
>
,
&
'a
Term
<
Sub
>
)
,
return_
:
(
&
'a
Term
<
Blk
>
,
&
'a
Term
<
Sub
>
)
,
},
}
...
...
@@ -68,7 +73,7 @@ impl<'a> Node<'a> {
pub
fn
get_block
(
&
self
)
->
&
'a
Term
<
Blk
>
{
use
Node
::
*
;
match
self
{
BlkStart
(
blk
)
|
BlkEnd
(
blk
)
=>
blk
,
BlkStart
(
blk
,
_sub
)
|
BlkEnd
(
blk
,
_sub
)
=>
blk
,
CallReturn
{
..
}
=>
panic!
(
"get_block() is undefined for CallReturn nodes"
),
}
}
...
...
@@ -77,12 +82,16 @@ impl<'a> Node<'a> {
impl
<
'a
>
std
::
fmt
::
Display
for
Node
<
'a
>
{
fn
fmt
(
&
self
,
formatter
:
&
mut
std
::
fmt
::
Formatter
)
->
std
::
fmt
::
Result
{
match
self
{
Self
::
BlkStart
(
block
)
=>
write!
(
formatter
,
"BlkStart @ {}"
,
block
.tid
),
Self
::
BlkEnd
(
block
)
=>
write!
(
formatter
,
"BlkEnd @ {}"
,
block
.tid
),
Self
::
BlkStart
(
block
,
sub
)
=>
{
write!
(
formatter
,
"BlkStart @ {} (sub {})"
,
block
.tid
,
sub
.tid
)
}
Self
::
BlkEnd
(
block
,
sub
)
=>
{
write!
(
formatter
,
"BlkEnd @ {} (sub {})"
,
block
.tid
,
sub
.tid
)
}
Self
::
CallReturn
{
call
,
return_
}
=>
write!
(
formatter
,
"CallReturn @ {} (
caller @ {}
)"
,
return_
.
tid
,
call
.tid
"CallReturn @ {} (
sub {}) (caller @ {} (sub {})
)"
,
return_
.
0
.tid
,
return_
.
1
.tid
,
call
.
0
.tid
,
call
.
1
.tid
),
}
}
...
...
@@ -112,10 +121,16 @@ struct GraphBuilder<'a> {
program
:
&
'a
Term
<
Program
>
,
extern_subs
:
HashSet
<
Tid
>
,
graph
:
Graph
<
'a
>
,
/// Denotes the NodeIndices of possible jump targets
jump_targets
:
HashMap
<
Tid
,
(
NodeIndex
,
NodeIndex
)
>
,
/// Denotes the NodeIndices of possible call targets
call_targets
:
HashMap
<
Tid
,
(
NodeIndex
,
NodeIndex
)
>
,
/// Denotes the NodeIndices of possible intraprocedural jump targets.
/// The keys are of the form (block_tid, sub_tid).
/// The values are of the form (BlkStart-node-index, BlkEnd-node-index).
jump_targets
:
HashMap
<
(
Tid
,
Tid
),
(
NodeIndex
,
NodeIndex
)
>
,
/// for each function the list of return addresses of the corresponding call sites
return_addresses
:
HashMap
<
Tid
,
Vec
<
(
NodeIndex
,
NodeIndex
)
>>
,
/// A list of `BlkEnd` nodes for which outgoing edges still have to be added to the graph.
block_worklist
:
Vec
<
NodeIndex
>
,
}
impl
<
'a
>
GraphBuilder
<
'a
>
{
...
...
@@ -125,35 +140,46 @@ impl<'a> GraphBuilder<'a> {
program
,
extern_subs
,
graph
:
Graph
::
new
(),
call_targets
:
HashMap
::
new
(),
jump_targets
:
HashMap
::
new
(),
return_addresses
:
HashMap
::
new
(),
block_worklist
:
Vec
::
new
(),
}
}
/// add start and end nodes of a block and the connecting edge
fn
add_block
(
&
mut
self
,
block
:
&
'a
Term
<
Blk
>
)
{
let
start
=
self
.graph
.add_node
(
Node
::
BlkStart
(
block
));
let
end
=
self
.graph
.add_node
(
Node
::
BlkEnd
(
block
));
self
.jump_targets
.insert
(
block
.tid
.clone
(),
(
start
,
end
));
/// Add start and end nodes of a block and the connecting edge.
/// Also add the end node to the `block_worklist`.
fn
add_block
(
&
mut
self
,
block
:
&
'a
Term
<
Blk
>
,
sub
:
&
'a
Term
<
Sub
>
)
->
(
NodeIndex
,
NodeIndex
)
{
let
start
=
self
.graph
.add_node
(
Node
::
BlkStart
(
block
,
sub
));
let
end
=
self
.graph
.add_node
(
Node
::
BlkEnd
(
block
,
sub
));
self
.jump_targets
.insert
((
block
.tid
.clone
(),
sub
.tid
.clone
()),
(
start
,
end
));
self
.graph
.add_edge
(
start
,
end
,
Edge
::
Block
);
self
.block_worklist
.push
(
end
);
(
start
,
end
)
}
/// add all blocks of the program to the graph
/// Add all blocks of the program to the graph.
///
/// Each block is only added once,
/// i.e. for blocks contained in more than one function the extra nodes have to be added separately later.
/// The `sub` a block is associated with is the `sub` that the block is contained in in the `program` struct.
fn
add_program_blocks
(
&
mut
self
)
{
let
subs
=
self
.program.term.subs
.iter
();
let
blocks
=
subs
.map
(|
sub
|
sub
.term.blocks
.iter
())
.flatten
();
for
block
in
blocks
{
self
.add_block
(
block
);
for
sub
in
subs
{
for
block
in
sub
.term.blocks
.iter
()
{
self
.add_block
(
block
,
sub
);
}
}
}
/// add all subs to the
jump
targets so that call instructions can be linked to the starting block of the corresponding sub.
/// add all subs to the
call
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
.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
);
let
target_index
=
self
.jump_targets
[
&
(
start_block
.tid
.clone
(),
sub
.tid
.clone
())
];
self
.
call
_targets
.insert
(
sub
.tid
.clone
(),
target_index
);
}
// TODO: Generate Log-Message for Subs without blocks.
}
...
...
@@ -166,38 +192,62 @@ impl<'a> GraphBuilder<'a> {
jump
:
&
'a
Term
<
Jmp
>
,
untaken_conditional
:
Option
<&
'a
Term
<
Jmp
>>
,
)
{
let
sub_term
=
match
self
.graph
[
source
]
{
Node
::
BlkEnd
(
_source_block
,
sub_term
)
=>
sub_term
,
_
=>
panic!
(),
};
match
&
jump
.term
{
Jmp
::
Branch
(
tid
)
|
Jmp
::
CBranch
{
target
:
tid
,
condition
:
_
,
}
=>
{
self
.graph
.add_edge
(
source
,
self
.jump_targets
[
&
tid
]
.
0
,
Edge
::
Jump
(
jump
,
untaken_conditional
),
);
if
let
Some
((
target_node
,
_
))
=
self
.jump_targets
.get
(
&
(
tid
.clone
(),
sub_term
.tid
.clone
()))
{
self
.graph
.add_edge
(
source
,
*
target_node
,
Edge
::
Jump
(
jump
,
untaken_conditional
),
);
}
else
{
let
target_block
=
self
.program.term
.find_block
(
tid
)
.unwrap
();
let
(
target_node
,
_
)
=
self
.add_block
(
target_block
,
sub_term
);
self
.graph
.add_edge
(
source
,
target_node
,
Edge
::
Jump
(
jump
,
untaken_conditional
));
}
}
Jmp
::
BranchInd
(
_
)
=>
(),
// TODO: add handling of indirect edges!
Jmp
::
Call
{
target
,
return_
}
=>
{
// first make sure that the return block exists
let
return_to_node_option
=
if
let
Some
(
return_tid
)
=
return_
{
if
let
Some
((
return_to_node
,
_
))
=
self
.jump_targets
.get
(
&
(
return_tid
.clone
(),
sub_term
.tid
.clone
()))
{
Some
(
*
return_to_node
)
}
else
{
let
return_block
=
self
.program.term
.find_block
(
return_tid
)
.unwrap
();
Some
(
self
.add_block
(
return_block
,
sub_term
)
.
0
)
}
}
else
{
None
};
// now add the call edge
if
self
.extern_subs
.contains
(
target
)
{
if
let
Some
(
return_tid
)
=
return_
{
self
.graph
.add_edge
(
source
,
self
.jump_targets
[
&
return_tid
]
.
0
,
Edge
::
ExternCallStub
(
jump
),
);
if
let
Some
(
return_to_node
)
=
return_to_node_option
{
self
.graph
.add_edge
(
source
,
return_to_node
,
Edge
::
ExternCallStub
(
jump
));
}
}
else
{
if
let
Some
(
target_node
)
=
self
.jump
_targets
.get
(
&
target
)
{
self
.graph
.add_edge
(
source
,
target_node
.
0
,
Edge
::
Call
(
jump
));
if
let
Some
(
(
target_node
,
_
))
=
self
.call
_targets
.get
(
&
target
)
{
self
.graph
.add_edge
(
source
,
*
target_node
,
Edge
::
Call
(
jump
));
}
// TODO: Log message for the else-case?
if
let
Some
(
ref
return_tid
)
=
return_
{
let
return_index
=
self
.jump_targets
[
return_tid
]
.
0
;
if
let
Some
(
return_node
)
=
return_to_node_option
{
self
.return_addresses
.entry
(
target
.clone
())
.and_modify
(|
vec
|
vec
.push
((
source
,
return_
index
)))
.or_insert_with
(||
vec!
[(
source
,
return_
index
)]);
.and_modify
(|
vec
|
vec
.push
((
source
,
return_
node
)))
.or_insert_with
(||
vec!
[(
source
,
return_
node
)]);
}
}
}
...
...
@@ -218,12 +268,12 @@ impl<'a> GraphBuilder<'a> {
}
}
/// Add all outgoing edges generated by calls and int
er
procedural jumps for a specific block to the graph.
/// Add all outgoing edges generated by calls and int
ra
procedural jumps for a specific block to the graph.
/// Return edges are *not* added by this function.
fn
add_outgoing_edges
(
&
mut
self
,
node
:
NodeIndex
,
block
:
&
'a
Term
<
Blk
>
)
{
let
jumps
=
block
.term.jmps
.as_slice
();
match
jumps
{
[]
=>
(),
// Blocks without jumps are dead ends corresponding to control flow reconstruction errors.
[]
=>
(),
// Blocks without jumps are dead ends corresponding to control flow reconstruction errors
or user-inserted dead ends
.
[
jump
]
=>
self
.add_jump_edge
(
node
,
jump
,
None
),
[
if_jump
,
else_jump
]
=>
{
self
.add_jump_edge
(
node
,
if_jump
,
None
);
...
...
@@ -239,14 +289,17 @@ impl<'a> GraphBuilder<'a> {
/// - an edge from the CallReturn node to the return-to site
fn
add_call_return_node_and_edges
(
&
mut
self
,
return_from_sub
:
&
Term
<
Sub
>
,
return_from_sub
:
&
'a
Term
<
Sub
>
,
return_source
:
NodeIndex
,
)
{
if
self
.return_addresses
.get
(
&
return_from_sub
.tid
)
.is_none
()
{
return
;
}
for
(
call_node
,
return_to_node
)
in
self
.return_addresses
[
&
return_from_sub
.tid
]
.iter
()
{
let
call_block
=
self
.graph
[
*
call_node
]
.get_block
();
let
(
call_block
,
caller_sub
)
=
match
self
.graph
[
*
call_node
]
{
Node
::
BlkEnd
(
block
,
sub
)
=>
(
block
,
sub
),
_
=>
panic!
(),
};
let
return_from_block
=
self
.graph
[
return_source
]
.get_block
();
let
call_term
=
call_block
.term
...
...
@@ -255,8 +308,8 @@ impl<'a> GraphBuilder<'a> {
.find
(|
jump
|
matches!
(
jump
.term
,
Jmp
::
Call
{
..
}))
.unwrap
();
let
cr_combine_node
=
self
.graph
.add_node
(
Node
::
CallReturn
{
call
:
call_block
,
return_
:
return_from_block
,
call
:
(
call_block
,
caller_sub
)
,
return_
:
(
return_from_block
,
return_from_sub
)
,
});
self
.graph
.add_edge
(
*
call_node
,
cr_combine_node
,
Edge
::
CRCallStub
);
...
...
@@ -269,26 +322,31 @@ impl<'a> GraphBuilder<'a> {
/// Add all return instruction related edges and nodes to the graph (for all return instructions).
fn
add_return_edges
(
&
mut
self
)
{
for
sub
in
&
self
.program.term.subs
{
for
block
in
&
sub
.term.blocks
{
let
mut
return_from_vec
=
Vec
::
new
();
for
node
in
self
.graph
.node_indices
()
{
if
let
Node
::
BlkEnd
(
block
,
sub
)
=
self
.graph
[
node
]
{
if
block
.term
.jmps
.iter
()
.any
(|
jmp
|
matches!
(
jmp
.term
,
Jmp
::
Return
(
_
)))
{
let
return_from_node
=
self
.jump_targets
[
&
block
.tid
]
.
1
;
self
.add_call_return_node_and_edges
(
sub
,
return_from_node
);
return_from_vec
.push
((
node
,
sub
));
}
}
}
for
(
return_from_node
,
return_from_sub
)
in
return_from_vec
{
self
.add_call_return_node_and_edges
(
return_from_sub
,
return_from_node
);
}
}
/// Add all non-return-instruction-related jump edges to the graph.
fn
add_jump_and_call_edges
(
&
mut
self
)
{
for
node
in
self
.graph
.node_indices
()
{
if
let
Node
::
BlkEnd
(
block
)
=
self
.graph
[
node
]
{
self
.add_outgoing_edges
(
node
,
block
);
while
!
self
.block_worklist
.is_empty
()
{
let
node
=
self
.block_worklist
.pop
()
.unwrap
();
match
self
.graph
[
node
]
{
Node
::
BlkEnd
(
block
,
_
)
=>
self
.add_outgoing_edges
(
node
,
block
),
_
=>
panic!
(),
}
}
}
...
...
@@ -309,26 +367,6 @@ pub fn get_program_cfg(program: &Term<Program>, extern_subs: HashSet<Tid>) -> Gr
builder
.build
()
}
/// For a given set of block TIDs generate a map from the TIDs to the indices of the BlkStart and BlkEnd nodes
/// corresponding to the block.
pub
fn
get_indices_of_block_nodes
<
'a
,
I
:
Iterator
<
Item
=
&
'a
Tid
>>
(
graph
:
&
'a
Graph
,
block_tids
:
I
,
)
->
HashMap
<
Tid
,
(
NodeIndex
,
NodeIndex
)
>
{
let
tids
:
HashSet
<
Tid
>
=
block_tids
.cloned
()
.collect
();
let
mut
tid_to_indices_map
=
HashMap
::
new
();
for
node_index
in
graph
.node_indices
()
{
if
let
Node
::
BlkStart
(
block_term
)
=
graph
[
node_index
]
{
if
let
Some
(
tid
)
=
tids
.get
(
&
block_term
.tid
)
{
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
));
}
}
}
tid_to_indices_map
}
#[cfg(test)]
mod
tests
{
use
super
::
*
;
...
...
@@ -371,10 +409,29 @@ mod tests {
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
::
new
(),
jmps
:
vec!
[
cond_jump_term
,
jump_term_2
],
},
};
let
sub2_blk2
=
Term
{
tid
:
Tid
::
new
(
"sub2_blk2"
),
term
:
Blk
{
defs
:
Vec
::
new
(),
jmps
:
vec!
[
return_term
],
},
};
...
...
@@ -382,7 +439,7 @@ mod tests {
tid
:
Tid
::
new
(
"sub2"
),
term
:
Sub
{
name
:
"sub2"
.to_string
(),
blocks
:
vec!
[
sub2_blk1
],
blocks
:
vec!
[
sub2_blk1
,
sub2_blk2
],
},
};
let
program
=
Term
{
...
...
@@ -401,7 +458,7 @@ mod tests {
let
program
=
mock_program
();
let
graph
=
get_program_cfg
(
&
program
,
HashSet
::
new
());
println!
(
"{}"
,
serde_json
::
to_string_pretty
(
&
graph
)
.unwrap
());
assert_eq!
(
graph
.node_count
(),
7
);
assert_eq!
(
graph
.edge_count
(),
8
);
assert_eq!
(
graph
.node_count
(),
14
);
assert_eq!
(
graph
.edge_count
(),
1
8
);
}
}
This diff is collapsed.
Click to expand it.
cwe_checker_rs/src/analysis/interprocedural_fixpoint.rs
View file @
4b6ca3be
...
...
@@ -185,7 +185,10 @@ impl<'a, T: Context<'a>> GeneralFPContext for GeneralizedContext<'a, T> {
NodeValue
::
Value
(
_
)
=>
panic!
(
"Unexpected interprocedural fixpoint graph state"
),
NodeValue
::
CallReturnCombinator
{
call
,
return_
}
=>
{
let
return_from_block
=
match
graph
.node_weight
(
start_node
)
{
Some
(
Node
::
CallReturn
{
call
:
_
,
return_
})
=>
return_
,
Some
(
Node
::
CallReturn
{
call
:
_
,
return_
:
(
return_from_block
,
_
),
})
=>
return_from_block
,
_
=>
panic!
(
"Malformed Control flow graph"
),
};
let
return_from_jmp
=
&
return_from_block
.term.jmps
[
0
];
...
...
This diff is collapsed.
Click to expand it.
cwe_checker_rs/src/analysis/pointer_inference/context/tests.rs
View file @
4b6ca3be
...
...
@@ -140,7 +140,14 @@ fn context_problem_implementation() {
jmps
:
Vec
::
new
(),
},
};
let
target_node
=
crate
::
analysis
::
graph
::
Node
::
BlkStart
(
&
target_block
);
let
sub
=
Term
{
tid
:
Tid
::
new
(
"caller_sub"
),
term
:
Sub
{
name
:
"caller_sub"
.into
(),
blocks
:
vec!
[
target_block
.clone
()],
},
};
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
();
assert_eq!
(
callee_state
.stack_id
,
new_id
(
"func"
,
"RSP"
));
...
...
This diff is collapsed.
Click to expand it.
cwe_checker_rs/src/analysis/pointer_inference/mod.rs
View file @
4b6ca3be
...
...
@@ -77,20 +77,22 @@ impl<'a> PointerInference<'a> {
.collect
();
for
sub_tid
in
project
.program.term.entry_points
.iter
()
{
if
let
Some
(
sub
)
=
subs
.get
(
sub_tid
)
{
if
let
Some
(
entry_block
)
=
sub
.term.blocks
.
iter
()
.next
(
)
{
if
let
Some
(
entry_block
)
=
sub
.term.blocks
.
get
(
0
)
{
entry_sub_to_entry_blocks_map
.insert
(
sub_tid
,
entry_block
.tid
.clone
());
}
}
}
let
tid_to_graph_indices_map
=
super
::
graph
::
get_indices_of_block_nodes
(
&
context
.graph
,
entry_sub_to_entry_blocks_map
.values
(),
);
let
mut
tid_to_graph_indices_map
=
HashMap
::
new
();
for
node
in
context
.graph
.node_indices
()
{
if
let
super
::
graph
::
Node
::
BlkStart
(
block
,
sub
)
=
context
.graph
[
node
]
{
tid_to_graph_indices_map
.insert
((
block
.tid
.clone
(),
sub
.tid
.clone
()),
node
);
}
}
let
entry_sub_to_entry_node_map
:
HashMap
<
Tid
,
NodeIndex
>
=
entry_sub_to_entry_blocks_map
.into_iter
()
.filter_map
(|(
sub_tid
,
block_tid
)|
{
if
let
Some
(
(
start_node_index
,
_end_node_index
)
)
=
tid_to_graph_indices_map
.get
(
&
block_tid
)
if
let
Some
(
start_node_index
)
=
tid_to_graph_indices_map
.get
(
&
(
block_tid
,
sub_tid
.clone
())
)
{
Some
((
sub_tid
.clone
(),
*
start_node_index
))
}
else
{
...
...
@@ -200,14 +202,14 @@ impl<'a> PointerInference<'a> {
let
graph
=
self
.computation
.get_graph
();
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_none
(
)
||
self
.computation
.get_node_value
(
node_id
)
.is_som
e
()
||
only_cfg_roots
&&
graph
if
let
Node
::
BlkStart
(
block
,
sub
)
=
node
{
if
start_block_to_sub_map
.get
(
&
block
.tid
)
==
Some
(
sub
)
&&
self
.computation
.get_node_value
(
node_id
)
.is_non
e
()
&&
(
!
only_cfg_roots
||
graph
.neighbors_directed
(
node_id
,
Direction
::
Incoming
)
.next
()
.is_
som
e
())
.is_
non
e
())
{
new_entry_points
.push
(
node_id
);
}
...
...
@@ -239,7 +241,7 @@ impl<'a> PointerInference<'a> {
let
mut
stateful_blocks
:
i64
=
0
;
let
mut
all_blocks
:
i64
=
0
;
for
(
node_id
,
node
)
in
graph
.node_references
()
{
if
let
Node
::
BlkStart
(
_block
)
=
node
{
if
let
Node
::
BlkStart
(
_block
,
_sub
)
=
node
{
all_blocks
+=
1
;
if
self
.computation
.get_node_value
(
node_id
)
.is_some
()
{
stateful_blocks
+=
1
;
...
...
This diff is collapsed.
Click to expand it.
cwe_checker_rs/src/analysis/pointer_inference/object_list.rs
View file @
4b6ca3be
...
...
@@ -213,7 +213,7 @@ impl AbstractObjectList {
possible_double_free_ids
.push
((
id
.clone
(),
error
));
}
}
}
else
if
let
Some
(
id
)
=
ids
.
iter
()
.next
(
)
{
}
else
if
let
Some
(
id
)
=
ids
.
get
(
0
)
{
if
let
Err
(
error
)
=
self
.objects
.get_mut
(
&
id
)
.unwrap
()
.
0
.mark_as_freed
()
{
possible_double_free_ids
.push
((
id
.clone
(),
error
));
}
...
...
This diff is collapsed.
Click to expand it.
cwe_checker_rs/src/intermediate_representation/term.rs
View file @
4b6ca3be
...
...
@@ -217,6 +217,19 @@ pub struct Program {
pub
entry_points
:
Vec
<
Tid
>
,
}
impl
Program
{
/// Find a block term by its term identifier.
/// WARNING: The function simply iterates through all blocks,
/// i.e. it is very inefficient for large projects!
pub
fn
find_block
(
&
self
,
tid
:
&
Tid
)
->
Option
<&
Term
<
Blk
>>
{
self
.subs
.iter
()
.map
(|
sub
|
sub
.term.blocks
.iter
())
.flatten
()
.find
(|
block
|
block
.tid
==
*
tid
)
}
}
/// The `Project` struct is the main data structure representing a binary.
///
/// It contains information about the disassembled binary
...
...
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