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
321a06c0
Unverified
Commit
321a06c0
authored
4 years ago
by
Enkelmann
Committed by
GitHub
4 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Substitute more trivial expressions with their results (#138)
parent
2da3c41f
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
59 additions
and
72 deletions
+59
-72
expression.rs
cwe_checker_rs/src/intermediate_representation/expression.rs
+51
-25
tests.rs
...er_rs/src/intermediate_representation/expression/tests.rs
+7
-0
lib.rs
test/src/lib.rs
+1
-47
No files found.
cwe_checker_rs/src/intermediate_representation/expression.rs
View file @
321a06c0
...
...
@@ -81,6 +81,55 @@ impl Expression {
}
}
/// Substitute trivial BinOp-expressions with their results,
/// e.g. substitute `a or a` with `a`.
///
/// This function assumes that `self` is a `BinOp`
/// and it does not substitute trivial expressions in the two input expressions of the `BinOp`.
fn
substitute_trivial_binops
(
&
mut
self
)
{
use
BinOpType
::
*
;
use
Expression
::
*
;
if
let
BinOp
{
op
,
lhs
,
rhs
}
=
self
{
if
lhs
==
rhs
{
match
op
{
BoolAnd
|
BoolOr
|
IntAnd
|
IntOr
=>
{
// This is an identity operation
*
self
=
(
**
lhs
)
.clone
();
}
BoolXOr
|
IntXOr
=>
{
// `a xor a` always equals zero.
*
self
=
Expression
::
Const
(
Bitvector
::
zero
(
lhs
.bytesize
()
.into
()));
}
IntEqual
|
IntLessEqual
|
IntSLessEqual
=>
{
*
self
=
Expression
::
Const
(
Bitvector
::
one
(
ByteSize
::
new
(
1
)
.into
()));
}
IntNotEqual
|
IntLess
|
IntSLess
=>
{
*
self
=
Expression
::
Const
(
Bitvector
::
zero
(
ByteSize
::
new
(
1
)
.into
()));
}
_
=>
(),
}
}
else
{
match
(
&**
lhs
,
&**
rhs
)
{
(
Const
(
bitvec
),
other
)
|
(
other
,
Const
(
bitvec
))
if
bitvec
.is_zero
()
=>
{
if
matches!
(
op
,
IntOr
|
IntXOr
|
BoolOr
|
BoolXOr
)
{
// `a or 0 = a` and `a xor 0 = a`
*
self
=
other
.clone
();
}
}
(
Const
(
bitvec
),
other
)
|
(
other
,
Const
(
bitvec
))
if
bitvec
.clone
()
.into_bitnot
()
.is_zero
()
=>
{
if
matches!
(
op
,
IntAnd
|
BoolAnd
)
{
// `a and -1 = a` since all bits of -1 are 1.
*
self
=
other
.clone
()
}
}
_
=>
(),
}
}
}
}
/// Substitute some trivial expressions with their result.
/// E.g. substitute `a XOR a` with zero or substitute `a OR a` with `a`.
pub
fn
substitute_trivial_operations
(
&
mut
self
)
{
...
...
@@ -106,33 +155,10 @@ impl Expression {
}
}
UnOp
{
op
:
_
,
arg
}
=>
arg
.substitute_trivial_operations
(),
BinOp
{
op
,
lhs
,
rhs
}
=>
{
BinOp
{
op
:
_
,
lhs
,
rhs
}
=>
{
lhs
.substitute_trivial_operations
();
rhs
.substitute_trivial_operations
();
if
lhs
==
rhs
{
match
op
{
BinOpType
::
BoolAnd
|
BinOpType
::
BoolOr
|
BinOpType
::
IntAnd
|
BinOpType
::
IntOr
=>
{
// This is an identity operation
*
self
=
(
**
lhs
)
.clone
();
}
BinOpType
::
BoolXOr
|
BinOpType
::
IntXOr
=>
{
// `a xor a` always equals zero.
*
self
=
Expression
::
Const
(
Bitvector
::
zero
(
lhs
.bytesize
()
.into
()));
}
BinOpType
::
IntEqual
|
BinOpType
::
IntLessEqual
|
BinOpType
::
IntSLessEqual
=>
{
*
self
=
Expression
::
Const
(
Bitvector
::
one
(
ByteSize
::
new
(
1
)
.into
()));
}
BinOpType
::
IntNotEqual
|
BinOpType
::
IntLess
|
BinOpType
::
IntSLess
=>
{
*
self
=
Expression
::
Const
(
Bitvector
::
zero
(
ByteSize
::
new
(
1
)
.into
()));
}
_
=>
(),
}
}
self
.substitute_trivial_binops
();
}
}
}
...
...
This diff is collapsed.
Click to expand it.
cwe_checker_rs/src/intermediate_representation/expression/tests.rs
View file @
321a06c0
...
...
@@ -116,6 +116,13 @@ fn trivial_expression_substitution() {
expr
,
Expression
::
Const
(
Bitvector
::
zero
(
ByteSize
::
new
(
8
)
.into
()))
);
let
mut
expr
=
Expression
::
BinOp
{
op
:
BinOpType
::
IntOr
,
lhs
:
Box
::
new
(
setup
.rax_variable
.clone
()),
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
zero
(
ByteSize
::
new
(
8
)
.into
()))),
};
expr
.substitute_trivial_operations
();
assert_eq!
(
expr
,
setup
.rax_variable
);
}
#[test]
...
...
This diff is collapsed.
Click to expand it.
test/src/lib.rs
View file @
321a06c0
...
...
@@ -174,13 +174,6 @@ mod tests {
let
mut
error_log
=
Vec
::
new
();
let
mut
tests
=
all_test_cases
(
"cwe_190"
,
"CWE190"
);
// Ghidra does not recognize all extern function calls in the disassembly step for MIPS.
// Needs own control flow graph analysis to be fixed.
mark_skipped
(
&
mut
tests
,
"mips64"
,
"clang"
);
mark_skipped
(
&
mut
tests
,
"mips64el"
,
"clang"
);
mark_skipped
(
&
mut
tests
,
"mips"
,
"gcc"
);
mark_skipped
(
&
mut
tests
,
"mipsel"
,
"gcc"
);
mark_architecture_skipped
(
&
mut
tests
,
"ppc64"
);
// Ghidra generates mangled function names here for some reason.
mark_architecture_skipped
(
&
mut
tests
,
"ppc64le"
);
// Ghidra generates mangled function names here for some reason.
...
...
@@ -289,13 +282,6 @@ mod tests {
let
mut
error_log
=
Vec
::
new
();
let
mut
tests
=
all_test_cases
(
"cwe_415"
,
"Memory"
);
// Ghidra does not recognize all extern function calls in the disassembly step for MIPS.
// Needs own control flow graph analysis to be fixed.
mark_architecture_skipped
(
&
mut
tests
,
"mips64"
);
mark_architecture_skipped
(
&
mut
tests
,
"mips64el"
);
mark_architecture_skipped
(
&
mut
tests
,
"mips"
);
mark_architecture_skipped
(
&
mut
tests
,
"mipsel"
);
mark_architecture_skipped
(
&
mut
tests
,
"ppc64"
);
// Ghidra generates mangled function names here for some reason.
mark_architecture_skipped
(
&
mut
tests
,
"ppc64le"
);
// Ghidra generates mangled function names here for some reason.
...
...
@@ -324,20 +310,13 @@ mod tests {
let
mut
error_log
=
Vec
::
new
();
let
mut
tests
=
all_test_cases
(
"cwe_416"
,
"Memory"
);
// Ghidra does not recognize all extern function calls in the disassembly step for MIPS.
// Needs own control flow graph analysis to be fixed.
mark_architecture_skipped
(
&
mut
tests
,
"mips64"
);
mark_architecture_skipped
(
&
mut
tests
,
"mips64el"
);
mark_architecture_skipped
(
&
mut
tests
,
"mips"
);
mark_architecture_skipped
(
&
mut
tests
,
"mipsel"
);
mark_architecture_skipped
(
&
mut
tests
,
"ppc64"
);
// Ghidra generates mangled function names here for some reason.
mark_architecture_skipped
(
&
mut
tests
,
"ppc64le"
);
// Ghidra generates mangled function names here for some reason.
// The analysis loses track of the stack pointer offset in the main() function
// because of a "INT_AND ESP 0xfffffff0" instruction.
// We would need knowledge about alignment guarantees for the stack pointer at the start of main() to fix this.
mark_
architecture_skipped
(
&
mut
tests
,
"x86
"
);
mark_
skipped
(
&
mut
tests
,
"x86"
,
"gcc
"
);
mark_compiler_skipped
(
&
mut
tests
,
"mingw32-gcc"
);
// TODO: Check reason for failure!
...
...
@@ -359,13 +338,6 @@ mod tests {
let
mut
error_log
=
Vec
::
new
();
let
mut
tests
=
all_test_cases
(
"cwe_426"
,
"CWE426"
);
// Ghidra does not recognize all extern function calls in the disassembly step for MIPS.
// Needs own control flow graph analysis to be fixed.
mark_skipped
(
&
mut
tests
,
"mips64"
,
"clang"
);
mark_skipped
(
&
mut
tests
,
"mips64el"
,
"clang"
);
mark_skipped
(
&
mut
tests
,
"mips"
,
"gcc"
);
mark_skipped
(
&
mut
tests
,
"mipsel"
,
"gcc"
);
mark_architecture_skipped
(
&
mut
tests
,
"ppc64"
);
// Ghidra generates mangled function names here for some reason.
mark_architecture_skipped
(
&
mut
tests
,
"ppc64le"
);
// Ghidra generates mangled function names here for some reason.
...
...
@@ -395,21 +367,12 @@ mod tests {
mark_skipped
(
&
mut
tests
,
"arm"
,
"clang"
);
mark_skipped
(
&
mut
tests
,
"mips"
,
"clang"
);
mark_skipped
(
&
mut
tests
,
"mipsel"
,
"clang"
);
// Ghidra does not recognize all extern function calls in the disassembly step for MIPS.
// Needs own control flow graph analysis to be fixed.
mark_skipped
(
&
mut
tests
,
"mips64"
,
"clang"
);
mark_skipped
(
&
mut
tests
,
"mips64el"
,
"clang"
);
mark_skipped
(
&
mut
tests
,
"mips"
,
"gcc"
);
mark_skipped
(
&
mut
tests
,
"mipsel"
,
"gcc"
);
mark_architecture_skipped
(
&
mut
tests
,
"ppc64"
);
// Ghidra generates mangled function names here for some reason.
mark_architecture_skipped
(
&
mut
tests
,
"ppc64le"
);
// Ghidra generates mangled function names here for some reason.
// This is a bug in the handling of sub-registers.
// Register `ECX` is read, but the analysis doesn't know that `ECX` is a sub-register of `RCX`.
mark_skipped
(
&
mut
tests
,
"x64"
,
"clang"
);
mark_compiler_skipped
(
&
mut
tests
,
"mingw32-gcc"
);
// TODO: Check reason for failure!
for
test_case
in
tests
{
...
...
@@ -430,12 +393,6 @@ mod tests {
let
mut
error_log
=
Vec
::
new
();
let
mut
tests
=
all_test_cases
(
"cwe_476"
,
"CWE476"
);
// TODO: Check reason for failure!
mark_architecture_skipped
(
&
mut
tests
,
"mips64"
);
mark_architecture_skipped
(
&
mut
tests
,
"mips64el"
);
mark_architecture_skipped
(
&
mut
tests
,
"mips"
);
mark_architecture_skipped
(
&
mut
tests
,
"mipsel"
);
mark_architecture_skipped
(
&
mut
tests
,
"ppc64"
);
// Ghidra generates mangled function names here for some reason.
mark_architecture_skipped
(
&
mut
tests
,
"ppc64le"
);
// Ghidra generates mangled function names here for some reason.
...
...
@@ -459,9 +416,6 @@ mod tests {
let
mut
error_log
=
Vec
::
new
();
let
mut
tests
=
linux_test_cases
(
"cwe_560"
,
"CWE560"
);
mark_skipped
(
&
mut
tests
,
"arm"
,
"gcc"
);
// The parameter is loaded from global memory (which is not supported yet)
mark_skipped
(
&
mut
tests
,
"mips"
,
"gcc"
);
// The parameter is loaded from global memory (which is not supported yet)
mark_skipped
(
&
mut
tests
,
"mipsel"
,
"gcc"
);
// The parameter is loaded from global memory (which is not supported yet)
mark_architecture_skipped
(
&
mut
tests
,
"ppc64"
);
// Ghidra generates mangled function names here for some reason.
mark_architecture_skipped
(
&
mut
tests
,
"ppc64le"
);
// Ghidra generates mangled function names here for some reason.
...
...
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