Example #1
0
    # Input vars
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow and underflow conditions
    actual_overflow = Not(BVSubNoOverflow(X_short, Y_short))
    actual_underflow = Not(BVSubNoUnderflow(X_short, Y_short, True))

    # cast to full n_bits values
    X = BVSignedUpCast(X_short, n_bits)
    Y = BVSignedUpCast(Y_short, n_bits)
    diff = SUB(X, Y)

    # Constants
    maxValue = BVSignedMax(type_bits, n_bits)
    minValue = BVSignedMin(type_bits, n_bits)

    # Overflow and underflow checks in YulUtilFunction::overflowCheckedIntSubFunction
    if type_bits == 256:
        underflow_check = AND(ISZERO(SLT(Y, 0)), SGT(diff, X))
        overflow_check = AND(SLT(Y, 0), SLT(diff, X))
    else:
        underflow_check = SLT(diff, minValue)
        overflow_check = SGT(diff, maxValue)

    type_bits += 8

    rule.check(actual_underflow, underflow_check != 0)
    rule.check(actual_overflow, overflow_check != 0)
"""

# Approximation with 16-bit base types.
n_bits = 16
type_bits = 8

while type_bits <= n_bits:

    rule = Rule()

    # Input vars
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow condition
    actual_overflow = Not(BVMulNoOverflow(X_short, Y_short, False))

    # cast to full n_bits values
    X = BVUnsignedUpCast(X_short, n_bits)
    Y = BVUnsignedUpCast(Y_short, n_bits)

    # Constants
    maxValue = BVUnsignedMax(type_bits, n_bits)

    # Overflow check in YulUtilFunction::overflowCheckedIntMulFunction
    overflow_check = AND(ISZERO(ISZERO(X)), GT(Y, DIV(maxValue, X)))

    rule.check(overflow_check != 0, actual_overflow)

    type_bits *= 2
Example #3
0
from opcodes import SIGNEXTEND, AND
from rule import Rule
from z3 import BitVec, BitVecVal, ULT
"""
Rule:
AND(A, SIGNEXTEND(B, X)) -> AND(A, X)
given
    B < WordSize / 8 - 1 AND
    A & (1 << ((B + 1) * 8) - 1) == A
