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
c11a21e9
Commit
c11a21e9
authored
Sep 22, 2020
by
Enkelmann
Committed by
Enkelmann
Nov 03, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implement conversion functions for jumps and defs.
parent
263c1498
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
845 additions
and
392 deletions
+845
-392
mod.rs
cwe_checker_rs/src/bil/mod.rs
+145
-0
variable.rs
cwe_checker_rs/src/bil/variable.rs
+25
-3
expression.rs
cwe_checker_rs/src/intermediate_representation/expression.rs
+2
-1
mod.rs
cwe_checker_rs/src/intermediate_representation/mod.rs
+40
-41
term.rs
cwe_checker_rs/src/intermediate_representation/term.rs
+31
-5
variable.rs
cwe_checker_rs/src/intermediate_representation/variable.rs
+5
-6
lib.rs
cwe_checker_rs/src/lib.rs
+2
-2
expressions.rs
cwe_checker_rs/src/pcode/expressions.rs
+190
-185
mod.rs
cwe_checker_rs/src/pcode/mod.rs
+0
-1
term.rs
cwe_checker_rs/src/pcode/term.rs
+196
-148
mod.rs
cwe_checker_rs/src/term/mod.rs
+209
-0
No files found.
cwe_checker_rs/src/bil/mod.rs
View file @
c11a21e9
use
crate
::
intermediate_representation
::
BinOpType
as
IrBinOpType
;
use
crate
::
intermediate_representation
::
ByteSize
;
use
crate
::
intermediate_representation
::
CastOpType
as
IrCastOpType
;
use
crate
::
intermediate_representation
::
Expression
as
IrExpression
;
use
crate
::
intermediate_representation
::
UnOpType
as
IrUnOpType
;
use
apint
::
Width
;
use
serde
::{
Deserialize
,
Serialize
};
pub
mod
variable
;
...
...
@@ -7,6 +13,13 @@ pub type Bitvector = apint::ApInt;
pub
type
BitSize
=
u16
;
impl
From
<
BitSize
>
for
ByteSize
{
/// Convert to `ByteSize`, while always rounding up to the nearest full byte.
fn
from
(
bitsize
:
BitSize
)
->
ByteSize
{
((
bitsize
as
u64
+
7
)
/
8
)
.into
()
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
enum
Expression
{
Var
(
Variable
),
...
...
@@ -189,6 +202,100 @@ impl Expression {
}
}
}
pub
fn
bitsize
(
&
self
)
->
BitSize
{
use
Expression
::
*
;
match
self
{
Var
(
var
)
=>
var
.bitsize
()
.unwrap
(),
Const
(
bitvector
)
=>
bitvector
.width
()
.to_usize
()
as
u16
,
Load
{
size
,
..
}
=>
*
size
,
Store
{
..
}
=>
0
,
BinOp
{
op
,
lhs
,
rhs
:
_
}
=>
{
use
BinOpType
::
*
;
match
op
{
EQ
|
NEQ
|
LT
|
LE
|
SLT
|
SLE
=>
1
,
_
=>
lhs
.bitsize
(),
}
}
UnOp
{
arg
,
..
}
=>
arg
.bitsize
(),
Cast
{
width
,
..
}
=>
*
width
,
Let
{
..
}
=>
panic!
(),
Unknown
{
description
:
_
,
type_
,
}
=>
type_
.bitsize
()
.unwrap
(),
IfThenElse
{
true_exp
,
..
}
=>
true_exp
.bitsize
(),
Extract
{
low_bit
,
high_bit
,
..
}
=>
high_bit
-
low_bit
,
Concat
{
left
,
right
}
=>
left
.bitsize
()
+
right
.bitsize
(),
}
}
}
impl
From
<
Expression
>
for
IrExpression
{
fn
from
(
expr
:
Expression
)
->
IrExpression
{
use
Expression
::
*
;
match
expr
{
Var
(
var
)
=>
IrExpression
::
Var
(
var
.into
()),
Const
(
bitvector
)
=>
IrExpression
::
Const
(
bitvector
),
Load
{
..
}
|
Store
{
..
}
|
Let
{
..
}
|
Unknown
{
..
}
|
IfThenElse
{
..
}
=>
{
panic!
()
}
BinOp
{
op
,
lhs
,
rhs
}
=>
IrExpression
::
BinOp
{
op
:
op
.into
(),
lhs
:
Box
::
new
(
IrExpression
::
from
(
*
lhs
)),
rhs
:
Box
::
new
(
IrExpression
::
from
(
*
rhs
)),
},
UnOp
{
op
,
arg
}
=>
IrExpression
::
UnOp
{
op
:
op
.into
(),
arg
:
Box
::
new
(
IrExpression
::
from
(
*
arg
)),
},
Cast
{
kind
,
width
,
arg
}
=>
{
use
CastType
::
*
;
match
kind
{
UNSIGNED
=>
IrExpression
::
Cast
{
arg
:
Box
::
new
(
IrExpression
::
from
(
*
arg
)),
op
:
IrCastOpType
::
IntZExt
,
size
:
width
.into
(),
},
SIGNED
=>
IrExpression
::
Cast
{
arg
:
Box
::
new
(
IrExpression
::
from
(
*
arg
)),
op
:
IrCastOpType
::
IntSExt
,
size
:
width
.into
(),
},
HIGH
=>
{
assert
!
(
width
%
8
==
0
);
let
low_byte
=
(
arg
.bitsize
()
-
BitSize
::
from
(
width
))
.into
();
IrExpression
::
Subpiece
{
arg
:
Box
::
new
(
IrExpression
::
from
(
*
arg
)),
low_byte
,
size
:
width
.into
(),
}
}
LOW
=>
IrExpression
::
Subpiece
{
arg
:
Box
::
new
(
IrExpression
::
from
(
*
arg
)),
low_byte
:
(
0
as
u64
)
.into
(),
size
:
width
.into
(),
},
}
}
Extract
{
low_bit
,
high_bit
,
arg
,
}
=>
IrExpression
::
Subpiece
{
size
:
(
high_bit
-
low_bit
+
1
)
.into
(),
low_byte
:
low_bit
.into
(),
arg
:
Box
::
new
(
IrExpression
::
from
(
*
arg
)),
},
Concat
{
left
,
right
}
=>
IrExpression
::
BinOp
{
op
:
IrBinOpType
::
Piece
,
lhs
:
Box
::
new
(
IrExpression
::
from
(
*
left
)),
rhs
:
Box
::
new
(
IrExpression
::
from
(
*
right
)),
},
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
...
...
@@ -222,12 +329,50 @@ pub enum BinOpType {
SLE
,
}
impl
From
<
BinOpType
>
for
IrBinOpType
{
fn
from
(
op
:
BinOpType
)
->
IrBinOpType
{
use
BinOpType
::
*
;
use
IrBinOpType
::
*
;
match
op
{
PLUS
=>
IntAdd
,
MINUS
=>
IntSub
,
TIMES
=>
IntMult
,
DIVIDE
=>
IntDiv
,
SDIVIDE
=>
IntSDiv
,
MOD
=>
IntRem
,
SMOD
=>
IntSRem
,
LSHIFT
=>
IntLeft
,
RSHIFT
=>
IntRight
,
ARSHIFT
=>
IntSRight
,
AND
=>
IntAnd
,
OR
=>
IntOr
,
XOR
=>
IntXOr
,
EQ
=>
IntEqual
,
NEQ
=>
IntNotEqual
,
LT
=>
IntLess
,
LE
=>
IntLessEqual
,
SLT
=>
IntSLess
,
SLE
=>
IntSLessEqual
,
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
pub
enum
UnOpType
{
NEG
,
NOT
,
}
impl
From
<
UnOpType
>
for
IrUnOpType
{
fn
from
(
op
:
UnOpType
)
->
IrUnOpType
{
use
UnOpType
::
*
;
match
op
{
NEG
=>
IrUnOpType
::
Int2Comp
,
NOT
=>
IrUnOpType
::
IntNegate
,
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
pub
enum
Endianness
{
LittleEndian
,
...
...
cwe_checker_rs/src/bil/variable.rs
View file @
c11a21e9
use
super
::
BitSize
;
use
crate
::
intermediate_representation
::
Variable
as
IrVariable
;
use
crate
::
prelude
::
*
;
use
serde
::{
Deserialize
,
Serialize
};
...
...
@@ -19,12 +20,33 @@ pub enum Type {
Unknown
,
}
impl
Type
{
pub
fn
bitsize
(
&
self
)
->
Result
<
BitSize
,
Error
>
{
if
let
Type
::
Immediate
(
bitsize
)
=
self
{
Ok
(
*
bitsize
)
}
else
{
Err
(
anyhow!
(
"Not a register type"
))
}
}
}
impl
Variable
{
pub
fn
bitsize
(
&
self
)
->
Result
<
BitSize
,
Error
>
{
if
let
Type
::
Immediate
(
bitsize
)
=
self
.type_
{
Ok
(
bitsize
)
self
.type_
.bitsize
()
}
}
impl
From
<
Variable
>
for
IrVariable
{
fn
from
(
var
:
Variable
)
->
IrVariable
{
let
size
=
if
let
Type
::
Immediate
(
bitsize
)
=
var
.type_
{
bitsize
.into
()
}
else
{
Err
(
anyhow!
(
"Not a register variable"
))
panic!
()
};
IrVariable
{
name
:
var
.name
,
size
,
is_temp
:
var
.is_temp
,
}
}
}
...
...
cwe_checker_rs/src/intermediate_representation/expression.rs
View file @
c11a21e9
...
...
@@ -38,6 +38,8 @@ pub enum BinOpType {
IntNotEqual
,
IntLess
,
IntSLess
,
IntLessEqual
,
IntSLessEqual
,
IntAdd
,
IntSub
,
IntCarry
,
...
...
@@ -74,7 +76,6 @@ pub enum CastOpType {
Int2Float
,
Float2Float
,
Trunc
,
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
...
...
cwe_checker_rs/src/intermediate_representation/mod.rs
View file @
c11a21e9
...
...
@@ -12,51 +12,51 @@ pub use term::*;
// TODO: move ByteSize and BitSize into their own module
#[derive(
Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Clone,
Copy,
Display,
Binary,
Octal,
LowerHex,
UpperHex,
From,
Into,
Not,
Add,
Sub,
Mul,
Div,
Rem,
Shr,
Shl,
AddAssign,
SubAssign,
MulAssign,
DivAssign,
RemAssign,
ShrAssign,
ShlAssign,
Sum,
Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Clone,
Copy,
Display,
Binary,
Octal,
LowerHex,
UpperHex,
From,
Into,
Not,
Add,
Sub,
Mul,
Div,
Rem,
Shr,
Shl,
AddAssign,
SubAssign,
MulAssign,
DivAssign,
RemAssign,
ShrAssign,
ShlAssign,
Sum,
)]
#[serde(transparent)]
pub
struct
ByteSize
(
u64
);
impl
From
<
ByteSize
>
for
BitSize
{
fn
from
(
bytesize
:
ByteSize
)
->
BitSize
{
u16
::
try_from
(
u64
::
from
(
bytesize
)
*
8
)
.unwrap
()
}
fn
from
(
bytesize
:
ByteSize
)
->
BitSize
{
u16
::
try_from
(
u64
::
from
(
bytesize
)
*
8
)
.unwrap
()
}
}
impl
From
<
ByteSize
>
for
apint
::
BitWidth
{
fn
from
(
bytesize
:
ByteSize
)
->
apint
::
BitWidth
{
apint
::
BitWidth
::
from
((
u64
::
from
(
bytesize
)
*
8
)
as
usize
)
}
}
\ No newline at end of file
fn
from
(
bytesize
:
ByteSize
)
->
apint
::
BitWidth
{
apint
::
BitWidth
::
from
((
u64
::
from
(
bytesize
)
*
8
)
as
usize
)
}
}
cwe_checker_rs/src/intermediate_representation/term.rs
View file @
c11a21e9
use
super
::{
ByteSize
,
Expression
,
Variable
};
use
crate
::
prelude
::
*
;
use
crate
::
term
::{
Term
,
Tid
};
use
super
::{
Variable
,
Expression
,
ByteSize
};
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
enum
Def
{
...
...
@@ -18,4 +16,33 @@ pub enum Def {
var
:
Variable
,
value
:
Expression
,
},
}
\ No newline at end of file
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
enum
Jmp
{
Branch
(
Tid
),
BranchInd
(
Expression
),
CBranch
{
target
:
Tid
,
condition
:
Expression
,
},
Call
{
target
:
Tid
,
return_
:
Option
<
Tid
>
,
},
CallInd
{
target
:
Expression
,
return_
:
Option
<
Tid
>
,
},
Return
(
Expression
),
CallOther
{
description
:
String
,
return_
:
Option
<
Tid
>
,
},
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Blk
{
pub
defs
:
Vec
<
Term
<
Def
>>
,
pub
jmps
:
Vec
<
Term
<
Jmp
>>
,
}
cwe_checker_rs/src/intermediate_representation/variable.rs
View file @
c11a21e9
use
crate
::
prelude
::
*
;
use
super
::
ByteSize
;
use
crate
::
prelude
::
*
;
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Variable
{
pub
name
:
String
,
pub
size
:
ByteSize
,
pub
is_temp
:
bool
,
}
\ No newline at end of file
pub
name
:
String
,
pub
size
:
ByteSize
,
pub
is_temp
:
bool
,
}
cwe_checker_rs/src/lib.rs
View file @
c11a21e9
...
...
@@ -11,10 +11,10 @@ pub mod abstract_domain;
pub
mod
analysis
;
pub
mod
bil
;
pub
mod
ffi
;
pub
mod
intermediate_representation
;
pub
mod
pcode
;
pub
mod
term
;
pub
mod
utils
;
pub
mod
pcode
;
pub
mod
intermediate_representation
;
mod
prelude
{
pub
use
apint
::
Width
;
...
...
cwe_checker_rs/src/pcode/expressions.rs
View file @
c11a21e9
use
crate
::
prelude
::
*
;
use
crate
::
term
::{
Term
,
Tid
};
use
crate
::
intermediate_representation
::
BinOpType
as
IrBinOpType
;
use
crate
::
intermediate_representation
::
ByteSize
;
use
crate
::
intermediate_representation
::
Variable
as
IrVariabl
e
;
use
crate
::
intermediate_representation
::
CastOpType
as
IrCastOpTyp
e
;
use
crate
::
intermediate_representation
::
Expression
as
IrExpression
;
use
crate
::
intermediate_representation
::
BinOpType
as
IrBinOpType
;
use
crate
::
intermediate_representation
::
UnOpType
as
IrUnOpType
;
use
crate
::
intermediate_representation
::
CastOpType
as
IrCastOpType
;
use
crate
::
intermediate_representation
::
Variable
as
IrVariable
;
use
crate
::
prelude
::
*
;
use
crate
::
term
::{
Term
,
Tid
};
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Variable
{
pub
name
:
Option
<
String
>
,
pub
value
:
Option
<
String
>
,
pub
size
:
ByteSize
,
pub
is_virtual
:
bool
,
pub
name
:
Option
<
String
>
,
pub
value
:
Option
<
String
>
,
pub
size
:
ByteSize
,
pub
is_virtual
:
bool
,
}
impl
From
<
Variable
>
for
IrVariable
{
fn
from
(
pcode_var
:
Variable
)
->
IrVariable
{
IrVariable
{
name
:
pcode_var
.name
.unwrap
(),
size
:
pcode_var
.size
,
is_temp
:
pcode_var
.is_virtual
,
// TODO: rename `pcode_var.is_virtual` to `is_temp`
fn
from
(
pcode_var
:
Variable
)
->
IrVariable
{
IrVariable
{
name
:
pcode_var
.name
.unwrap
(),
size
:
pcode_var
.size
,
is_temp
:
pcode_var
.is_virtual
,
// TODO: rename `pcode_var.is_virtual` to `is_temp`
}
}
}
}
impl
From
<
Variable
>
for
IrExpression
{
fn
from
(
pcode_var
:
Variable
)
->
IrExpression
{
match
(
&
pcode_var
.name
,
&
pcode_var
.value
)
{
(
Some
(
_name
),
None
)
=>
IrExpression
::
Var
(
pcode_var
.into
()),
(
None
,
Some
(
hex_value
))
=>
{
// TODO: Implement parsing for large hex values.
if
pcode_var
.size
>
8
.into
()
{
panic!
(
"Parsing of immediates greater than 8 bytes not yet implemented: {}"
,
hex_value
);
fn
from
(
pcode_var
:
Variable
)
->
IrExpression
{
match
(
&
pcode_var
.name
,
&
pcode_var
.value
)
{
(
Some
(
_name
),
None
)
=>
IrExpression
::
Var
(
pcode_var
.into
()),
(
None
,
Some
(
hex_value
))
=>
{
// TODO: Implement parsing for large hex values.
if
u64
::
from
(
pcode_var
.size
)
>
8
{
panic!
(
"Parsing of immediates greater than 8 bytes not yet implemented: {}"
,
hex_value
);
}
let
val
:
u64
=
u64
::
from_str_radix
(
&
hex_value
,
16
)
.unwrap
();
let
mut
bitvector
:
Bitvector
=
Bitvector
::
from_u64
(
val
);
bitvector
.truncate
(
pcode_var
.size
)
.unwrap
();
IrExpression
::
Const
(
bitvector
)
}
_
=>
panic!
(),
}
let
val
:
u64
=
u64
::
from_str_radix
(
&
hex_value
,
16
)
.unwrap
();
let
mut
bitvector
:
Bitvector
=
Bitvector
::
from_u64
(
val
);
bitvector
.truncate
(
pcode_var
.size
)
.unwrap
();
IrExpression
::
Const
(
bitvector
)
},
_
=>
panic!
(),
}
}
}
impl
From
<
Variable
>
for
ByteSize
{
fn
from
(
pcode_var
:
Variable
)
->
ByteSize
{
match
(
&
pcode_var
.name
,
&
pcode_var
.value
)
{
(
None
,
Some
(
hex_value
))
=>
{
// TODO: Implement parsing for large hex values.
if
pcode_var
.size
>
8
.into
()
{
panic!
(
"Parsing of immediates greater than 8 bytes not yet implemented: {}"
,
hex_value
);
fn
from
(
pcode_var
:
Variable
)
->
ByteSize
{
match
(
&
pcode_var
.name
,
&
pcode_var
.value
)
{
(
None
,
Some
(
hex_value
))
=>
{
// TODO: Implement parsing for large hex values.
if
u64
::
from
(
pcode_var
.size
)
>
8
{
panic!
(
"Parsing of immediates greater than 8 bytes not yet implemented: {}"
,
hex_value
);
}
let
val
:
u64
=
u64
::
from_str_radix
(
&
hex_value
,
16
)
.unwrap
();
val
.into
()
}
_
=>
panic!
(),
}
let
val
:
u64
=
u64
::
from_str_radix
(
&
hex_value
,
16
)
.unwrap
();
val
.into
()
},
_
=>
panic!
(),
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Expression
{
pub
mnemonic
:
ExpressionType
,
pub
input0
:
Option
<
Variable
>
,
pub
input1
:
Option
<
Variable
>
,
pub
input2
:
Option
<
Variable
>
,
}
impl
From
<
Expression
>
for
IrExpression
{
fn
from
(
expr
:
Expression
)
->
IrExpression
{
match
expr
.mnemonic
{
_
=>
todo!
(),
}
}
pub
mnemonic
:
ExpressionType
,
pub
input0
:
Option
<
Variable
>
,
pub
input1
:
Option
<
Variable
>
,
pub
input2
:
Option
<
Variable
>
,
}
#[allow(non_camel_case_types)]
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
pub
enum
ExpressionType
{
COPY
,
LOAD
,
STORE
,
PIECE
,
SUBPIECE
,
COPY
,
LOAD
,
STORE
,
PIECE
,
SUBPIECE
,
INT_EQUAL
,
INT_NOTEQUAL
,
INT_LESS
,
INT_SLESS
,
INT_LESSEQUAL
,
INT_SLESSEQUAL
,
INT_ADD
,
INT_SUB
,
INT_CARRY
,
INT_SCARRY
,
INT_SBORROW
,
INT_XOR
,
INT_AND
,
INT_OR
,
INT_LEFT
,
INT_RIGHT
,
INT_SRIGHT
,
INT_MULT
,
INT_DIV
,
INT_REM
,
INT_SDIV
,
INT_SREM
,
INT_EQUAL
,
INT_NOTEQUAL
,
INT_LESS
,
INT_SLESS
,
INT_ADD
,
INT_SUB
,
BOOL_XOR
,
BOOL_AND
,
BOOL_OR
,
INT_CARRY
,
INT_SCARRY
,
INT_SBORROW
,
INT_XOR
,
INT_AND
,
INT_OR
,
FLOAT_EQUAL
,
FLOAT_NOTEQUAL
,
FLOAT_LESS
,
FLOAT_LESSEQUAL
,
INT_LEFT
,
INT_RIGHT
,
INT_SRIGHT
,
INT_MULT
,
INT_DIV
,
FLOAT_ADD
,
FLOAT_SUB
,
FLOAT_MULT
,
FLOAT_DIV
,
INT_REM
,
INT_SDIV
,
INT_SREM
,
BOOL_XOR
,
BOOL_AND
,
BOOL_OR
,
FLOAT_EQUAL
,
FLOAT_NOTEQUAL
,
FLOAT_LESS
,
FLOAT_LESSEQUAL
,
FLOAT_ADD
,
FLOAT_SUB
,
FLOAT_MULT
,
FLOAT_DIV
,
INT_NEGATE
,
INT_2COMP
,
BOOL_NEGATE
,
INT_NEGATE
,
INT_2COMP
,
BOOL_NEGATE
,
FLOAT_NEGATE
,
FLOAT_ABS
,
FLOAT_SQRT
,
FLOAT_CEIL
,
FLOAT_FLOOR
,
FLOAT_ROUND
,
FLOAT_NAN
,
FLOAT_NEGATE
,
FLOAT_ABS
,
FLOAT_SQRT
,
FLOAT_CEIL
,
FLOAT_FLOOR
,
FLOAT_ROUND
,
FLOAT_NAN
,
INT_ZEXT
,
INT_SEXT
,
INT2FLOAT
,
FLOAT2FLOAT
,
TRUNC
,
INT_ZEXT
,
INT_SEXT
,
INT2FLOAT
,
FLOAT2FLOAT
,
TRUNC
,
}
impl
From
<
ExpressionType
>
for
IrBinOpType
{
fn
from
(
expr_type
:
ExpressionType
)
->
IrBinOpType
{
use
ExpressionType
::
*
;
match
expr_type
{
PIECE
=>
IrBinOpType
::
Piece
,
INT_EQUAL
=>
IrBinOpType
::
IntEqual
,
INT_NOTEQUAL
=>
IrBinOpType
::
IntNotEqual
,
INT_LESS
=>
IrBinOpType
::
IntLess
,
INT_SLESS
=>
IrBinOpType
::
IntSLess
,
INT_ADD
=>
IrBinOpType
::
IntAdd
,
INT_SUB
=>
IrBinOpType
::
IntSub
,
fn
from
(
expr_type
:
ExpressionType
)
->
IrBinOpType
{
use
ExpressionType
::
*
;
use
IrBinOpType
::
*
;
match
expr_type
{
PIECE
=>
IrBinOpType
::
Piece
,
INT_EQUAL
=>
IrBinOpType
::
IntEqual
,
INT_NOTEQUAL
=>
IrBinOpType
::
IntNotEqual
,
INT_LESS
=>
IrBinOpType
::
IntLess
,
INT_SLESS
=>
IrBinOpType
::
IntSLess
,
INT_LESSEQUAL
=>
IntLessEqual
,
INT_SLESSEQUAL
=>
IntSLessEqual
,
INT_CARRY
=>
IrBinOpType
::
IntCarry
,
INT_SCARRY
=>
IrBinOpType
::
IntSCarry
,
INT_SBORROW
=>
IrBinOpType
::
IntSBorrow
,
INT_XOR
=>
IrBinOpType
::
IntXOr
,
INT_AND
=>
IrBinOpType
::
IntAnd
,
INT_OR
=>
IrBinOpType
::
IntOr
,
INT_ADD
=>
IrBinOpType
::
IntAdd
,
INT_SUB
=>
IrBinOpType
::
IntSub
,
INT_LEFT
=>
IrBinOpType
::
IntLeft
,
INT_RIGHT
=>
IrBinOpType
::
IntRight
,
INT_SRIGHT
=>
IrBinOpType
::
IntSRight
,
INT_MULT
=>
IrBinOpType
::
IntMult
,
INT_DIV
=>
IrBinOpType
::
IntDiv
,
INT_CARRY
=>
IrBinOpType
::
IntCarry
,
INT_SCARRY
=>
IrBinOpType
::
IntSCarry
,
INT_SBORROW
=>
IrBinOpType
::
IntSBorrow
,
INT_XOR
=>
IrBinOpType
::
IntXOr
,
INT_AND
=>
IrBinOpType
::
IntAnd
,
INT_OR
=>
IrBinOpType
::
IntOr
,
INT_REM
=>
IrBinOpType
::
IntRem
,
INT_SDIV
=>
IrBinOpType
::
IntSDiv
,
INT_SREM
=>
IrBinOpType
::
IntSRem
,
BOOL_XOR
=>
IrBinOpType
::
BoolXOr
,
BOOL_AND
=>
IrBinOpType
::
BoolAnd
,
INT_LEFT
=>
IrBinOpType
::
IntLeft
,
INT_RIGHT
=>
IrBinOpType
::
IntRight
,
INT_SRIGHT
=>
IrBinOpType
::
IntSRight
,
INT_MULT
=>
IrBinOpType
::
IntMult
,
INT_DIV
=>
IrBinOpType
::
IntDiv
,
BOOL_OR
=>
IrBinOpType
::
BoolOr
,
FLOAT_EQUAL
=>
IrBinOpType
::
FloatEqual
,
FLOAT_NOTEQUAL
=>
IrBinOpType
::
FloatNotEqual
,
FLOAT_LESS
=>
IrBinOpType
::
FloatLess
,
FLOAT_LESSEQUAL
=>
IrBinOpType
::
FloatLessEqual
,
INT_REM
=>
IrBinOpType
::
IntRem
,
INT_SDIV
=>
IrBinOpType
::
IntSDiv
,
INT_SREM
=>
IrBinOpType
::
IntSRem
,
BOOL_XOR
=>
IrBinOpType
::
BoolXOr
,
BOOL_AND
=>
IrBinOpType
::
BoolAnd
,
FLOAT_ADD
=>
IrBinOpType
::
FloatAdd
,
FLOAT_SUB
=>
IrBinOpType
::
FloatSub
,
FLOAT_MULT
=>
IrBinOpType
::
FloatMult
,
FLOAT_DIV
=>
IrBinOpType
::
FloatDiv
,
BOOL_OR
=>
IrBinOpType
::
BoolOr
,
FLOAT_EQUAL
=>
IrBinOpType
::
FloatEqual
,
FLOAT_NOTEQUAL
=>
IrBinOpType
::
FloatNotEqual
,
FLOAT_LESS
=>
IrBinOpType
::
FloatLess
,
FLOAT_LESSEQUAL
=>
IrBinOpType
::
FloatLessEqual
,
_
=>
panic!
(),
FLOAT_ADD
=>
IrBinOpType
::
FloatAdd
,
FLOAT_SUB
=>
IrBinOpType
::
FloatSub
,
FLOAT_MULT
=>
IrBinOpType
::
FloatMult
,
FLOAT_DIV
=>
IrBinOpType
::
FloatDiv
,
_
=>
panic!
(),
}
}
}
}
impl
From
<
ExpressionType
>
for
IrUnOpType
{
fn
from
(
expr_type
:
ExpressionType
)
->
IrUnOpType
{
use
ExpressionType
::
*
;
match
expr_type
{
INT_NEGATE
=>
IrUnOpType
::
IntNegate
,
INT_2COMP
=>
IrUnOpType
::
Int2Comp
,
BOOL_NEGATE
=>
IrUnOpType
::
BoolNegate
,
FLOAT_NEGATE
=>
IrUnOpType
::
FloatNegate
,
FLOAT_ABS
=>
IrUnOpType
::
FloatAbs
,
FLOAT_SQRT
=>
IrUnOpType
::
FloatSqrt
,
FLOAT_CEIL
=>
IrUnOpType
::
FloatCeil
,
FLOAT_FLOOR
=>
IrUnOpType
::
FloatFloor
,
FLOAT_ROUND
=>
IrUnOpType
::
FloatRound
,
FLOAT_NAN
=>
IrUnOpType
::
FloatNaN
,
_
=>
panic!
(),
fn
from
(
expr_type
:
ExpressionType
)
->
IrUnOpType
{
use
ExpressionType
::
*
;
match
expr_type
{
INT_NEGATE
=>
IrUnOpType
::
IntNegate
,
INT_2COMP
=>
IrUnOpType
::
Int2Comp
,
BOOL_NEGATE
=>
IrUnOpType
::
BoolNegate
,
FLOAT_NEGATE
=>
IrUnOpType
::
FloatNegate
,
FLOAT_ABS
=>
IrUnOpType
::
FloatAbs
,
FLOAT_SQRT
=>
IrUnOpType
::
FloatSqrt
,
FLOAT_CEIL
=>
IrUnOpType
::
FloatCeil
,
FLOAT_FLOOR
=>
IrUnOpType
::
FloatFloor
,
FLOAT_ROUND
=>
IrUnOpType
::
FloatRound
,
FLOAT_NAN
=>
IrUnOpType
::
FloatNaN
,
_
=>
panic!
(),
}
}
}
}
impl
From
<
ExpressionType
>
for
IrCastOpType
{
fn
from
(
expr_type
:
ExpressionType
)
->
IrCastOpType
{
use
ExpressionType
::
*
;
match
expr_type
{
INT_ZEXT
=>
IrCastOpType
::
IntZExt
,
INT_SEXT
=>
IrCastOpType
::
IntSExt
,
INT2FLOAT
=>
IrCastOpType
::
Int2Float
,
FLOAT2FLOAT
=>
IrCastOpType
::
Float2Float
,
TRUNC
=>
IrCastOpType
::
Trunc
,
_
=>
panic!
(),
fn
from
(
expr_type
:
ExpressionType
)
->
IrCastOpType
{
use
ExpressionType
::
*
;
match
expr_type
{
INT_ZEXT
=>
IrCastOpType
::
IntZExt
,
INT_SEXT
=>
IrCastOpType
::
IntSExt
,
INT2FLOAT
=>
IrCastOpType
::
Int2Float
,
FLOAT2FLOAT
=>
IrCastOpType
::
Float2Float
,
TRUNC
=>
IrCastOpType
::
Trunc
,
_
=>
panic!
(),
}
}
}
}
#[cfg(test)]
mod
tests
{
use
super
::
*
;
use
super
::
*
;
#[test]
fn
variable_deserialization
()
{
let
_
:
Variable
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
variable_deserialization
()
{
let
_
:
Variable
=
serde_json
::
from_str
(
r
#
"
{
"
name
": "
RSP
",
"
size
": 8,
"
is_virtual
": false
}
"
#
,
)
.unwrap
();
}
)
.unwrap
();
}
#[test]
fn
expression_deserialization
()
{
let
_
:
Expression
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
expression_deserialization
()
{
let
_
:
Expression
=
serde_json
::
from_str
(
r
#
"
{
"
mnemonic
": "
INT_SUB
",
"
input0
": {
...
...
@@ -257,7 +263,7 @@ mod tests {
}
}
"
#
,
)
.unwrap
();
}
}
\ No newline at end of file
)
.unwrap
();
}
}
cwe_checker_rs/src/pcode/mod.rs
View file @
c11a21e9
...
...
@@ -7,4 +7,3 @@ mod expressions;
pub
use
expressions
::
*
;
mod
term
;
pub
use
term
::
*
;
cwe_checker_rs/src/pcode/term.rs
View file @
c11a21e9
use
super
::{
Expression
,
Variable
};
use
crate
::
intermediate_representation
::
Def
as
IrDef
;
use
crate
::
intermediate_representation
::
Expression
as
IrExpression
;
use
crate
::
intermediate_representation
::
Jmp
as
IrJmp
;
use
crate
::
prelude
::
*
;
use
crate
::
term
::{
Term
,
Tid
};
// TODO: Handle the case where an indirect tail call is represented by CALLIND plus RETURN
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Call
{
pub
target
:
Label
,
pub
return_
:
Option
<
Label
>
,
pub
target
:
Label
,
pub
return_
:
Option
<
Label
>
,
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Jmp
{
pub
mnemonic
:
JmpType
,
pub
goto
:
Option
<
Label
>
,
pub
call
:
Option
<
Call
>
,
pub
condition
:
Option
<
Expression
>
,
pub
mnemonic
:
JmpType
,
pub
goto
:
Option
<
Label
>
,
pub
call
:
Option
<
Call
>
,
pub
condition
:
Option
<
Variable
>
,
}
// TODO: CALLOTHER is still missing!
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone,
Copy)]
pub
enum
JmpType
{
BRANCH
,
CBRANCH
,
BRANCHIND
,
CALL
,
CALLIND
,
RETURN
,
BRANCH
,
CBRANCH
,
BRANCHIND
,
CALL
,
CALLIND
,
RETURN
,
}
impl
From
<
Jmp
>
for
IrJmp
{
fn
from
(
jmp
:
Jmp
)
->
IrJmp
{
use
JmpType
::
*
;
let
unwrap_label_direct
=
|
label
|
{
if
let
Label
::
Direct
(
tid
)
=
label
{
tid
}
else
{
panic!
()
}
};
let
unwrap_label_indirect
=
|
label
|
{
if
let
Label
::
Indirect
(
expr
)
=
label
{
expr
}
else
{
panic!
()
}
};
match
jmp
.mnemonic
{
BRANCH
=>
IrJmp
::
Branch
(
unwrap_label_direct
(
jmp
.goto
.unwrap
())),
CBRANCH
=>
IrJmp
::
CBranch
{
target
:
unwrap_label_direct
(
jmp
.goto
.unwrap
()),
condition
:
jmp
.condition
.unwrap
()
.into
(),
},
BRANCHIND
=>
IrJmp
::
BranchInd
(
unwrap_label_indirect
(
jmp
.goto
.unwrap
())
.into
()),
CALL
=>
{
let
call
=
jmp
.call
.unwrap
();
IrJmp
::
Call
{
target
:
unwrap_label_direct
(
call
.target
),
return_
:
call
.return_
.map
(
unwrap_label_direct
),
}
}
CALLIND
=>
{
let
call
=
jmp
.call
.unwrap
();
IrJmp
::
CallInd
{
target
:
unwrap_label_indirect
(
call
.target
)
.into
(),
return_
:
call
.return_
.map
(
unwrap_label_direct
),
}
}
RETURN
=>
IrJmp
::
Return
(
unwrap_label_indirect
(
jmp
.goto
.unwrap
())
.into
()),
}
}
}
// TODO: Remove since code duplication?
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
enum
Label
{
Direct
(
Tid
),
Indirect
(
Variable
),
Direct
(
Tid
),
Indirect
(
Variable
),
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Def
{
pub
lhs
:
Variable
,
pub
rhs
:
Expression
,
pub
lhs
:
Variable
,
pub
rhs
:
Expression
,
}
impl
From
<
Def
>
for
IrDef
{
fn
from
(
def
:
Def
)
->
IrDef
{
use
super
::
ExpressionType
::
*
;
match
def
.rhs.mnemonic
{
COPY
=>
IrDef
::
Assign
{
var
:
def
.lhs
.into
(),
value
:
IrExpression
::
from
(
def
.rhs
),
},
LOAD
=>
IrDef
::
Load
{
var
:
def
.lhs
.into
(),
address
:
def
.rhs.input1
.unwrap
()
.into
(),
},
STORE
=>
IrDef
::
Store
{
address
:
def
.rhs.input1
.unwrap
()
.into
(),
value
:
def
.rhs.input2
.unwrap
()
.into
(),
},
PIECE
|
INT_EQUAL
|
INT_NOTEQUAL
|
INT_LESS
|
INT_SLESS
|
INT_ADD
|
INT_SUB
|
INT_CARRY
|
INT_SCARRY
|
INT_SBORROW
|
INT_XOR
|
INT_AND
|
INT_OR
|
INT_LEFT
|
INT_RIGHT
|
INT_SRIGHT
|
INT_MULT
|
INT_DIV
|
INT_REM
|
INT_SDIV
|
INT_SREM
|
BOOL_XOR
|
BOOL_AND
|
BOOL_OR
|
FLOAT_EQUAL
|
FLOAT_NOTEQUAL
|
FLOAT_LESS
|
FLOAT_LESSEQUAL
|
FLOAT_ADD
|
FLOAT_SUB
|
FLOAT_MULT
|
FLOAT_DIV
=>
IrDef
::
Assign
{
var
:
def
.lhs
.into
(),
value
:
IrExpression
::
BinOp
{
op
:
def
.rhs.mnemonic
.into
(),
lhs
:
Box
::
new
(
def
.rhs.input0
.unwrap
()
.into
()),
rhs
:
Box
::
new
(
def
.rhs.input1
.unwrap
()
.into
()),
},
},
SUBPIECE
=>
IrDef
::
Assign
{
var
:
def
.lhs
.clone
()
.into
(),
value
:
IrExpression
::
Subpiece
{
low_byte
:
def
.rhs.input1
.unwrap
()
.into
(),
size
:
def
.lhs.size
,
arg
:
Box
::
new
(
def
.rhs.input0
.unwrap
()
.into
()),
},
},
INT_NEGATE
|
INT_2COMP
|
BOOL_NEGATE
|
FLOAT_NEGATE
|
FLOAT_ABS
|
FLOAT_SQRT
|
FLOAT_CEIL
|
FLOAT_FLOOR
|
FLOAT_ROUND
|
FLOAT_NAN
=>
IrDef
::
Assign
{
var
:
def
.lhs
.into
(),
value
:
IrExpression
::
UnOp
{
op
:
def
.rhs.mnemonic
.into
(),
arg
:
Box
::
new
(
def
.rhs.input0
.unwrap
()
.into
()),
},
},
INT_ZEXT
|
INT_SEXT
|
INT2FLOAT
|
FLOAT2FLOAT
|
TRUNC
=>
IrDef
::
Assign
{
var
:
def
.lhs
.clone
()
.into
(),
value
:
IrExpression
::
Cast
{
op
:
def
.rhs.mnemonic
.into
(),
size
:
def
.lhs.size
,
arg
:
Box
::
new
(
def
.rhs.input0
.unwrap
()
.into
()),
},
},
fn
from
(
def
:
Def
)
->
IrDef
{
use
super
::
ExpressionType
::
*
;
match
def
.rhs.mnemonic
{
COPY
=>
IrDef
::
Assign
{
var
:
def
.lhs
.into
(),
value
:
def
.rhs.input0
.unwrap
()
.into
(),
},
LOAD
=>
IrDef
::
Load
{
var
:
def
.lhs
.into
(),
address
:
def
.rhs.input1
.unwrap
()
.into
(),
},
STORE
=>
IrDef
::
Store
{
address
:
def
.rhs.input1
.unwrap
()
.into
(),
value
:
def
.rhs.input2
.unwrap
()
.into
(),
},
PIECE
|
INT_EQUAL
|
INT_NOTEQUAL
|
INT_LESS
|
INT_SLESS
|
INT_LESSEQUAL
|
INT_SLESSEQUAL
|
INT_ADD
|
INT_SUB
|
INT_CARRY
|
INT_SCARRY
|
INT_SBORROW
|
INT_XOR
|
INT_AND
|
INT_OR
|
INT_LEFT
|
INT_RIGHT
|
INT_SRIGHT
|
INT_MULT
|
INT_DIV
|
INT_REM
|
INT_SDIV
|
INT_SREM
|
BOOL_XOR
|
BOOL_AND
|
BOOL_OR
|
FLOAT_EQUAL
|
FLOAT_NOTEQUAL
|
FLOAT_LESS
|
FLOAT_LESSEQUAL
|
FLOAT_ADD
|
FLOAT_SUB
|
FLOAT_MULT
|
FLOAT_DIV
=>
IrDef
::
Assign
{
var
:
def
.lhs
.into
(),
value
:
IrExpression
::
BinOp
{
op
:
def
.rhs.mnemonic
.into
(),
lhs
:
Box
::
new
(
def
.rhs.input0
.unwrap
()
.into
()),
rhs
:
Box
::
new
(
def
.rhs.input1
.unwrap
()
.into
()),
},
},
SUBPIECE
=>
IrDef
::
Assign
{
var
:
def
.lhs
.clone
()
.into
(),
value
:
IrExpression
::
Subpiece
{
low_byte
:
def
.rhs.input1
.unwrap
()
.into
(),
size
:
def
.lhs.size
,
arg
:
Box
::
new
(
def
.rhs.input0
.unwrap
()
.into
()),
},
},
INT_NEGATE
|
INT_2COMP
|
BOOL_NEGATE
|
FLOAT_NEGATE
|
FLOAT_ABS
|
FLOAT_SQRT
|
FLOAT_CEIL
|
FLOAT_FLOOR
|
FLOAT_ROUND
|
FLOAT_NAN
=>
IrDef
::
Assign
{
var
:
def
.lhs
.into
(),
value
:
IrExpression
::
UnOp
{
op
:
def
.rhs.mnemonic
.into
(),
arg
:
Box
::
new
(
def
.rhs.input0
.unwrap
()
.into
()),
},
},
INT_ZEXT
|
INT_SEXT
|
INT2FLOAT
|
FLOAT2FLOAT
|
TRUNC
=>
IrDef
::
Assign
{
var
:
def
.lhs
.clone
()
.into
(),
value
:
IrExpression
::
Cast
{
op
:
def
.rhs.mnemonic
.into
(),
size
:
def
.lhs.size
,
arg
:
Box
::
new
(
def
.rhs.input0
.unwrap
()
.into
()),
},
},
}
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Blk
{
pub
defs
:
Vec
<
Term
<
Def
>>
,
pub
jmps
:
Vec
<
Term
<
Jmp
>>
,
pub
defs
:
Vec
<
Term
<
Def
>>
,
pub
jmps
:
Vec
<
Term
<
Jmp
>>
,
}
// TODO: We need a unit test for stack parameter (that use location instead of var)!
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Arg
{
pub
var
:
Option
<
Variable
>
,
pub
location
:
Option
<
Expression
>
,
pub
intent
:
ArgIntent
,
pub
var
:
Option
<
Variable
>
,
pub
location
:
Option
<
Expression
>
,
pub
intent
:
ArgIntent
,
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
enum
ArgIntent
{
INPUT
,
OUTPUT
,
BOTH
,
INPUT
,
OUTPUT
,
BOTH
,
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Sub
{
pub
name
:
String
,
pub
blocks
:
Vec
<
Term
<
Blk
>>
,
pub
name
:
String
,
pub
blocks
:
Vec
<
Term
<
Blk
>>
,
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
ExternSymbol
{
pub
tid
:
Tid
,
pub
address
:
String
,
pub
name
:
String
,
pub
calling_convention
:
Option
<
String
>
,
pub
arguments
:
Vec
<
Arg
>
,
pub
tid
:
Tid
,
pub
address
:
String
,
pub
name
:
String
,
pub
calling_convention
:
Option
<
String
>
,
pub
arguments
:
Vec
<
Arg
>
,
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Program
{
pub
subs
:
Vec
<
Term
<
Sub
>>
,
pub
extern_symbols
:
Vec
<
ExternSymbol
>
,
pub
entry_points
:
Vec
<
Tid
>
,
pub
subs
:
Vec
<
Term
<
Sub
>>
,
pub
extern_symbols
:
Vec
<
ExternSymbol
>
,
pub
entry_points
:
Vec
<
Tid
>
,
}
#[cfg(test)]
mod
tests
{
use
super
::
*
;
use
super
::
*
;
#[test]
fn
def_deserialization
()
{
let
def
:
Def
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
def_deserialization
()
{
let
def
:
Def
=
serde_json
::
from_str
(
r
#
"
{
"
lhs
": {
"
name
": "
CF
",
...
...
@@ -169,15 +217,15 @@ mod tests {
}
}
"
#
,
)
.unwrap
();
let
_
:
IrDef
=
def
.into
();
}
)
.unwrap
();
let
_
:
IrDef
=
def
.into
();
}
#[test]
fn
label_deserialization
()
{
let
_
:
Label
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
label_deserialization
()
{
let
_
:
Label
=
serde_json
::
from_str
(
r
#
"
{
"
Direct
": {
"
id
": "
blk_00103901
",
...
...
@@ -185,10 +233,10 @@ mod tests {
}
}
"
#
,
)
.unwrap
();
let
_
:
Label
=
serde_json
::
from_str
(
r
#
"
)
.unwrap
();
let
_
:
Label
=
serde_json
::
from_str
(
r
#
"
{
"
Indirect
": {
"
name
": "
00109
ef0
",
...
...
@@ -197,14 +245,14 @@ mod tests {
}
}
"
#
,
)
.unwrap
();
}
)
.unwrap
();
}
#[test]
fn
jmp_deserialization
()
{
let
_
:
Term
<
Jmp
>
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
jmp_deserialization
()
{
let
_
:
Term
<
Jmp
>
=
serde_json
::
from_str
(
r
#
"
{
"
tid
": {
"
id
": "
instr_00102014_2
",
...
...
@@ -231,14 +279,14 @@ mod tests {
}
}
"
#
,
)
.unwrap
();
}
)
.unwrap
();
}
#[test]
fn
blk_deserialization
()
{
let
_
:
Term
<
Blk
>
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
blk_deserialization
()
{
let
_
:
Term
<
Blk
>
=
serde_json
::
from_str
(
r
#
"
{
"
tid
": {
"
id
": "
blk_00101000
",
...
...
@@ -250,14 +298,14 @@ mod tests {
}
}
"
#
,
)
.unwrap
();
}
)
.unwrap
();
}
#[test]
fn
arg_deserialization
()
{
let
_
:
Arg
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
arg_deserialization
()
{
let
_
:
Arg
=
serde_json
::
from_str
(
r
#
"
{
"
var
": {
"
name
": "
RDI
",
...
...
@@ -267,14 +315,14 @@ mod tests {
"
intent
": "
INPUT
"
}
"
#
,
)
.unwrap
();
}
)
.unwrap
();
}
#[test]
fn
sub_deserialization
()
{
let
_
:
Term
<
Sub
>
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
sub_deserialization
()
{
let
_
:
Term
<
Sub
>
=
serde_json
::
from_str
(
r
#
"
{
"
tid
": {
"
id
": "
sub_00101000
",
...
...
@@ -286,14 +334,14 @@ mod tests {
}
}
"
#
,
)
.unwrap
();
}
)
.unwrap
();
}
#[test]
fn
extern_symbol_deserialization
()
{
let
_
:
ExternSymbol
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
extern_symbol_deserialization
()
{
let
_
:
ExternSymbol
=
serde_json
::
from_str
(
r
#
"
{
"
tid
": {
"
id
": "
sub_0010b020
",
...
...
@@ -338,14 +386,14 @@ mod tests {
]
}
"
#
,
)
.unwrap
();
}
)
.unwrap
();
}
#[test]
fn
program_deserialization
()
{
let
_
:
Term
<
Program
>
=
serde_json
::
from_str
(
r
#
"
#[test]
fn
program_deserialization
()
{
let
_
:
Term
<
Program
>
=
serde_json
::
from_str
(
r
#
"
{
"
tid
": {
"
id
": "
prog_00101000
",
...
...
@@ -358,7 +406,7 @@ mod tests {
}
}
"
#
,
)
.unwrap
();
}
)
.unwrap
();
}
}
cwe_checker_rs/src/term/mod.rs
View file @
c11a21e9
use
crate
::
bil
::
*
;
use
crate
::
intermediate_representation
::
Def
as
IrDef
;
use
crate
::
intermediate_representation
::
Expression
as
IrExpression
;
use
crate
::
intermediate_representation
::
Jmp
as
IrJmp
;
use
serde
::{
Deserialize
,
Serialize
};
pub
mod
symbol
;
...
...
@@ -37,6 +40,80 @@ pub struct Def {
pub
rhs
:
Expression
,
}
impl
Def
{
fn
to_ir_defs
(
self
)
->
Vec
<
IrDef
>
{
match
self
.rhs
{
Expression
::
Load
{
address
,
..
}
=>
{
let
(
defs
,
cleaned_address
,
_
)
=
extract_loads_from_expression
(
*
address
,
0
);
let
mut
ir_defs
:
Vec
<
IrDef
>
=
defs
.into_iter
()
.map
(|
def
|
def
.to_ir_assignment
())
.collect
();
ir_defs
.push
(
IrDef
::
Load
{
address
:
cleaned_address
.into
(),
var
:
self
.lhs
.into
(),
});
ir_defs
}
Expression
::
Store
{
address
,
value
,
..
}
=>
{
let
(
mut
defs
,
cleaned_address
,
counter
)
=
extract_loads_from_expression
(
*
address
,
0
);
let
(
mut
more_defs
,
cleaned_value
,
_
)
=
extract_loads_from_expression
(
*
value
,
counter
);
defs
.append
(
&
mut
more_defs
);
let
mut
ir_defs
:
Vec
<
IrDef
>
=
defs
.into_iter
()
.map
(|
def
|
def
.to_ir_assignment
())
.collect
();
ir_defs
.push
(
IrDef
::
Store
{
address
:
cleaned_address
.into
(),
value
:
cleaned_value
.into
(),
});
ir_defs
}
Expression
::
IfThenElse
{
condition
,
true_exp
,
false_exp
,
}
=>
{
// We only match for conditional stores.
// Other usages of the `IfThenElse`-expression will result in panics.
let
(
address
,
value
)
=
match
(
*
true_exp
,
*
false_exp
)
{
(
Expression
::
Store
{
address
,
value
,
..
},
Expression
::
Var
(
var
))
|
(
Expression
::
Var
(
var
),
Expression
::
Store
{
address
,
value
,
..
})
if
var
==
self
.lhs
=>
{
(
address
,
value
)
}
_
=>
panic!
(),
};
let
(
mut
defs
,
_cleaned_condition
,
counter
)
=
extract_loads_from_expression
(
*
condition
,
0
);
let
(
mut
more_defs
,
cleaned_adress
,
counter
)
=
extract_loads_from_expression
(
*
address
,
counter
);
let
(
mut
even_more_defs
,
cleaned_value
,
_
)
=
extract_loads_from_expression
(
*
value
,
counter
);
defs
.append
(
&
mut
more_defs
);
defs
.append
(
&
mut
even_more_defs
);
let
mut
ir_defs
:
Vec
<
IrDef
>
=
defs
.into_iter
()
.map
(|
def
|
def
.to_ir_assignment
())
.collect
();
ir_defs
.push
(
IrDef
::
Store
{
address
:
cleaned_adress
.into
(),
value
:
IrExpression
::
Unknown
{
description
:
"BAP conditional store"
.into
(),
size
:
cleaned_value
.bitsize
()
.into
(),
},
});
ir_defs
}
_
=>
vec!
[
self
.to_ir_assignment
()],
}
}
fn
to_ir_assignment
(
self
)
->
IrDef
{
IrDef
::
Assign
{
var
:
self
.lhs
.into
(),
value
:
self
.rhs
.into
(),
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Jmp
{
pub
condition
:
Option
<
Expression
>
,
...
...
@@ -51,6 +128,38 @@ pub enum JmpKind {
Interrupt
{
value
:
isize
,
return_addr
:
Tid
},
}
impl
From
<
Jmp
>
for
IrJmp
{
fn
from
(
jmp
:
Jmp
)
->
IrJmp
{
match
jmp
.kind
{
JmpKind
::
Goto
(
Label
::
Direct
(
tid
))
=>
IrJmp
::
Branch
(
tid
),
JmpKind
::
Goto
(
Label
::
Indirect
(
expr
))
=>
IrJmp
::
BranchInd
(
expr
.into
()),
JmpKind
::
Return
(
Label
::
Indirect
(
expr
))
=>
IrJmp
::
Return
(
expr
.into
()),
JmpKind
::
Return
(
Label
::
Direct
(
_
))
=>
panic!
(),
JmpKind
::
Call
(
call
)
=>
{
let
return_
=
match
call
.return_
{
Some
(
Label
::
Direct
(
tid
))
=>
Some
(
tid
),
None
=>
None
,
_
=>
panic!
(),
};
match
call
.target
{
Label
::
Direct
(
tid
)
=>
IrJmp
::
Call
{
target
:
tid
,
return_
,
},
Label
::
Indirect
(
expr
)
=>
IrJmp
::
CallInd
{
target
:
expr
.into
(),
return_
,
},
}
}
JmpKind
::
Interrupt
{
value
,
return_addr
}
=>
IrJmp
::
CallOther
{
description
:
format!
(
"Interrupt {}"
,
value
),
return_
:
Some
(
return_addr
),
},
}
}
}
#[derive(Serialize,
Deserialize,
Debug,
PartialEq,
Eq,
Hash,
Clone)]
pub
struct
Call
{
pub
target
:
Label
,
...
...
@@ -168,6 +277,106 @@ impl ArgIntent {
}
}
fn
extract_loads_from_expression
(
expr
:
Expression
,
counter
:
u64
)
->
(
Vec
<
Def
>
,
Expression
,
u64
)
{
use
Expression
::
*
;
match
expr
{
Load
{
memory
,
address
,
endian
,
size
,
}
=>
{
let
(
mut
defs
,
cleaned_address
,
mut
counter
)
=
extract_loads_from_expression
(
*
address
,
counter
);
counter
+=
1
;
let
temp_var
=
Variable
{
name
:
format!
(
"temp_{}"
,
counter
),
type_
:
Type
::
Immediate
(
size
),
is_temp
:
true
,
};
defs
.push
(
Def
{
lhs
:
temp_var
.clone
(),
rhs
:
Load
{
memory
,
address
:
Box
::
new
(
cleaned_address
),
endian
,
size
,
},
});
(
defs
,
Var
(
temp_var
),
counter
)
}
Var
(
_
)
|
Const
(
_
)
|
Unknown
{
..
}
=>
(
Vec
::
new
(),
expr
,
counter
),
Store
{
..
}
|
Let
{
..
}
|
IfThenElse
{
..
}
=>
panic!
(),
BinOp
{
op
,
lhs
,
rhs
}
=>
{
let
(
mut
defs
,
cleaned_lhs
,
counter
)
=
extract_loads_from_expression
(
*
lhs
,
counter
);
let
(
mut
defs_rhs
,
cleaned_rhs
,
counter
)
=
extract_loads_from_expression
(
*
rhs
,
counter
);
defs
.append
(
&
mut
defs_rhs
);
(
defs
,
BinOp
{
op
,
lhs
:
Box
::
new
(
cleaned_lhs
),
rhs
:
Box
::
new
(
cleaned_rhs
),
},
counter
,
)
}
UnOp
{
op
,
arg
}
=>
{
let
(
defs
,
cleaned_arg
,
counter
)
=
extract_loads_from_expression
(
*
arg
,
counter
);
(
defs
,
UnOp
{
op
,
arg
:
Box
::
new
(
cleaned_arg
),
},
counter
,
)
}
Cast
{
kind
,
width
,
arg
}
=>
{
let
(
defs
,
cleaned_arg
,
counter
)
=
extract_loads_from_expression
(
*
arg
,
counter
);
(
defs
,
Cast
{
kind
,
width
,
arg
:
Box
::
new
(
cleaned_arg
),
},
counter
,
)
}
Extract
{
low_bit
,
high_bit
,
arg
,
}
=>
{
let
(
defs
,
cleaned_arg
,
counter
)
=
extract_loads_from_expression
(
*
arg
,
counter
);
(
defs
,
Extract
{
low_bit
,
high_bit
,
arg
:
Box
::
new
(
cleaned_arg
),
},
counter
,
)
}
Concat
{
left
,
right
}
=>
{
let
(
mut
defs
,
cleaned_left
,
counter
)
=
extract_loads_from_expression
(
*
left
,
counter
);
let
(
mut
defs_right
,
cleaned_right
,
counter
)
=
extract_loads_from_expression
(
*
right
,
counter
);
defs
.append
(
&
mut
defs_right
);
(
defs
,
Concat
{
left
:
Box
::
new
(
cleaned_left
),
right
:
Box
::
new
(
cleaned_right
),
},
counter
,
)
}
}
}
#[cfg(test)]
mod
tests
{
use
super
::
*
;
...
...
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