DIV(X, A) -> SHR(k, X)
Requirements:
A == 1 << K
"""

rule = Rule()

n_bits = 32

# Input vars
X = BitVec('X', n_bits)
A = BitVec('A', n_bits)
K = BitVec('K', n_bits)

# Requirements
rule.require(A == SHL(K, 1))

# Non optimized result
nonopt_1 = MUL(X, A)
nonopt_2 = MUL(A, X)
nonopt_3 = DIV(X, A)

# Optimized result
opt_1 = SHL(K, X)
opt_2 = SHL(K, X)
opt_3 = SHR(K, X)

rule.check(nonopt_1, opt_1)
rule.check(nonopt_2, opt_2)
rule.check(nonopt_3, opt_3)
from opcodes import AND, SHL
from rule import Rule
from z3 import BitVec, BitVecVal, ULT
"""
Rule:
SHL(B, AND(X, A)) -> AND(SHL(B, X), A << B)
SHL(B, AND(A, X)) -> AND(SHL(B, X), A << B)
Requirements:
B < BitWidth
"""

rule = Rule()

n_bits = 128

# Input vars
X = BitVec('X', n_bits)
A = BitVec('A', n_bits)
B = BitVec('B', n_bits)

# Constants
BitWidth = BitVecVal(n_bits, n_bits)

# Requirements
rule.require(ULT(B, BitWidth))

# Non optimized result
nonopt_1 = SHL(B, AND(X, A))
nonopt_2 = SHL(B, AND(A, X))

# Optimized result
from opcodes import DIV, SHL, SHR
from rule import Rule
from z3 import BitVec

"""
Rule:
DIV(X, SHL(Y, 1)) -> SHR(Y, X)
Requirements:
"""

rule = Rule()

n_bits = 32

# Input vars
X = BitVec('X', n_bits)
Y = BitVec('Y', n_bits)

# Non optimized result
nonopt = DIV(X, SHL(Y, 1))

# Optimized result
opt = SHR(Y, X)

rule.check(nonopt, opt)
from opcodes import SHL, MUL
from rule import Rule
from z3 import BitVec
"""
Rule:
MUL(X, SHL(Y, 1)) -> SHL(Y, X)
MUL(SHL(X, 1), Y) -> SHL(X, Y)
Requirements:
"""

rule = Rule()

n_bits = 64

# Input vars
X = BitVec('X', n_bits)
Y = BitVec('Y', n_bits)

# Requirements

# Non optimized result
nonopt_1 = MUL(X, SHL(Y, 1))
nonopt_2 = MUL(SHL(X, 1), Y)

# Optimized result
opt_1 = SHL(Y, X)
opt_2 = SHL(X, Y)

rule.check(nonopt_1, opt_1)
rule.check(nonopt_2, opt_2)
n_bits = 64

# Input vars
X = BitVec('X', n_bits)
A = BitVec('A', n_bits)
B = BitVec('B', n_bits)

# Constants
BitWidth = BitVecVal(n_bits, n_bits)

# Requirements
rule.require(ULT(A, BitWidth))
rule.require(ULT(B, BitWidth))

# Non optimized result
nonopt = SHR(B, SHL(A, X))

# Optimized result
Mask = SHR(B, SHL(A, Int2BV(IntVal(-1), n_bits)))
opt = If(
	UGT(A, B),
	AND(SHL(A - B, X), Mask),
		If(
			UGT(B, A),
			AND(SHR(B - A, X), Mask),
			AND(X, Mask)
		)
	)

rule.check(nonopt, opt)
示例#6
0
from opcodes import SHL
from rule import Rule
from z3 import BitVec, BV2Int, Int2BV, IntVal
"""
Shift left workaround that Solidity implements
due to a bug in Boost.
"""

rule = Rule()

n_bits = 8
bigint_bits = 16

# Input vars
X = BitVec('X', n_bits)
A = BitVec('A', n_bits)
B = BitVec('B', bigint_bits)

# Compute workaround
workaround = Int2BV(
    BV2Int((Int2BV(BV2Int(X), bigint_bits) << Int2BV(BV2Int(A), bigint_bits))
           & Int2BV(BV2Int(Int2BV(IntVal(-1), n_bits)), bigint_bits)), n_bits)

rule.check(workaround, SHL(A, X))
示例#7
0
from opcodes import BYTE, SHL
from rule import Rule
from z3 import BitVec, ULE
"""
byte(A, shl(B, X))
given B % 8 == 0 && A <= 32 && B <= 256
->
byte(A + B / 8, X)
"""

rule = Rule()

n_bits = 256

# Input vars
X = BitVec('X', n_bits)
A = BitVec('A', n_bits)
B = BitVec('B', n_bits)

# Non optimized result
nonopt = BYTE(A, SHL(B, X))
# Optimized result
opt = BYTE(A + B / 8, X)

rule.require(B % 8 == 0)
rule.require(ULE(A, 32))
rule.require(ULE(B, 256))

rule.check(nonopt, opt)
示例#8
0
from opcodes import SHL, SIGNEXTEND
from rule import Rule
from z3 import BitVec, LShR, ULE
"""
Rule:
SHL(A, SIGNEXTEND(B, X)) -> SIGNEXTEND((A >> 3) + B, SHL(A, X))
given return A & 7 == 0  AND  A <= WordSize  AND  B <= WordSize / 8
"""

n_bits = 256

# Input vars
X = BitVec('X', n_bits)
Y = BitVec('Y', n_bits)
A = BitVec('A', n_bits)
B = BitVec('B', n_bits)

rule = Rule()
rule.require(A & 7 == 0)
rule.require(ULE(A, n_bits))
rule.require(ULE(B, n_bits / 8))
rule.check(SHL(A, SIGNEXTEND(B, X)), SIGNEXTEND(LShR(A, 3) + B, SHL(A, X)))
示例#9
0
from opcodes import SHL
from rule import Rule
from z3 import BitVec, If
"""
Checking conversion of exp(2, X) to shl(X, 1)
"""

rule = Rule()
n_bits = 256

# Proof of exp(2, X) = shl(X, 1) by induction:
#
# Base case: X = 0, exp(2, 0) = 1 = 1 = shl(0, 1)
# Inductive step: assuming exp(2, X) = shl(X, 1) for X <= N
#                 to prove: exp(2, N + 1) = shl(N + 1, 1)
#
# Notice that exp(2, N + 1) = 2 * exp(2, N) mod 2**256
# since exp(2, N) = shl(N, 1), it is enough to show that
# 2 * shl(N, 1) mod 2**256 = shl(N + 1, 1)
#
# Also note that N + 1 < 2**256

N = BitVec('N', n_bits)
inductive_step = 2 * SHL(N, 1)

rule.check(inductive_step, If(N == 2**256 - 1, 0, SHL(N + 1, 1)))