"""

n_bits = 128

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

rule = Rule()
# Requirements
rule.require(ULT(B, BitVecVal(n_bits // 8 - 1, n_bits)))
rule.require((A & ((BitVecVal(1, n_bits) << ((B + 1) * 8)) - 1)) == A)
rule.check(AND(A, SIGNEXTEND(B, X)), AND(A, X))
Example #4
0
from opcodes import AND
from rule import Rule
from z3 import BitVec, BitVecVal
"""
Rule:
AND(AND(X, Y), Y) -> AND(X, Y)
AND(Y, AND(X, Y)) -> AND(X, Y)
AND(AND(Y, X), Y) -> AND(Y, X)
AND(Y, AND(Y, X)) -> AND(Y, X)
Requirements:
"""

rule = Rule()

n_bits = 256

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

# Constants
BitWidth = BitVecVal(n_bits, n_bits)

# Requirements

# Non optimized result
nonopt_1 = AND(AND(X, Y), Y)
nonopt_2 = AND(Y, AND(X, Y))
nonopt_3 = AND(AND(Y, X), Y)
nonopt_4 = AND(Y, AND(Y, X))
Example #5
0
from opcodes import AND, ISZERO, MOD, SUB
from rule import Rule
from util import BVUnsignedMax
from z3 import BitVec, BitVecVal, If
"""
Checking conversion of exp(-1, X) to sub(isZero(and(X, 1)), and(X, 1))
"""

rule = Rule()
n_bits = 256

X = BitVec('X', n_bits)

exp_neg_one = If(
    MOD(X, 2) == 0, BitVecVal(1, n_bits), BVUnsignedMax(n_bits, n_bits))

rule.check(SUB(ISZERO(AND(X, 1)), AND(X, 1)), exp_neg_one)
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
Mask = SHL(B, A)
opt = AND(SHL(B, X), Mask)

rule.check(nonopt_1, opt)
rule.check(nonopt_2, opt)
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)
Example #8
0
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow and underflow conditions
    actual_overflow = Not(BVMulNoOverflow(X_short, Y_short, True))
    actual_underflow = Not(BVMulNoUnderflow(X_short, Y_short))

    # cast to full n_bits values
    X = BVSignedUpCast(X_short, n_bits)
    Y = BVSignedUpCast(Y_short, n_bits)

    # Constants
    maxValue = BVSignedMax(type_bits, n_bits)
    minValue = BVSignedMin(type_bits, n_bits)

    # Overflow and underflow checks in YulUtilFunction::overflowCheckedIntMulFunction
    overflow_check_1 = AND(AND(SGT(X, 0), SGT(Y, 0)), GT(X, DIV(maxValue, Y)))
    underflow_check_1 = AND(AND(SGT(X, 0), SLT(Y, 0)),
                            SLT(Y, SDIV(minValue, X)))
    underflow_check_2 = AND(AND(SLT(X, 0), SGT(Y, 0)),
                            SLT(X, SDIV(minValue, Y)))
    overflow_check_2 = AND(AND(SLT(X, 0), SLT(Y, 0)),
                           SLT(X, SDIV(maxValue, Y)))

    rule.check(actual_overflow, Or(overflow_check_1 != 0,
                                   overflow_check_2 != 0))
    rule.check(actual_underflow,
               Or(underflow_check_1 != 0, underflow_check_2 != 0))

    type_bits *= 2
Example #9
0
    # Input vars
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow and underflow conditions
    actual_overflow = Not(BVAddNoOverflow(X_short, Y_short, True))
    actual_underflow = Not(BVAddNoUnderflow(X_short, Y_short))

    # cast to full n_bits values
    X = BVSignedUpCast(X_short, n_bits)
    Y = BVSignedUpCast(Y_short, n_bits)
    sum_ = ADD(X, Y)

    # Constants
    maxValue = BVSignedMax(type_bits, n_bits)
    minValue = BVSignedMin(type_bits, n_bits)

    # Overflow and underflow checks in YulUtilFunction::overflowCheckedIntAddFunction
    if type_bits == 256:
        overflow_check = AND(ISZERO(SLT(X, 0)), SLT(sum_, Y))
        underflow_check = AND(SLT(X, 0), ISZERO(SLT(sum_, Y)))
    else:
        overflow_check = SGT(sum_, maxValue)
        underflow_check = SLT(sum_, minValue)

    type_bits += 8

    rule.check(actual_overflow, overflow_check != 0)
    rule.check(actual_underflow, underflow_check != 0)
Example #10
0
type_bits = 8

while type_bits <= n_bits:

    rule = Rule()

    # Input vars
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow and underflow conditions
    actual_overflow = Not(BVAddNoOverflow(X_short, Y_short, True))
    actual_underflow = Not(BVAddNoUnderflow(X_short, Y_short))

    # cast to full n_bits values
    X = BVSignedUpCast(X_short, n_bits)
    Y = BVSignedUpCast(Y_short, n_bits)

    # Constants
    maxValue = BVSignedMax(type_bits, n_bits)
    minValue = BVSignedMin(type_bits, n_bits)

    # Overflow and underflow checks in YulUtilFunction::overflowCheckedIntAddFunction
    overflow_check = AND(ISZERO(SLT(X, 0)), SGT(Y, SUB(maxValue, X)))
    underflow_check = AND(SLT(X, 0), SLT(Y, SUB(minValue, X)))

    rule.check(actual_overflow, overflow_check != 0)
    rule.check(actual_underflow, underflow_check != 0)

    type_bits *= 2
Example #11
0
Overflow checked signed integer division.
"""

n_bits = 256
type_bits = 8

while type_bits <= n_bits:

    rule = Rule()

    # Input vars
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow conditions
    actual_overflow = Not(BVSDivNoOverflow(X_short, Y_short))

    # cast to full n_bits values
    X = BVSignedUpCast(X_short, n_bits)
    Y = BVSignedUpCast(Y_short, n_bits)

    # Constants
    minValue = BVSignedMin(type_bits, n_bits)

    # Overflow check in YulUtilFunction::overflowCheckedIntDivFunction
    overflow_check = AND(EQ(X, minValue), EQ(Y, SUB(0, 1)))

    rule.check(actual_overflow, overflow_check != 0)

    type_bits *= 2
