pub struct CfaState { /* private fields */ }
Implementations§
source§impl CfaState
impl CfaState
sourcepub fn is_bottom(&self) -> bool
pub fn is_bottom(&self) -> bool
Examples found in repository?
src/cfa.rs (line 170)
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
fn merge(&mut self, other: Self) -> bool {
if self.is_bottom() {
if !other.is_bottom() {
*self = other;
return true;
}
} else if !other.is_bottom() {
if self.stack != other.stack {
let s_len = self.stack.as_ref().unwrap().len();
let o_len = other.stack.as_ref().unwrap().len();
// Determine height of new stack
let m = cmp::min(s_len,o_len);
// Construct a new stack
let mut nstack = Vec::new();
// Perform stack merge
for i in (0..m).rev() {
let l = self.peek(i);
let r = other.peek(i);
nstack.push(l.merge(r));
}
// Update me
*self = CfaState{stack:Some(nstack)}
}
}
//
false
}
sourcepub fn push(self, val: Value) -> Self
pub fn push(self, val: Value) -> Self
Push an iterm onto this stack.
Examples found in repository?
src/cfa.rs (line 221)
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
fn transfer(self, insn: &Instruction) -> CfaState {
match insn {
STOP => BOTTOM,
// 0s: Stop and Arithmetic Operations
ADD|MUL|SUB|DIV|SDIV|MOD|SMOD|EXP|SIGNEXTEND => {
self.pop().pop().push(Value::Unknown)
}
ADDMOD|MULMOD => {
self.pop().pop().pop().push(Value::Unknown)
}
// 0s: Stop and Arithmetic Operations
ISZERO|NOT => {
self.pop().push(Value::Unknown)
}
// Binary Comparators
LT|GT|SLT|SGT|EQ => {
self.pop().pop().push(Value::Unknown)
}
// Binary bitwise operators
AND|OR|XOR|BYTE|SHL|SHR|SAR => {
self.pop().pop().push(Value::Unknown)
}
// 20s: Keccak256
// 30s: Environmental Information
CALLVALUE => self.push(Value::Unknown),
CALLDATALOAD => self.pop().push(Value::Unknown),
CALLDATASIZE => self.push(Value::Unknown),
// 40s: Block Information
// 50s: Stack, Memory, Storage and Flow Operations
POP => self.pop(),
MLOAD => self.pop().push(Value::Unknown),
MSTORE => self.pop().pop(),
SLOAD => self.pop().push(Value::Unknown),
SSTORE => self.pop().pop(),
JUMPI => self.pop().pop(),
JUMPDEST(_) => self, // nop
// 60 & 70s: Push Operations
PUSH(bytes) => {
let n = util::from_be_bytes(&bytes);
if n <= MAX_CODE_SIZE {
self.push(Value::Known(n as usize))
} else {
self.push(Value::Unknown)
}
}
// 80s: Duplicate Operations
DUP(n) => {
let m = (*n - 1) as usize;
let nth = self.peek(m);
self.push(nth)
}
// 90s: Swap Operations
SWAP(n) => {
let m = (*n - 1) as usize;
let x = self.peek(m);
let y = self.peek(0);
self.set(0,x).set(m,y)
}
// 90s: Exchange Operations
// a0s: Logging Operations
// f0s: System Operations
INVALID|JUMP|RETURN|REVERT|STOP => {
BOTTOM
}
_ => {
// This is a catch all to ensure no instructions are
// missed above.
panic!("unknown instruction ({:?})",insn);
}
}
}
sourcepub fn pop(self) -> Self
pub fn pop(self) -> Self
Pop an item of this stack, producing an updated state.
Examples found in repository?
src/cfa.rs (line 161)
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
fn branch(&self, pc: usize, insn: &Instruction) -> Self {
match insn {
JUMPI => self.clone().pop().pop(),
JUMP => self.clone().pop(),
_ => {
unreachable!()
}
}
}
fn merge(&mut self, other: Self) -> bool {
if self.is_bottom() {
if !other.is_bottom() {
*self = other;
return true;
}
} else if !other.is_bottom() {
if self.stack != other.stack {
let s_len = self.stack.as_ref().unwrap().len();
let o_len = other.stack.as_ref().unwrap().len();
// Determine height of new stack
let m = cmp::min(s_len,o_len);
// Construct a new stack
let mut nstack = Vec::new();
// Perform stack merge
for i in (0..m).rev() {
let l = self.peek(i);
let r = other.peek(i);
nstack.push(l.merge(r));
}
// Update me
*self = CfaState{stack:Some(nstack)}
}
}
//
false
}
fn top(&self) -> usize {
// Extract the stack. We assume for now we are not bottom.
let stack = self.stack.as_ref().unwrap();
// Inspect last element. Again, we assume for now this
// exists.
match stack.last().unwrap() {
Value::Known(n) => *n,
Value::Unknown => {
// At some point, this will need to be fixed.
panic!("Unknown value encountered");
}
}
}
// ============================================================================
// Abstract Instruction Semantics (stack)
// ============================================================================
/// Update an abstract state with the effects of a given instruction.
fn transfer(self, insn: &Instruction) -> CfaState {
match insn {
STOP => BOTTOM,
// 0s: Stop and Arithmetic Operations
ADD|MUL|SUB|DIV|SDIV|MOD|SMOD|EXP|SIGNEXTEND => {
self.pop().pop().push(Value::Unknown)
}
ADDMOD|MULMOD => {
self.pop().pop().pop().push(Value::Unknown)
}
// 0s: Stop and Arithmetic Operations
ISZERO|NOT => {
self.pop().push(Value::Unknown)
}
// Binary Comparators
LT|GT|SLT|SGT|EQ => {
self.pop().pop().push(Value::Unknown)
}
// Binary bitwise operators
AND|OR|XOR|BYTE|SHL|SHR|SAR => {
self.pop().pop().push(Value::Unknown)
}
// 20s: Keccak256
// 30s: Environmental Information
CALLVALUE => self.push(Value::Unknown),
CALLDATALOAD => self.pop().push(Value::Unknown),
CALLDATASIZE => self.push(Value::Unknown),
// 40s: Block Information
// 50s: Stack, Memory, Storage and Flow Operations
POP => self.pop(),
MLOAD => self.pop().push(Value::Unknown),
MSTORE => self.pop().pop(),
SLOAD => self.pop().push(Value::Unknown),
SSTORE => self.pop().pop(),
JUMPI => self.pop().pop(),
JUMPDEST(_) => self, // nop
// 60 & 70s: Push Operations
PUSH(bytes) => {
let n = util::from_be_bytes(&bytes);
if n <= MAX_CODE_SIZE {
self.push(Value::Known(n as usize))
} else {
self.push(Value::Unknown)
}
}
// 80s: Duplicate Operations
DUP(n) => {
let m = (*n - 1) as usize;
let nth = self.peek(m);
self.push(nth)
}
// 90s: Swap Operations
SWAP(n) => {
let m = (*n - 1) as usize;
let x = self.peek(m);
let y = self.peek(0);
self.set(0,x).set(m,y)
}
// 90s: Exchange Operations
// a0s: Logging Operations
// f0s: System Operations
INVALID|JUMP|RETURN|REVERT|STOP => {
BOTTOM
}
_ => {
// This is a catch all to ensure no instructions are
// missed above.
panic!("unknown instruction ({:?})",insn);
}
}
}
sourcepub fn peek(&self, n: usize) -> Value
pub fn peek(&self, n: usize) -> Value
Perk nth item on the stack (where 0
is top).
Examples found in repository?
src/cfa.rs (line 185)
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
fn merge(&mut self, other: Self) -> bool {
if self.is_bottom() {
if !other.is_bottom() {
*self = other;
return true;
}
} else if !other.is_bottom() {
if self.stack != other.stack {
let s_len = self.stack.as_ref().unwrap().len();
let o_len = other.stack.as_ref().unwrap().len();
// Determine height of new stack
let m = cmp::min(s_len,o_len);
// Construct a new stack
let mut nstack = Vec::new();
// Perform stack merge
for i in (0..m).rev() {
let l = self.peek(i);
let r = other.peek(i);
nstack.push(l.merge(r));
}
// Update me
*self = CfaState{stack:Some(nstack)}
}
}
//
false
}
fn top(&self) -> usize {
// Extract the stack. We assume for now we are not bottom.
let stack = self.stack.as_ref().unwrap();
// Inspect last element. Again, we assume for now this
// exists.
match stack.last().unwrap() {
Value::Known(n) => *n,
Value::Unknown => {
// At some point, this will need to be fixed.
panic!("Unknown value encountered");
}
}
}
// ============================================================================
// Abstract Instruction Semantics (stack)
// ============================================================================
/// Update an abstract state with the effects of a given instruction.
fn transfer(self, insn: &Instruction) -> CfaState {
match insn {
STOP => BOTTOM,
// 0s: Stop and Arithmetic Operations
ADD|MUL|SUB|DIV|SDIV|MOD|SMOD|EXP|SIGNEXTEND => {
self.pop().pop().push(Value::Unknown)
}
ADDMOD|MULMOD => {
self.pop().pop().pop().push(Value::Unknown)
}
// 0s: Stop and Arithmetic Operations
ISZERO|NOT => {
self.pop().push(Value::Unknown)
}
// Binary Comparators
LT|GT|SLT|SGT|EQ => {
self.pop().pop().push(Value::Unknown)
}
// Binary bitwise operators
AND|OR|XOR|BYTE|SHL|SHR|SAR => {
self.pop().pop().push(Value::Unknown)
}
// 20s: Keccak256
// 30s: Environmental Information
CALLVALUE => self.push(Value::Unknown),
CALLDATALOAD => self.pop().push(Value::Unknown),
CALLDATASIZE => self.push(Value::Unknown),
// 40s: Block Information
// 50s: Stack, Memory, Storage and Flow Operations
POP => self.pop(),
MLOAD => self.pop().push(Value::Unknown),
MSTORE => self.pop().pop(),
SLOAD => self.pop().push(Value::Unknown),
SSTORE => self.pop().pop(),
JUMPI => self.pop().pop(),
JUMPDEST(_) => self, // nop
// 60 & 70s: Push Operations
PUSH(bytes) => {
let n = util::from_be_bytes(&bytes);
if n <= MAX_CODE_SIZE {
self.push(Value::Known(n as usize))
} else {
self.push(Value::Unknown)
}
}
// 80s: Duplicate Operations
DUP(n) => {
let m = (*n - 1) as usize;
let nth = self.peek(m);
self.push(nth)
}
// 90s: Swap Operations
SWAP(n) => {
let m = (*n - 1) as usize;
let x = self.peek(m);
let y = self.peek(0);
self.set(0,x).set(m,y)
}
// 90s: Exchange Operations
// a0s: Logging Operations
// f0s: System Operations
INVALID|JUMP|RETURN|REVERT|STOP => {
BOTTOM
}
_ => {
// This is a catch all to ensure no instructions are
// missed above.
panic!("unknown instruction ({:?})",insn);
}
}
}
sourcepub fn set(self, n: usize, val: Value) -> Self
pub fn set(self, n: usize, val: Value) -> Self
Set specific item on this stack.
Examples found in repository?
src/cfa.rs (line 272)
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
fn transfer(self, insn: &Instruction) -> CfaState {
match insn {
STOP => BOTTOM,
// 0s: Stop and Arithmetic Operations
ADD|MUL|SUB|DIV|SDIV|MOD|SMOD|EXP|SIGNEXTEND => {
self.pop().pop().push(Value::Unknown)
}
ADDMOD|MULMOD => {
self.pop().pop().pop().push(Value::Unknown)
}
// 0s: Stop and Arithmetic Operations
ISZERO|NOT => {
self.pop().push(Value::Unknown)
}
// Binary Comparators
LT|GT|SLT|SGT|EQ => {
self.pop().pop().push(Value::Unknown)
}
// Binary bitwise operators
AND|OR|XOR|BYTE|SHL|SHR|SAR => {
self.pop().pop().push(Value::Unknown)
}
// 20s: Keccak256
// 30s: Environmental Information
CALLVALUE => self.push(Value::Unknown),
CALLDATALOAD => self.pop().push(Value::Unknown),
CALLDATASIZE => self.push(Value::Unknown),
// 40s: Block Information
// 50s: Stack, Memory, Storage and Flow Operations
POP => self.pop(),
MLOAD => self.pop().push(Value::Unknown),
MSTORE => self.pop().pop(),
SLOAD => self.pop().push(Value::Unknown),
SSTORE => self.pop().pop(),
JUMPI => self.pop().pop(),
JUMPDEST(_) => self, // nop
// 60 & 70s: Push Operations
PUSH(bytes) => {
let n = util::from_be_bytes(&bytes);
if n <= MAX_CODE_SIZE {
self.push(Value::Known(n as usize))
} else {
self.push(Value::Unknown)
}
}
// 80s: Duplicate Operations
DUP(n) => {
let m = (*n - 1) as usize;
let nth = self.peek(m);
self.push(nth)
}
// 90s: Swap Operations
SWAP(n) => {
let m = (*n - 1) as usize;
let x = self.peek(m);
let y = self.peek(0);
self.set(0,x).set(m,y)
}
// 90s: Exchange Operations
// a0s: Logging Operations
// f0s: System Operations
INVALID|JUMP|RETURN|REVERT|STOP => {
BOTTOM
}
_ => {
// This is a catch all to ensure no instructions are
// missed above.
panic!("unknown instruction ({:?})",insn);
}
}
}
Trait Implementations§
source§impl AbstractState for CfaState
impl AbstractState for CfaState
source§fn transfer(self, insn: &Instruction) -> CfaState
fn transfer(self, insn: &Instruction) -> CfaState
Update an abstract state with the effects of a given instruction.
source§fn is_reachable(&self) -> bool
fn is_reachable(&self) -> bool
Determines whether a given block is considered reachable or
not.
source§fn branch(&self, pc: usize, insn: &Instruction) -> Self
fn branch(&self, pc: usize, insn: &Instruction) -> Self
Apply a given branch to this stage, yielding an updated state
at the point of the branch.