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
1e46589f
Unverified
Commit
1e46589f
authored
2 years ago
by
Enkelmann
Committed by
GitHub
2 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify more cases of trivial expressions (#346)
parent
44ec840b
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
145 additions
and
13 deletions
+145
-13
tests.rs
...r_lib/src/intermediate_representation/expression/tests.rs
+19
-0
trivial_operation_substitution.rs
...presentation/expression/trivial_operation_substitution.rs
+126
-13
No files found.
src/cwe_checker_lib/src/intermediate_representation/expression/tests.rs
View file @
1e46589f
...
@@ -268,6 +268,25 @@ fn trivial_expression_substitution() {
...
@@ -268,6 +268,25 @@ fn trivial_expression_substitution() {
rhs
:
Box
::
new
(
setup
.rax_variable
.clone
()),
rhs
:
Box
::
new
(
setup
.rax_variable
.clone
()),
}
}
);
);
// Test (x - const_1) - const_2 = x - (const_1 + const_2)
let
mut
expr
=
Expression
::
BinOp
{
lhs
:
Box
::
new
(
Expression
::
BinOp
{
lhs
:
Box
::
new
(
setup
.rax_variable
.clone
()),
op
:
BinOpType
::
IntSub
,
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_i64
(
3
))),
}),
op
:
BinOpType
::
IntSub
,
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_i64
(
4
))),
};
expr
.substitute_trivial_operations
();
assert_eq!
(
expr
,
Expression
::
BinOp
{
lhs
:
Box
::
new
(
setup
.rax_variable
.clone
()),
op
:
BinOpType
::
IntSub
,
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_i64
(
7
)))
}
);
}
}
#[test]
#[test]
...
...
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/expression/trivial_operation_substitution.rs
View file @
1e46589f
use
super
::
*
;
use
super
::
*
;
impl
Expression
{
impl
Expression
{
/// Substitute trivial BinOp-expressions with their results,
/// Substitute cases, where a binary operation can be simplified because the left and right operand are identical.
/// e.g. substitute `a or a` with `a`.
fn
substitute_binop_for_lhs_equal_rhs
(
&
mut
self
)
{
///
/// 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
BinOpType
::
*
;
use
Expression
::
*
;
use
Expression
::
*
;
if
let
BinOp
{
op
,
lhs
,
rhs
}
=
self
{
if
let
BinOp
{
op
,
lhs
,
rhs
}
=
self
{
...
@@ -28,7 +24,15 @@ impl Expression {
...
@@ -28,7 +24,15 @@ impl Expression {
}
}
_
=>
(),
_
=>
(),
}
}
}
else
{
}
}
}
/// Substitute `AND`, `OR` and `XOR` operations where one operand is a constant.
fn
substitute_and_xor_or_with_constant
(
&
mut
self
)
{
use
BinOpType
::
*
;
use
Expression
::
*
;
if
let
BinOp
{
op
,
lhs
,
rhs
}
=
self
{
match
(
&**
lhs
,
op
,
&**
rhs
)
{
match
(
&**
lhs
,
op
,
&**
rhs
)
{
(
Const
(
bitvec
),
op
,
other
)
|
(
other
,
op
,
Const
(
bitvec
))
(
Const
(
bitvec
),
op
,
other
)
|
(
other
,
op
,
Const
(
bitvec
))
if
bitvec
.is_zero
()
&&
matches!
(
op
,
IntOr
|
IntXOr
|
BoolOr
|
BoolXOr
)
=>
if
bitvec
.is_zero
()
&&
matches!
(
op
,
IntOr
|
IntXOr
|
BoolOr
|
BoolXOr
)
=>
...
@@ -37,12 +41,51 @@ impl Expression {
...
@@ -37,12 +41,51 @@ impl Expression {
*
self
=
other
.clone
();
*
self
=
other
.clone
();
}
}
(
Const
(
bitvec
),
op
,
other
)
|
(
other
,
op
,
Const
(
bitvec
))
(
Const
(
bitvec
),
op
,
other
)
|
(
other
,
op
,
Const
(
bitvec
))
if
bitvec
.clone
()
.into_bitnot
()
.is_zero
()
if
bitvec
.clone
()
.into_bitnot
()
.is_zero
()
&&
matches!
(
op
,
IntAnd
|
BoolAnd
)
=>
&&
matches!
(
op
,
IntAnd
|
BoolAnd
)
=>
{
{
// `a and -1 = a` since all bits of -1 are 1.
// `a and -1 = a` since all bits of -1 are 1.
*
self
=
other
.clone
()
*
self
=
other
.clone
()
}
}
(
Const
(
bitvec
),
BoolAnd
,
_other
)
|
(
_other
,
BoolAnd
,
Const
(
bitvec
))
if
bitvec
.is_zero
()
=>
{
// `a and 0 = 0` for booleans
*
self
=
Const
(
bitvec
.clone
());
}
(
Const
(
bitvec
),
BoolAnd
,
other
)
|
(
other
,
BoolAnd
,
Const
(
bitvec
))
if
bitvec
.is_one
()
=>
{
// `a and 1 = a` for booleans
*
self
=
other
.clone
();
}
(
Const
(
bitvec
),
BoolOr
,
_other
)
|
(
_other
,
BoolOr
,
Const
(
bitvec
))
if
bitvec
.is_one
()
=>
{
// `a or 1 = 1` for booleans
*
self
=
Const
(
bitvec
.clone
());
}
(
Const
(
bitvec
),
BoolXOr
,
other
)
|
(
other
,
BoolXOr
,
Const
(
bitvec
))
if
bitvec
.is_one
()
=>
{
// `a xor 1 = ¬a` for booleans
*
self
=
UnOp
{
op
:
UnOpType
::
BoolNegate
,
arg
:
Box
::
new
(
other
.clone
()),
};
}
_
=>
(),
}
}
}
/// Simplify some comparison operations.
///
/// For example, `a == b || a < b` can be simplified to `a <= b`.
fn
substitute_equivalent_comparison_ops
(
&
mut
self
)
{
use
BinOpType
::
*
;
use
Expression
::
*
;
if
let
BinOp
{
op
,
lhs
,
rhs
}
=
self
{
match
(
&**
lhs
,
op
,
&**
rhs
)
{
(
(
Const
(
bitvec
),
Const
(
bitvec
),
op
,
op
,
...
@@ -171,8 +214,7 @@ impl Expression {
...
@@ -171,8 +214,7 @@ impl Expression {
rhs
:
lessequal_right
,
rhs
:
lessequal_right
,
},
},
)
if
(
lessequal_left
==
notequal_left
&&
lessequal_right
==
notequal_right
)
)
if
(
lessequal_left
==
notequal_left
&&
lessequal_right
==
notequal_right
)
||
(
lessequal_left
==
notequal_right
||
(
lessequal_left
==
notequal_right
&&
lessequal_right
==
notequal_left
)
=>
&&
lessequal_right
==
notequal_left
)
=>
{
{
// `x <= y and x != y` is equivalent to `x < y `
// `x <= y and x != y` is equivalent to `x < y `
*
self
=
Expression
::
BinOp
{
*
self
=
Expression
::
BinOp
{
...
@@ -207,8 +249,7 @@ impl Expression {
...
@@ -207,8 +249,7 @@ impl Expression {
rhs
:
lessequal_right
,
rhs
:
lessequal_right
,
},
},
)
if
(
lessequal_left
==
notequal_left
&&
lessequal_right
==
notequal_right
)
)
if
(
lessequal_left
==
notequal_left
&&
lessequal_right
==
notequal_right
)
||
(
lessequal_left
==
notequal_right
||
(
lessequal_left
==
notequal_right
&&
lessequal_right
==
notequal_left
)
=>
&&
lessequal_right
==
notequal_left
)
=>
{
{
// `x <= y and x != y` is equivalent to `x < y `
// `x <= y and x != y` is equivalent to `x < y `
*
self
=
Expression
::
BinOp
{
*
self
=
Expression
::
BinOp
{
...
@@ -221,6 +262,78 @@ impl Expression {
...
@@ -221,6 +262,78 @@ impl Expression {
}
}
}
}
}
}
/// Simplify arithmetic operations where intermediate results can be computed because some operands are constants.
fn
substitute_arithmetics_with_constants
(
&
mut
self
)
{
use
BinOpType
::
*
;
use
Expression
::
*
;
if
let
BinOp
{
op
,
lhs
,
rhs
}
=
self
{
match
(
&**
lhs
,
op
,
&**
rhs
)
{
(
Const
(
left
),
op
,
Const
(
right
))
if
matches!
(
op
,
IntSub
|
IntAdd
)
=>
{
// Compute the result of arithmetics with constants
*
self
=
Const
(
left
.bin_op
(
*
op
,
right
)
.expect
(
"Arithmetic operation with non-matching byte sizes."
),
);
}
(
BinOp
{
lhs
:
left
,
op
:
IntSub
,
rhs
:
middle
,
},
IntSub
,
Const
(
const_right
),
)
=>
{
if
let
Const
(
const_middle
)
=
&**
middle
{
// `(x - const_1) - const_2 = x - (const_1 + const_2)`
*
self
=
BinOp
{
lhs
:
left
.clone
(),
op
:
IntSub
,
rhs
:
Box
::
new
(
Const
(
const_middle
.bin_op
(
IntAdd
,
const_right
)
.unwrap
())),
}
}
}
(
BinOp
{
lhs
:
left
,
op
:
IntAdd
,
rhs
:
middle
,
},
IntAdd
,
Const
(
const_right
),
)
=>
{
if
let
Const
(
const_middle
)
=
&**
middle
{
// `(x + const_1) + const_2 = x + (const_1 + const_2)`
*
self
=
BinOp
{
lhs
:
left
.clone
(),
op
:
IntAdd
,
rhs
:
Box
::
new
(
Const
(
const_middle
.bin_op
(
IntAdd
,
const_right
)
.unwrap
())),
}
}
else
if
let
Const
(
const_left
)
=
&**
left
{
// `(const_1 + x) + const_2 = x + (const_1 + const_2)`
*
self
=
BinOp
{
lhs
:
middle
.clone
(),
op
:
IntAdd
,
rhs
:
Box
::
new
(
Const
(
const_left
.bin_op
(
IntAdd
,
const_right
)
.unwrap
())),
}
}
}
_
=>
(),
}
}
}
/// 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
)
{
self
.substitute_binop_for_lhs_equal_rhs
();
self
.substitute_and_xor_or_with_constant
();
self
.substitute_equivalent_comparison_ops
();
self
.substitute_arithmetics_with_constants
();
}
}
/// Substitute some trivial expressions with their result.
/// Substitute some trivial expressions with their result.
...
...
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