from opcodes import AND, OR
from rule import Rule
from z3 import BitVec
"""
Rule:
AND(OR(AND(X, A), Y), B) -> OR(AND(X, A & B), AND(Y, B))
"""

rule = Rule()

# bit width is irrelevant
n_bits = 128

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

# Non optimized result, explicit form
nonopt = AND(OR(AND(X, A), Y), B)

# Optimized result
opt = OR(AND(X, A & B), AND(Y, B))

rule.check(nonopt, opt)

# Now the forms as they are constructod in the code.
for inner in [AND(X, A), AND(A, X)]:
    for second in [OR(inner, Y), OR(Y, inner)]:
        rule.check(AND(second, B), opt)
Example #13
0
type_bits = 8

while type_bits <= n_bits:

    rule = Rule()

    # Input vars
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow and underflow conditions
    actual_overflow = Not(BVSubNoOverflow(X_short, Y_short))
    actual_underflow = Not(BVSubNoUnderflow(X_short, Y_short, True))

    # cast to full n_bits values
    X = BVSignedUpCast(X_short, n_bits)
    Y = BVSignedUpCast(Y_short, n_bits)

    # Constants
    maxValue = BVSignedMax(type_bits, n_bits)
    minValue = BVSignedMin(type_bits, n_bits)

    # Overflow and underflow checks in YulUtilFunction::overflowCheckedIntSubFunction
    underflow_check = AND(ISZERO(SLT(Y, 0)), SLT(X, ADD(minValue, Y)))
    overflow_check = AND(SLT(Y, 0), SGT(X, ADD(maxValue, Y)))

    rule.check(actual_underflow, underflow_check != 0)
    rule.check(actual_overflow, overflow_check != 0)

    type_bits *= 2
Example #14
0
	# Input vars
	X_short = BitVec('X', type_bits)
	Y_short = BitVec('Y', type_bits)

	# Z3's overflow and underflow conditions
	actual_overflow = Not(BVMulNoOverflow(X_short, Y_short, True))
	actual_underflow = Not(BVMulNoUnderflow(X_short, Y_short))

	# cast to full n_bits values
	X = BVSignedUpCast(X_short, n_bits)
	Y = BVSignedUpCast(Y_short, n_bits)
	product_raw = MUL(X, Y)
	#remove any overflown bits
	product = BVSignedCleanupFunction(product_raw, type_bits)

	# Constants
	min_value = BVSignedMin(type_bits, n_bits)

	# Overflow and underflow checks in YulUtilFunction::overflowCheckedIntMulFunction
	if type_bits > n_bits / 2:
		sol_overflow_check_1 = ISZERO(OR(ISZERO(X), EQ(Y, SDIV(product, X))))
		if type_bits == n_bits:
			sol_overflow_check_2 = AND(SLT(X, 0), EQ(Y, min_value))
			sol_overflow_check = Or(sol_overflow_check_1 != 0, sol_overflow_check_2 != 0)
		else:
			sol_overflow_check = (sol_overflow_check_1 != 0)
	else:
		sol_overflow_check = (ISZERO(EQ(product, product_raw)) != 0)

	rule.check(Or(actual_overflow, actual_underflow), sol_overflow_check)
Example #15
0
Overflow checked unsigned integer multiplication.
"""

n_bits = 256

# Check that YulUtilFunction::cleanupFunction cleanup matches BVUnsignedCleanupFunction
for type_bits in range(8, 256, 8):

    rule = Rule()

    # Input vars
    X = BitVec('X', n_bits)
    mask = BitVecVal((1 << type_bits) - 1, n_bits)

    cleaned_reference = BVUnsignedCleanupFunction(X, type_bits)
    cleaned = AND(X, mask)

    rule.check(cleaned, cleaned_reference)

# Check that BVUnsignedCleanupFunction properly cleans up values.
for type_bits in range(8, 256, 8):

    rule = Rule()

    # Input vars
    X_short = BitVec('X', type_bits)
    dirt = BitVec('dirt', n_bits - type_bits)

    X = BVUnsignedUpCast(X_short, n_bits)
    X_dirty = Concat(dirt, X_short)
    X_cleaned = BVUnsignedCleanupFunction(X_dirty, type_bits)