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
428d42d8
Commit
428d42d8
authored
Aug 17, 2021
by
Enkelmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
improve worklist order for fixpoint algorithm (#212)
parent
76936d8c
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
135 additions
and
9 deletions
+135
-9
fixpoint.rs
src/cwe_checker_lib/src/analysis/fixpoint.rs
+115
-8
forward_interprocedural_fixpoint.rs
...cker_lib/src/analysis/forward_interprocedural_fixpoint.rs
+17
-0
mod.rs
src/cwe_checker_lib/src/analysis/pointer_inference/mod.rs
+1
-1
test_sample.bin
test/bare_metal_samples/test_sample.bin
+0
-0
lib.rs
test/src/lib.rs
+2
-0
No files found.
src/cwe_checker_lib/src/analysis/fixpoint.rs
View file @
428d42d8
...
...
@@ -103,33 +103,70 @@ impl<T: Context> Computation<T> {
pub
fn
new
(
fp_context
:
T
,
default_value
:
Option
<
T
::
NodeValue
>
)
->
Self
{
let
graph
=
fp_context
.get_graph
();
// order the nodes in weak topological order
let
sorted_nodes
:
Vec
<
NodeIndex
>
=
petgraph
::
algo
::
kosaraju_scc
(
&
graph
)
let
priority_
sorted_nodes
:
Vec
<
NodeIndex
>
=
petgraph
::
algo
::
kosaraju_scc
(
&
graph
)
.into_iter
()
.flatten
()
.rev
()
.collect
();
Self
::
from_node_priority_list
(
fp_context
,
default_value
,
priority_sorted_nodes
)
}
/// Create a new fixpoint computation from a fixpoint problem, an optional default value
/// and the list of nodes of the graph ordered by the priority for the worklist algorithm.
/// The worklist algorithm will try to stabilize the nodes with a higher index
/// in the `priority_sorted_nodes` array before those with a lower index.
fn
from_node_priority_list
(
fp_context
:
T
,
default_value
:
Option
<
T
::
NodeValue
>
,
priority_sorted_nodes
:
Vec
<
NodeIndex
>
,
)
->
Self
{
let
mut
node_to_index
=
BTreeMap
::
new
();
for
(
i
,
node_index
)
in
sorted_nodes
.iter
()
.enumerate
()
{
for
(
i
,
node_index
)
in
priority_
sorted_nodes
.iter
()
.enumerate
()
{
node_to_index
.insert
(
node_index
,
i
);
}
let
node_priority_list
:
Vec
<
usize
>
=
node_to_index
.values
()
.copied
()
.collect
();
let
mut
worklist
=
BTreeSet
::
new
();
// If a default value exists, all nodes are added to the worklist. If not, the worklist is empty
if
default_value
.is_some
()
{
for
i
in
0
..
sorted_nodes
.len
()
{
for
i
in
0
..
priority_
sorted_nodes
.len
()
{
worklist
.insert
(
i
);
}
}
Computation
{
fp_context
,
node_priority_list
,
priority_to_node_list
:
sorted_nodes
,
priority_to_node_list
:
priority_
sorted_nodes
,
worklist
,
default_value
,
node_values
:
FnvHashMap
::
default
(),
}
}
/// Create a new fixpoint computation from a fixpoint problem and an optional default value for all nodes.
///
/// Computations created by this function use an alternate priority order for the fixpoint stabilization algorithm:
/// Nodes with 10 or more incoming edges will be stabilized last by the algorithm.
pub
fn
new_with_alternate_worklist_order
(
fp_context
:
T
,
default_value
:
Option
<
T
::
NodeValue
>
,
)
->
Self
{
let
graph
=
fp_context
.get_graph
();
let
mut
high_priority_nodes
=
Vec
::
new
();
let
mut
priority_sorted_nodes
=
Vec
::
new
();
for
node
in
petgraph
::
algo
::
kosaraju_scc
(
&
graph
)
.into_iter
()
.flatten
()
{
if
graph
.neighbors_directed
(
node
,
petgraph
::
EdgeDirection
::
Incoming
)
.count
()
>=
10
{
priority_sorted_nodes
.push
(
node
);
}
else
{
high_priority_nodes
.push
(
node
)
}
}
priority_sorted_nodes
.append
(
&
mut
high_priority_nodes
);
Self
::
from_node_priority_list
(
fp_context
,
default_value
,
priority_sorted_nodes
)
}
/// Get the value of a node.
pub
fn
get_node_value
(
&
self
,
node
:
NodeIndex
)
->
Option
<&
T
::
NodeValue
>
{
if
let
Some
(
value
)
=
self
.node_values
.get
(
&
node
)
{
...
...
@@ -184,6 +221,16 @@ impl<T: Context> Computation<T> {
}
}
/// Remove the highest priority node from the internal worklist and return it.
fn
take_next_node_from_worklist
(
&
mut
self
)
->
Option
<
NodeIndex
>
{
if
let
Some
(
priority
)
=
self
.worklist
.iter
()
.next_back
()
.cloned
()
{
let
priority
=
self
.worklist
.take
(
&
priority
)
.unwrap
();
Some
(
self
.priority_to_node_list
[
priority
])
}
else
{
None
}
}
/// Compute the fixpoint of the fixpoint problem.
/// Each node will be visited at most max_steps times.
/// If a node does not stabilize after max_steps visits, the end result will not be a fixpoint but only an intermediate result of a fixpoint computation.
...
...
@@ -207,9 +254,7 @@ impl<T: Context> Computation<T> {
/// Compute the fixpoint of the fixpoint problem.
/// If the fixpoint algorithm does not converge to a fixpoint, this function will not terminate.
pub
fn
compute
(
&
mut
self
)
{
while
let
Some
(
priority
)
=
self
.worklist
.iter
()
.next_back
()
.cloned
()
{
let
priority
=
self
.worklist
.take
(
&
priority
)
.unwrap
();
let
node
=
self
.priority_to_node_list
[
priority
];
while
let
Some
(
node
)
=
self
.take_next_node_from_worklist
()
{
self
.update_node
(
node
);
}
}
...
...
@@ -290,4 +335,66 @@ mod tests {
assert_eq!
(
30
,
*
solution
.get_node_value
(
NodeIndex
::
new
(
9
))
.unwrap
());
assert_eq!
(
0
,
*
solution
.get_node_value
(
NodeIndex
::
new
(
5
))
.unwrap
());
}
#[test]
fn
worklist_node_order
()
{
let
mut
graph
:
DiGraph
<
(),
u64
>
=
DiGraph
::
new
();
for
_i
in
0
..
21
{
graph
.add_node
(());
}
for
i
in
1
..
19
{
graph
.add_edge
(
NodeIndex
::
new
(
0
),
NodeIndex
::
new
(
i
),
1
);
}
for
i
in
1
..
19
{
graph
.add_edge
(
NodeIndex
::
new
(
i
),
NodeIndex
::
new
(
19
),
1
);
}
graph
.add_edge
(
NodeIndex
::
new
(
19
),
NodeIndex
::
new
(
20
),
1
);
let
mut
computation
=
Computation
::
new
(
FPContext
{
graph
:
graph
.clone
(),
},
Some
(
1
),
);
assert
!
(
computation
.node_priority_list
[
0
]
>
computation
.node_priority_list
[
1
]);
assert
!
(
computation
.node_priority_list
[
1
]
>
computation
.node_priority_list
[
19
]);
assert
!
(
computation
.node_priority_list
[
19
]
>
computation
.node_priority_list
[
20
]);
// assert that the nodes have the correct priority ordering
assert_eq!
(
computation
.take_next_node_from_worklist
(),
Some
(
NodeIndex
::
new
(
0
))
);
for
_i
in
1
..
19
{
assert
!
(
computation
.take_next_node_from_worklist
()
.unwrap
()
.index
()
<
19
);
}
assert_eq!
(
computation
.take_next_node_from_worklist
(),
Some
(
NodeIndex
::
new
(
19
))
);
assert_eq!
(
computation
.take_next_node_from_worklist
(),
Some
(
NodeIndex
::
new
(
20
))
);
let
mut
computation
=
Computation
::
new_with_alternate_worklist_order
(
FPContext
{
graph
},
Some
(
1
));
assert
!
(
computation
.node_priority_list
[
19
]
<
computation
.node_priority_list
[
0
]);
assert
!
(
computation
.node_priority_list
[
1
]
>
computation
.node_priority_list
[
20
]);
// assert that the nodes have the correct priority ordering
assert_eq!
(
computation
.take_next_node_from_worklist
(),
Some
(
NodeIndex
::
new
(
0
))
);
for
_i
in
1
..
19
{
assert
!
(
computation
.take_next_node_from_worklist
()
.unwrap
()
.index
()
<
19
);
}
assert_eq!
(
computation
.take_next_node_from_worklist
(),
Some
(
NodeIndex
::
new
(
20
))
);
// nodes with a lot of incoming edges get stabilized last in the alternate worklist order
assert_eq!
(
computation
.take_next_node_from_worklist
(),
Some
(
NodeIndex
::
new
(
19
))
);
}
}
src/cwe_checker_lib/src/analysis/forward_interprocedural_fixpoint.rs
View file @
428d42d8
...
...
@@ -258,3 +258,20 @@ pub fn create_computation<'a, T: Context<'a>>(
let
generalized_problem
=
GeneralizedContext
::
new
(
problem
);
super
::
fixpoint
::
Computation
::
new
(
generalized_problem
,
default_value
.map
(
NodeValue
::
Value
))
}
/// Generate a new computation from the corresponding context and an optional default value for nodes.
/// Uses the alternate worklist order when computing the fixpoint.
///
/// The alternate worklist order moves nodes with 10 or more incoming edges to the end of the priority queue.
/// This can improve the convergence speed for these nodes in the fixpoint algorithm.
/// Use if you encounter convergence problems for nodes with a lot of incoming edges.
pub
fn
create_computation_with_alternate_worklist_order
<
'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_with_alternate_worklist_order
(
generalized_problem
,
default_value
.map
(
NodeValue
::
Value
),
)
}
src/cwe_checker_lib/src/analysis/pointer_inference/mod.rs
View file @
428d42d8
...
...
@@ -149,7 +149,7 @@ impl<'a> PointerInference<'a> {
})
.collect
();
let
mut
fixpoint_computation
=
super
::
forward_interprocedural_fixpoint
::
create_computation
(
context
,
None
);
super
::
forward_interprocedural_fixpoint
::
create_computation
_with_alternate_worklist_order
(
context
,
None
);
if
print_stats
{
let
_
=
log_sender
.send
(
LogThreadMsg
::
Log
(
LogMessage
::
new_debug
(
format!
(
"Pointer Inference: Adding {} entry points"
,
...
...
test/bare_metal_samples/test_sample.bin
View file @
428d42d8
No preview for this file type
test/src/lib.rs
View file @
428d42d8
...
...
@@ -245,6 +245,8 @@ mod tests {
mark_skipped
(
&
mut
tests
,
"x86"
,
"gcc"
);
// Loss of stack register value since we do not track pointer alignment yet.
mark_compiler_skipped
(
&
mut
tests
,
"mingw32-gcc"
);
// TODO: Check reason for failure!
for
test_case
in
tests
{
let
num_expected_occurences
=
1
;
if
let
Err
(
error
)
=
test_case
.run_test
(
"[CWE119]"
,
num_expected_occurences
)
{
...
...
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