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
52804195
Unverified
Commit
52804195
authored
Sep 02, 2020
by
Enkelmann
Committed by
GitHub
Sep 02, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
replace let-bindings in expressions (#82)
parent
a849f2ae
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
201 additions
and
2 deletions
+201
-2
mod.rs
cwe_checker_rs/src/bil/mod.rs
+157
-0
analysis.rs
cwe_checker_rs/src/ffi/analysis.rs
+4
-2
mod.rs
cwe_checker_rs/src/term/mod.rs
+40
-0
No files found.
cwe_checker_rs/src/bil/mod.rs
View file @
52804195
...
@@ -63,6 +63,134 @@ pub enum Expression {
...
@@ -63,6 +63,134 @@ pub enum Expression {
},
},
}
}
impl
Expression
{
/// Resolve all let-bindings inside an expression to create an equivalent expression without usage of let-bindings.
pub
fn
replace_let_bindings
(
&
mut
self
)
{
use
Expression
::
*
;
match
self
{
Var
(
_
)
|
Const
(
_
)
|
Unknown
{
..
}
=>
(),
Load
{
memory
,
address
,
..
}
=>
{
memory
.replace_let_bindings
();
address
.replace_let_bindings
();
}
Store
{
memory
,
address
,
value
,
..
}
=>
{
memory
.replace_let_bindings
();
address
.replace_let_bindings
();
value
.replace_let_bindings
();
}
BinOp
{
op
:
_
,
lhs
,
rhs
}
=>
{
lhs
.replace_let_bindings
();
rhs
.replace_let_bindings
();
}
UnOp
{
op
:
_
,
arg
}
=>
arg
.replace_let_bindings
(),
Cast
{
kind
:
_
,
width
:
_
,
arg
,
}
=>
arg
.replace_let_bindings
(),
Let
{
var
,
bound_exp
,
body_exp
,
}
=>
{
let
to_replace
=
Expression
::
Var
(
var
.clone
());
body_exp
.replace_let_bindings
();
body_exp
.substitute
(
&
to_replace
,
bound_exp
);
*
self
=
*
body_exp
.clone
();
}
IfThenElse
{
condition
,
true_exp
,
false_exp
,
}
=>
{
condition
.replace_let_bindings
();
true_exp
.replace_let_bindings
();
false_exp
.replace_let_bindings
();
}
Extract
{
low_bit
:
_
,
high_bit
:
_
,
arg
,
}
=>
arg
.replace_let_bindings
(),
Concat
{
left
,
right
}
=>
{
left
.replace_let_bindings
();
right
.replace_let_bindings
();
}
}
}
/// Substitutes all subexpressions equal to `to_replace` with the expression `replace_with`.
fn
substitute
(
&
mut
self
,
to_replace
:
&
Expression
,
replace_with
:
&
Expression
)
{
use
Expression
::
*
;
if
self
==
to_replace
{
*
self
=
replace_with
.clone
();
}
else
{
match
self
{
Var
(
_
)
|
Const
(
_
)
|
Unknown
{
..
}
=>
(),
Load
{
memory
,
address
,
..
}
=>
{
memory
.substitute
(
to_replace
,
replace_with
);
address
.substitute
(
to_replace
,
replace_with
);
}
Store
{
memory
,
address
,
value
,
..
}
=>
{
memory
.substitute
(
to_replace
,
replace_with
);
address
.substitute
(
to_replace
,
replace_with
);
value
.substitute
(
to_replace
,
replace_with
);
}
BinOp
{
op
:
_
,
lhs
,
rhs
}
=>
{
lhs
.substitute
(
to_replace
,
replace_with
);
rhs
.substitute
(
to_replace
,
replace_with
);
}
UnOp
{
op
:
_
,
arg
}
=>
arg
.substitute
(
to_replace
,
replace_with
),
Cast
{
kind
:
_
,
width
:
_
,
arg
,
}
=>
arg
.substitute
(
to_replace
,
replace_with
),
Let
{
var
:
_
,
bound_exp
,
body_exp
,
}
=>
{
bound_exp
.substitute
(
to_replace
,
replace_with
);
body_exp
.substitute
(
to_replace
,
replace_with
);
}
IfThenElse
{
condition
,
true_exp
,
false_exp
,
}
=>
{
condition
.substitute
(
to_replace
,
replace_with
);
true_exp
.substitute
(
to_replace
,
replace_with
);
false_exp
.substitute
(
to_replace
,
replace_with
);
}
Extract
{
low_bit
:
_
,
high_bit
:
_
,
arg
,
}
=>
arg
.substitute
(
to_replace
,
replace_with
),
Concat
{
left
,
right
}
=>
{
left
.substitute
(
to_replace
,
replace_with
);
right
.substitute
(
to_replace
,
replace_with
);
}
}
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
pub
enum
CastType
{
pub
enum
CastType
{
UNSIGNED
,
UNSIGNED
,
...
@@ -110,6 +238,14 @@ pub enum Endianness {
...
@@ -110,6 +238,14 @@ pub enum Endianness {
mod
tests
{
mod
tests
{
use
super
::
*
;
use
super
::
*
;
fn
register
(
name
:
&
str
)
->
Variable
{
Variable
{
name
:
name
.into
(),
type_
:
Type
::
Immediate
(
64
),
is_temp
:
false
,
}
}
#[test]
#[test]
fn
variant_deserialization
()
{
fn
variant_deserialization
()
{
let
string
=
"
\
"
UNSIGNED
\
""
;
let
string
=
"
\
"
UNSIGNED
\
""
;
...
@@ -140,4 +276,25 @@ mod tests {
...
@@ -140,4 +276,25 @@ mod tests {
println!
(
"{}"
,
serde_json
::
to_string
(
&
exp
)
.unwrap
());
println!
(
"{}"
,
serde_json
::
to_string
(
&
exp
)
.unwrap
());
assert_eq!
(
exp
,
serde_json
::
from_str
(
string
)
.unwrap
())
assert_eq!
(
exp
,
serde_json
::
from_str
(
string
)
.unwrap
())
}
}
#[test]
fn
replace_let_bindings
()
{
let
mut
source_exp
=
Expression
::
Let
{
var
:
register
(
"x"
),
bound_exp
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_u64
(
12
))),
body_exp
:
Box
::
new
(
Expression
::
BinOp
{
op
:
BinOpType
::
PLUS
,
lhs
:
Box
::
new
(
Expression
::
Var
(
register
(
"x"
))),
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_u64
(
42
))),
}),
};
let
target_exp
=
Expression
::
BinOp
{
op
:
BinOpType
::
PLUS
,
lhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_u64
(
12
))),
rhs
:
Box
::
new
(
Expression
::
Const
(
Bitvector
::
from_u64
(
42
))),
};
source_exp
.replace_let_bindings
();
assert_eq!
(
source_exp
,
target_exp
);
}
}
}
cwe_checker_rs/src/ffi/analysis.rs
View file @
52804195
...
@@ -8,9 +8,10 @@ use super::failwith_on_panic;
...
@@ -8,9 +8,10 @@ use super::failwith_on_panic;
fn
run_pointer_inference
(
program_jsonbuilder_val
:
ocaml
::
Value
)
->
(
Vec
<
CweWarning
>
,
Vec
<
String
>
)
{
fn
run_pointer_inference
(
program_jsonbuilder_val
:
ocaml
::
Value
)
->
(
Vec
<
CweWarning
>
,
Vec
<
String
>
)
{
let
json_builder
=
unsafe
{
JsonBuilder
::
from_ocaml
(
&
program_jsonbuilder_val
)
};
let
json_builder
=
unsafe
{
JsonBuilder
::
from_ocaml
(
&
program_jsonbuilder_val
)
};
let
program_json
=
serde_json
::
Value
::
from
(
json_builder
);
let
program_json
=
serde_json
::
Value
::
from
(
json_builder
);
let
project
:
Project
=
let
mut
project
:
Project
=
serde_json
::
from_value
(
program_json
)
.expect
(
"Project deserialization failed"
);
serde_json
::
from_value
(
program_json
)
.expect
(
"Project deserialization failed"
);
project
.replace_let_bindings
();
crate
::
analysis
::
pointer_inference
::
run
(
&
project
,
false
)
crate
::
analysis
::
pointer_inference
::
run
(
&
project
,
false
)
}
}
...
@@ -26,9 +27,10 @@ caml!(rs_run_pointer_inference(program_jsonbuilder_val) {
...
@@ -26,9 +27,10 @@ caml!(rs_run_pointer_inference(program_jsonbuilder_val) {
fn
run_pointer_inference_and_print_debug
(
program_jsonbuilder_val
:
ocaml
::
Value
)
{
fn
run_pointer_inference_and_print_debug
(
program_jsonbuilder_val
:
ocaml
::
Value
)
{
let
json_builder
=
unsafe
{
JsonBuilder
::
from_ocaml
(
&
program_jsonbuilder_val
)
};
let
json_builder
=
unsafe
{
JsonBuilder
::
from_ocaml
(
&
program_jsonbuilder_val
)
};
let
program_json
=
serde_json
::
Value
::
from
(
json_builder
);
let
program_json
=
serde_json
::
Value
::
from
(
json_builder
);
let
project
:
Project
=
let
mut
project
:
Project
=
serde_json
::
from_value
(
program_json
)
.expect
(
"Project deserialization failed"
);
serde_json
::
from_value
(
program_json
)
.expect
(
"Project deserialization failed"
);
project
.replace_let_bindings
();
crate
::
analysis
::
pointer_inference
::
run
(
&
project
,
true
);
// Note: This discard all CweWarnings and log messages.
crate
::
analysis
::
pointer_inference
::
run
(
&
project
,
true
);
// Note: This discard all CweWarnings and log messages.
}
}
...
...
cwe_checker_rs/src/term/mod.rs
View file @
52804195
...
@@ -92,9 +92,49 @@ pub struct Project {
...
@@ -92,9 +92,49 @@ pub struct Project {
}
}
impl
Project
{
impl
Project
{
/// Get the bitsize of pointer values for the architecture of the project.
pub
fn
get_pointer_bitsize
(
&
self
)
->
BitSize
{
pub
fn
get_pointer_bitsize
(
&
self
)
->
BitSize
{
self
.stack_pointer_register
.bitsize
()
.unwrap
()
self
.stack_pointer_register
.bitsize
()
.unwrap
()
}
}
/// Substitute all let-binding-expressions in the project with equivalent expressions,
/// that do not contain the let-bindings.
/// This way subsequent analyses do not have to handle expressions containing let-bindings.
pub
fn
replace_let_bindings
(
&
mut
self
)
{
for
sub
in
self
.program.term.subs
.iter_mut
()
{
for
blk
in
sub
.term.blocks
.iter_mut
()
{
for
def
in
blk
.term.defs
.iter_mut
()
{
def
.term.rhs
.replace_let_bindings
();
}
for
jmp
in
blk
.term.jmps
.iter_mut
()
{
if
let
Some
(
ref
mut
condition
)
=
jmp
.term.condition
{
condition
.replace_let_bindings
();
}
match
&
mut
jmp
.term.kind
{
JmpKind
::
Call
(
call
)
=>
{
call
.target
.replace_let_bindings
();
if
let
Some
(
ref
mut
return_target
)
=
call
.return_
{
return_target
.replace_let_bindings
();
}
}
JmpKind
::
Goto
(
label
)
|
JmpKind
::
Return
(
label
)
=>
{
label
.replace_let_bindings
()
}
JmpKind
::
Interrupt
{
..
}
=>
(),
}
}
}
}
}
}
impl
Label
{
/// Replace let-bindings inside the expression for `Indirect` labels.
fn
replace_let_bindings
(
&
mut
self
)
{
if
let
Label
::
Indirect
(
expression
)
=
self
{
expression
.replace_let_bindings
();
}
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
...
...
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