From 79967645420811ea45b0a9e666ee876cfc3f7b4c Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Sat, 27 Feb 2021 23:46:53 -0500 Subject: [PATCH 01/11] XSlotted metaclass to force all Expressions to use slots --- manticore/core/smtlib/expression.py | 101 +++++++++++++++++++++++----- tests/other/test_smtlibv2.py | 37 ---------- 2 files changed, 83 insertions(+), 55 deletions(-) diff --git a/manticore/core/smtlib/expression.py b/manticore/core/smtlib/expression.py index 5aea0210c..af4f716f2 100644 --- a/manticore/core/smtlib/expression.py +++ b/manticore/core/smtlib/expression.py @@ -4,7 +4,7 @@ import re import copy -from typing import Union, Optional, Dict, List +from typing import Union, Optional, Dict, Tuple class ExpressionException(SmtlibError): @@ -15,10 +15,60 @@ class ExpressionException(SmtlibError): pass -class Expression: +class XSlotted(type): + """ + Metaclass that will propagate slots on multi-inheritance classes + Every class should define __xslots__ (instead of __slots__) + + class Base(object, metaclass=XSlotted, abstract=True): + pass + + class A(Base, abstract=True): + __xslots__ = ('a',) + pass + + class B(Base, abstract=True): + __xslots__ = ('b',) + pass + + class C(A, B): + pass + + # Normal case / baseline + class X(object): + __slots__ = ('a', 'b') + + c = C() + c.a = 1 + c.b = 2 + + x = X() + x.a = 1 + x.b = 2 + + import sys + print (sys.getsizeof(c),sys.getsizeof(x)) #same value + """ + + def __new__(cls, clsname, bases, attrs, abstract=False): + xslots = frozenset(attrs.get("__xslots__", ())) + # merge the xslots of all the bases with the one defined here + for base in bases: + xslots = xslots.union(getattr(base, "__xslots__", ())) + attrs["__xslots__"] = tuple(xslots) + if abstract: + attrs["__slots__"] = tuple() + else: + attrs["__slots__"] = tuple(map(lambda attr: attr.split("#", 1)[0], attrs["__xslots__"])) + attrs["__hash__"] = object.__hash__ + # attrs["__hash__"] = lambda self : hash((clsname, tuple(getattr(self, name) for name in self.__slots__ if name not in ("_concrete_cache", "_written")))) + return super().__new__(cls, clsname, bases, attrs) + + +class Expression(object, metaclass=XSlotted, abstract=True): """ Abstract taintable Expression. """ - __slots__ = ["_taint"] + __xslots__: Tuple[str, ...] = ("_taint",) def __init__(self, taint: Union[tuple, frozenset] = ()): if self.__class__ is Expression: @@ -115,8 +165,6 @@ def taint_with(arg, *taints, value_bits=256, index_bits=256): ############################################################################### # Booleans class Bool(Expression): - __slots__: List[str] = [] - def __init__(self, *operands, **kwargs): super().__init__(*operands, **kwargs) @@ -169,7 +217,7 @@ def __bool__(self): class BoolVariable(Bool): - __slots__ = ["_name"] + __xslots__: Tuple[str, ...] = ("_name",) def __init__(self, name: str, *args, **kwargs): assert " " not in name @@ -195,11 +243,11 @@ def declaration(self): class BoolConstant(Bool): - __slots__ = ["_value"] + __xslots__: Tuple[str, ...] = ("_value",) def __init__(self, value: bool, *args, **kwargs): - self._value = value super().__init__(*args, **kwargs) + self._value = value def __bool__(self): return self.value @@ -210,7 +258,7 @@ def value(self): class BoolOperation(Bool): - __slots__ = ["_operands"] + __xslots__: Tuple[str, ...] = ("_operands",) def __init__(self, *operands, **kwargs): self._operands = operands @@ -253,7 +301,7 @@ def __init__(self, cond: "Bool", true: "Bool", false: "Bool", **kwargs): class BitVec(Expression): """ This adds a bitsize to the Expression class """ - __slots__ = ["size"] + __xslots__: Tuple[str, ...] = ("size",) def __init__(self, size, *operands, **kwargs): super().__init__(*operands, **kwargs) @@ -456,7 +504,7 @@ def Bool(self): class BitVecVariable(BitVec): - __slots__ = ["_name"] + __xslots__: Tuple[str, ...] = ("_name",) def __init__(self, size: int, name: str, *args, **kwargs): assert " " not in name @@ -482,7 +530,7 @@ def declaration(self): class BitVecConstant(BitVec): - __slots__ = ["_value"] + __xslots__: Tuple[str, ...] = ("_value",) def __init__(self, size: int, value: int, *args, **kwargs): MASK = (1 << size) - 1 @@ -513,7 +561,7 @@ def signed_value(self): class BitVecOperation(BitVec): - __slots__ = ["_operands"] + __xslots__: Tuple[str, ...] = ("_operands",) def __init__(self, size, *operands, **kwargs): self._operands = operands @@ -671,7 +719,7 @@ def __init__(self, a, b, *args, **kwargs): ############################################################################### # Array BV32 -> BV8 or BV64 -> BV8 class Array(Expression): - __slots__ = ["_index_bits", "_index_max", "_value_bits"] + __xslots__: Tuple[str, ...] = ("_index_bits", "_index_max", "_value_bits") def __init__( self, index_bits: int, index_max: Optional[int], value_bits: int, *operands, **kwargs @@ -764,7 +812,7 @@ def store(self, index, value): def write(self, offset, buf): if not isinstance(buf, (Array, bytearray)): - raise TypeError("Array or bytearray expected got {:s}".format(type(buf))) + raise TypeError(f"Array or bytearray expected got {type(buf)}") arr = self for i, val in enumerate(buf): arr = arr.store(offset + i, val) @@ -903,7 +951,7 @@ def __radd__(self, other): class ArrayVariable(Array): - __slots__ = ["_name"] + __xslots__: Tuple[str, ...] = ("_name",) def __init__(self, index_bits, index_max, value_bits, name, *args, **kwargs): assert " " not in name @@ -929,7 +977,7 @@ def declaration(self): class ArrayOperation(Array): - __slots__ = ["_operands"] + __xslots__: Tuple[str, ...] = ("_operands",) def __init__(self, array: Array, *operands, **kwargs): self._operands = (array, *operands) @@ -989,6 +1037,8 @@ def __setstate__(self, state): class ArraySlice(ArrayOperation): + __xslots__: Tuple[str, ...] = ("_slice_offset", "_slice_size") + def __init__( self, array: Union["Array", "ArrayProxy"], offset: int, size: int, *args, **kwargs ): @@ -1033,6 +1083,15 @@ def store(self, index, value): class ArrayProxy(Array): + __xslots__: Tuple[str, ...] = ( + "constraints", + "_default", + "_concrete_cache", + "_written", + "_array", + "_name", + ) + def __init__(self, array: Array, default: Optional[int] = None): self._default = default self._concrete_cache: Dict[int, int] = {} @@ -1229,7 +1288,7 @@ def get(self, index, default=None): class ArraySelect(BitVec): - __slots__ = ["_operands"] + __xslots__: Tuple[str, ...] = ("_operands",) def __init__(self, array: "Array", index: "BitVec", *operands, **kwargs): assert index.size == array.index_bits @@ -1257,6 +1316,8 @@ def __repr__(self): class BitVecSignExtend(BitVecOperation): + __xslots__: Tuple[str, ...] = ("extend",) + def __init__(self, operand: "BitVec", size_dest: int, *args, **kwargs): assert size_dest >= operand.size super().__init__(size_dest, operand, *args, **kwargs) @@ -1264,6 +1325,8 @@ def __init__(self, operand: "BitVec", size_dest: int, *args, **kwargs): class BitVecZeroExtend(BitVecOperation): + __xslots__: Tuple[str, ...] = ("extend",) + def __init__(self, size_dest: int, operand: "BitVec", *args, **kwargs): assert size_dest >= operand.size super().__init__(size_dest, operand, *args, **kwargs) @@ -1271,6 +1334,8 @@ def __init__(self, size_dest: int, operand: "BitVec", *args, **kwargs): class BitVecExtract(BitVecOperation): + __xslots__: Tuple[str, ...] = ("_begining", "_end") + def __init__(self, operand: "BitVec", offset: int, size: int, *args, **kwargs): assert offset >= 0 and offset + size <= operand.size super().__init__(size, operand, *args, **kwargs) diff --git a/tests/other/test_smtlibv2.py b/tests/other/test_smtlibv2.py index 3050b900f..6d4a2b878 100644 --- a/tests/other/test_smtlibv2.py +++ b/tests/other/test_smtlibv2.py @@ -26,43 +26,6 @@ DIRPATH = os.path.dirname(__file__) -class RegressionTest(unittest.TestCase): - def test_related_to(self): - import gzip - import pickle, sys - - filename = os.path.abspath(os.path.join(DIRPATH, "data", "ErrRelated.pkl.gz")) - - # A constraint set and a contraint caught in the act of making related_to fail - constraints, constraint = pickle.loads(gzip.open(filename, "rb").read()) - - Z3Solver.instance().can_be_true.cache_clear() - ground_truth = Z3Solver.instance().can_be_true(constraints, constraint) - self.assertEqual(ground_truth, False) - - Z3Solver.instance().can_be_true.cache_clear() - self.assertEqual( - ground_truth, - Z3Solver.instance().can_be_true(constraints.related_to(constraints), constraint), - ) - - # Replace - new_constraint = Operators.UGE( - Operators.SEXTEND(BitVecConstant(256, 0x1A), 256, 512) * BitVecConstant(512, 1), - 0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000, - ) - self.assertEqual(translate_to_smtlib(constraint), translate_to_smtlib(new_constraint)) - - Z3Solver.instance().can_be_true.cache_clear() - self.assertEqual(ground_truth, Z3Solver.instance().can_be_true(constraints, new_constraint)) - - Z3Solver.instance().can_be_true.cache_clear() - self.assertEqual( - ground_truth, - Z3Solver.instance().can_be_true(constraints.related_to(new_constraint), new_constraint), - ) - - """ class Z3Specific(unittest.TestCase): _multiprocess_can_split_ = True From 6f3efb1212707a4303b4955f3925687e75e79935 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Sat, 27 Feb 2021 23:49:09 -0500 Subject: [PATCH 02/11] Run CI on slotted branch without PR --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34468c213..3cffb33fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - slotted pull_request: schedule: # run CI every day even if no PRs/merges occur From 6d7e4ca72788583abe8899c31522a0d1a1b26729 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Sun, 28 Feb 2021 11:22:35 -0500 Subject: [PATCH 03/11] Add test for slots. Also small refactor for abstract classes and operands arguments --- manticore/core/smtlib/expression.py | 37 ++++-- manticore/core/smtlib/operators.py | 2 +- manticore/core/smtlib/visitors.py | 4 +- manticore/wasm/cli.py | 9 +- tests/ethereum/test_general.py | 4 +- tests/native/test_register.py | 4 +- tests/other/test_smtlibv2.py | 183 ++++++++++++++++++++++++++++ tox.ini | 8 +- 8 files changed, 225 insertions(+), 26 deletions(-) diff --git a/manticore/core/smtlib/expression.py b/manticore/core/smtlib/expression.py index af4f716f2..a256b0d0f 100644 --- a/manticore/core/smtlib/expression.py +++ b/manticore/core/smtlib/expression.py @@ -164,7 +164,9 @@ def taint_with(arg, *taints, value_bits=256, index_bits=256): ############################################################################### # Booleans -class Bool(Expression): +class Bool(Expression, abstract=True): + """Bool expressions represent symbolic value of truth""" + def __init__(self, *operands, **kwargs): super().__init__(*operands, **kwargs) @@ -257,7 +259,9 @@ def value(self): return self._value -class BoolOperation(Bool): +class BoolOperation(Bool, abstract=True): + """ An operation that results in a Bool """ + __xslots__: Tuple[str, ...] = ("_operands",) def __init__(self, *operands, **kwargs): @@ -298,8 +302,8 @@ def __init__(self, cond: "Bool", true: "Bool", false: "Bool", **kwargs): super().__init__(cond, true, false, **kwargs) -class BitVec(Expression): - """ This adds a bitsize to the Expression class """ +class BitVec(Expression, abstract=True): + """ BitVector expressions have a fixed bit size """ __xslots__: Tuple[str, ...] = ("size",) @@ -560,7 +564,9 @@ def signed_value(self): return self._value -class BitVecOperation(BitVec): +class BitVecOperation(BitVec, abstract=True): + """ An operation that results in a BitVec """ + __xslots__: Tuple[str, ...] = ("_operands",) def __init__(self, size, *operands, **kwargs): @@ -718,7 +724,14 @@ def __init__(self, a, b, *args, **kwargs): ############################################################################### # Array BV32 -> BV8 or BV64 -> BV8 -class Array(Expression): +class Array(Expression, abstract=True): + """An Array expression is an unmutable mapping from bitvector to bitvector + + array.index_bits is the number of bits used for addressing a value + array.value_bits is the number of bits used in the values + array.index_max counts the valid indexes starting at 0. Accessing outside the bound is undefined + """ + __xslots__: Tuple[str, ...] = ("_index_bits", "_index_max", "_value_bits") def __init__( @@ -868,18 +881,18 @@ def read_BE(self, address, size): bytes = [] for offset in range(size): bytes.append(self.get(address + offset, 0)) - return BitVecConcat(size * self.value_bits, *bytes) + return BitVecConcat(size * self.value_bits, tuple(bytes)) def read_LE(self, address, size): address = self.cast_index(address) bytes = [] for offset in range(size): bytes.append(self.get(address + offset, 0)) - return BitVecConcat(size * self.value_bits, *reversed(bytes)) + return BitVecConcat(size * self.value_bits, tuple(reversed(bytes))) def write_BE(self, address, value, size): address = self.cast_index(address) - value = BitVec(size * self.value_bits).cast(value) + value = BitVecConstant(size * self.value_bits, value=0).cast(value) array = self for offset in range(size): array = array.store( @@ -890,7 +903,7 @@ def write_BE(self, address, value, size): def write_LE(self, address, value, size): address = self.cast_index(address) - value = BitVec(size * self.value_bits).cast(value) + value = BitVecConstant(size * self.value_bits, value=0).cast(value) array = self for offset in reversed(range(size)): array = array.store( @@ -977,6 +990,8 @@ def declaration(self): class ArrayOperation(Array): + """An operation that result in an Array""" + __xslots__: Tuple[str, ...] = ("_operands",) def __init__(self, array: Array, *operands, **kwargs): @@ -1356,7 +1371,7 @@ def end(self): class BitVecConcat(BitVecOperation): - def __init__(self, size_dest: int, *operands, **kwargs): + def __init__(self, size_dest: int, operands: Tuple, **kwargs): assert all(isinstance(x, BitVec) for x in operands) assert size_dest == sum(x.size for x in operands) super().__init__(size_dest, *operands, **kwargs) diff --git a/manticore/core/smtlib/operators.py b/manticore/core/smtlib/operators.py index 969679b56..79e2f0c61 100644 --- a/manticore/core/smtlib/operators.py +++ b/manticore/core/smtlib/operators.py @@ -163,7 +163,7 @@ def cast(x): return BitVecConstant(arg_size, x) return x - return BitVecConcat(total_size, *list(map(cast, args))) + return BitVecConcat(total_size, tuple(map(cast, args))) else: return args[0] else: diff --git a/manticore/core/smtlib/visitors.py b/manticore/core/smtlib/visitors.py index ec6e446e8..f18b66b9f 100644 --- a/manticore/core/smtlib/visitors.py +++ b/manticore/core/smtlib/visitors.py @@ -594,7 +594,7 @@ def visit_BitVecConcat(self, expression, *operands): if last_o is not None: new_operands.append(last_o) if changed: - return BitVecConcat(expression.size, *new_operands) + return BitVecConcat(expression.size, tuple(new_operands)) op = operands[0] value = None @@ -648,7 +648,7 @@ def visit_BitVecExtract(self, expression, *operands): if size == 0: assert expression.size == sum([x.size for x in new_operands]) return BitVecConcat( - expression.size, *reversed(new_operands), taint=expression.taint + expression.size, tuple(reversed(new_operands)), taint=expression.taint ) if begining >= item.size: diff --git a/manticore/wasm/cli.py b/manticore/wasm/cli.py index e474ce732..650e51b65 100644 --- a/manticore/wasm/cli.py +++ b/manticore/wasm/cli.py @@ -18,9 +18,12 @@ def wasm_main(args, _logger): policy=args.policy, ) - if consts.profile: - profiler = Profiler() - m.register_plugin(profiler) + try: + if consts.profile: + profiler = Profiler() + m.register_plugin(profiler) + except AttributeError: + pass m.default_invoke(func_name=consts.target_func) diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index 799456298..abcaf1b91 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -16,7 +16,7 @@ from manticore.core.plugin import Plugin from manticore.core.smtlib import ConstraintSet, operators from manticore.core.smtlib import Z3Solver -from manticore.core.smtlib.expression import BitVec +from manticore.core.smtlib.expression import BitVec, BitVecVariable from manticore.core.smtlib.visitors import to_constant from manticore.core.state import TerminateState from manticore.ethereum import ( @@ -1382,7 +1382,7 @@ def will_evm_execute_instruction_callback(self, state, i, *args, **kwargs): class EthHelpersTest(unittest.TestCase): def setUp(self): - self.bv = BitVec(256) + self.bv = BitVecVariable(256, name="BVV") def test_concretizer(self): policy = "SOME_NONSTANDARD_POLICY" diff --git a/tests/native/test_register.py b/tests/native/test_register.py index e099fc292..0663e811b 100644 --- a/tests/native/test_register.py +++ b/tests/native/test_register.py @@ -1,6 +1,6 @@ import unittest -from manticore.core.smtlib import Bool, BitVecConstant +from manticore.core.smtlib import Bool, BoolVariable, BitVecConstant from manticore.native.cpu.register import Register @@ -47,7 +47,7 @@ def test_bool_write_nonflag(self): def test_Bool(self): r = Register(32) - b = Bool() + b = BoolVariable(name="B") r.write(b) self.assertIs(r.read(), b) diff --git a/tests/other/test_smtlibv2.py b/tests/other/test_smtlibv2.py index 6d4a2b878..021b7b2ff 100644 --- a/tests/other/test_smtlibv2.py +++ b/tests/other/test_smtlibv2.py @@ -1,5 +1,7 @@ import unittest import os +import sys +from typing import Set, Type from manticore.core.smtlib import ( ConstraintSet, @@ -63,6 +65,187 @@ def test_check_solver_undefined(self): """ +class ExpressionPropertiesTest(unittest.TestCase): + _multiprocess_can_split_ = True + + def test_xslotted(self): + """Test that XSlotted multi inheritance classes uses same amount + of memory than a single class object with slots + """ + + class Base(object, metaclass=XSlotted, abstract=True): + __xslots__ = ("t",) + pass + + class A(Base, abstract=True): + __xslots__ = ("a",) + pass + + class B(Base, abstract=True): + __xslots__ = ("b",) + pass + + class C(A, B): + pass + + class X(object): + __slots__ = ("t", "a", "b") + + c = C() + c.a = 1 + c.t = 10 + + c.b = 2 + c.t = 10 + + x = X() + x.a = 1 + x.b = 2 + x.t = 20 + + self.assertEqual(sys.getsizeof(c), sys.getsizeof(x)) + + def test_Expression(self): + # Used to check if all Expression have test + checked = set() + + def check(ty: Type, pickle_size=None, sizeof=None, **kwargs): + x = ty(**kwargs) + """ + print( + type(x), + "\n Pickle size:", + len(pickle_dumps(x)), + "\n GetSizeOf:", + sys.getsizeof(x), + "\n Slotted:", + not hasattr(x, "__dict__"), + ) + """ + self.assertEqual(len(pickle_dumps(x)), pickle_size) + if sys.version_info[1] == 6: # Python 3.6 + self.assertEqual(sys.getsizeof(x), sizeof) + elif sys.version_info[1] == 7: # Python 3.7 + self.assertEqual(sys.getsizeof(x), sizeof + 8) + elif sys.version_info[1] >= 8: # Python 3.8+ + self.assertEqual(sys.getsizeof(x), sizeof - 8) + self.assertFalse(hasattr(x, "__dict__")) # slots! + self.assertTrue(hasattr(x, "_taint")) # taint! + checked.add(ty) + + # Can not instantiate an Expression + for ty in ( + Expression, + # Constant, # These are actually tuples of types + # Variable, + # Operation, + BoolOperation, + BitVecOperation, + ArrayOperation, + BitVec, + Bool, + Array, + ): + self.assertRaises(Exception, ty, ()) + self.assertTrue(hasattr(ty, "__doc__")) + self.assertTrue(ty.__doc__, ty) + checked.add(ty) + + # The test numbers are taken from Python 3.6.13 (the oldest supported version) + # New pythons could use a different number of bytes. Look at the 'check' function + check(BitVecVariable, size=32, name="name", pickle_size=113, sizeof=64) + check(BoolVariable, name="name", pickle_size=102, sizeof=56) + check( + ArrayVariable, + index_bits=32, + value_bits=8, + index_max=100, + name="name", + pickle_size=150, + sizeof=80, + ) + check(BitVecConstant, size=32, value=10, pickle_size=109, sizeof=64) + check(BoolConstant, value=False, pickle_size=97, sizeof=56) + + # But you can instantiate a BoolOr + x = BoolVariable(name="x") + y = BoolVariable(name="y") + z = BoolVariable(name="z") + check(BoolEqual, a=x, b=y, pickle_size=168, sizeof=56) + check(BoolAnd, a=x, b=y, pickle_size=166, sizeof=56) + check(BoolOr, a=x, b=y, pickle_size=165, sizeof=56) + check(BoolXor, a=x, b=y, pickle_size=166, sizeof=56) + check(BoolNot, value=x, pickle_size=143, sizeof=56) + check(BoolITE, cond=z, true=x, false=y, pickle_size=189, sizeof=56) + + bvx = BitVecVariable(size=32, name="bvx") + bvy = BitVecVariable(size=32, name="bvy") + + check(UnsignedGreaterThan, a=bvx, b=bvy, pickle_size=197, sizeof=56) + check(GreaterThan, a=bvx, b=bvy, pickle_size=189, sizeof=56) + check(UnsignedGreaterOrEqual, a=bvx, b=bvy, pickle_size=200, sizeof=56) + check(GreaterOrEqual, a=bvx, b=bvy, pickle_size=192, sizeof=56) + check(UnsignedLessThan, a=bvx, b=bvy, pickle_size=194, sizeof=56) + check(LessThan, a=bvx, b=bvy, pickle_size=186, sizeof=56) + check(UnsignedLessOrEqual, a=bvx, b=bvy, pickle_size=197, sizeof=56) + check(LessOrEqual, a=bvx, b=bvy, pickle_size=189, sizeof=56) + + check(BitVecOr, a=bvx, b=bvy, pickle_size=190, sizeof=64) + check(BitVecXor, a=bvx, b=bvy, pickle_size=191, sizeof=64) + check(BitVecAnd, a=bvx, b=bvy, pickle_size=191, sizeof=64) + check(BitVecNot, a=bvx, pickle_size=162, sizeof=64) + check(BitVecNeg, a=bvx, pickle_size=162, sizeof=64) + check(BitVecAdd, a=bvx, b=bvy, pickle_size=191, sizeof=64) + check(BitVecMul, a=bvx, b=bvy, pickle_size=191, sizeof=64) + check(BitVecSub, a=bvx, b=bvy, pickle_size=191, sizeof=64) + check(BitVecDiv, a=bvx, b=bvy, pickle_size=191, sizeof=64) + check(BitVecMod, a=bvx, b=bvy, pickle_size=191, sizeof=64) + check(BitVecUnsignedDiv, a=bvx, b=bvy, pickle_size=199, sizeof=64) + check(BitVecRem, a=bvx, b=bvy, pickle_size=191, sizeof=64) + check(BitVecUnsignedRem, a=bvx, b=bvy, pickle_size=199, sizeof=64) + + check(BitVecShiftLeft, a=bvx, b=bvy, pickle_size=197, sizeof=64) + check(BitVecShiftRight, a=bvx, b=bvy, pickle_size=198, sizeof=64) + check(BitVecArithmeticShiftLeft, a=bvx, b=bvy, pickle_size=207, sizeof=64) + check(BitVecArithmeticShiftRight, a=bvx, b=bvy, pickle_size=208, sizeof=64) + + check(BitVecZeroExtend, operand=bvx, size_dest=122, pickle_size=180, sizeof=72) + check(BitVecSignExtend, operand=bvx, size_dest=122, pickle_size=180, sizeof=72) + check(BitVecExtract, operand=bvx, offset=0, size=8, pickle_size=189, sizeof=80) + check( + BitVecConcat, + operands=(bvx, bvy), + size_dest=(bvx.size + bvy.size), + pickle_size=194, + sizeof=64, + ) + check( + BitVecITE, + size=bvx.size, + condition=x, + true_value=bvx, + false_value=bvy, + pickle_size=231, + sizeof=64, + ) + + a = ArrayVariable(index_bits=32, value_bits=32, index_max=324, name="name") + check(ArraySlice, array=a, offset=0, size=10, pickle_size=244, sizeof=136) + check(ArraySelect, array=a, index=bvx, pickle_size=255, sizeof=64) + check(ArrayStore, array=a, index=bvx, value=bvy, pickle_size=281, sizeof=120) + check(ArrayProxy, array=a, default=0, pickle_size=222, sizeof=120) + + def all_subclasses(cls) -> Set[Type]: + return {cls}.union( + set(cls.__subclasses__()).union( + [s for c in cls.__subclasses__() for s in all_subclasses(c)] + ) + ) + + all_types = all_subclasses(Expression) + self.assertSetEqual(checked, all_types) + + class ExpressionTest(unittest.TestCase): _multiprocess_can_split_ = True diff --git a/tox.ini b/tox.ini index e132e3b0f..18383b7df 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,9 @@ [tox] -envlist = py3{6,7} +envlist = py3{6,7,8,9} [testenv] -deps = - .[dev] -commands = nosetests tests -install_command = pip install --no-binary keystone-engine {opts} {packages} +deps = .[dev] +commands = pytest -n auto tests [testenv:pep8] deps = flake8 From aabecd4490b2a0a118114dbe6b3938f599faf6b2 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Sun, 28 Feb 2021 14:28:37 -0500 Subject: [PATCH 04/11] Revert "Run CI on slotted branch without PR" This reverts commit 6f3efb1212707a4303b4955f3925687e75e79935. --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3cffb33fe..34468c213 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,6 @@ on: push: branches: - master - - slotted pull_request: schedule: # run CI every day even if no PRs/merges occur From 8aa7b164a12dc47cae647363dcbb04df11da5b7d Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Sun, 28 Feb 2021 14:56:42 -0500 Subject: [PATCH 05/11] Remove pickle data file belonging to deleted test --- tests/other/data/ErrRelated.pkl.gz | Bin 17638 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/other/data/ErrRelated.pkl.gz diff --git a/tests/other/data/ErrRelated.pkl.gz b/tests/other/data/ErrRelated.pkl.gz deleted file mode 100644 index eb1036567ca2ce788a1c79c0ea6973bfe1b2240d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17638 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 BKM4Q; From ebaf51f93f78b4f8e81d85614603ef9b0af558e3 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Tue, 2 Mar 2021 09:13:28 -0500 Subject: [PATCH 06/11] Cleanup test --- tests/other/test_smtlibv2.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/other/test_smtlibv2.py b/tests/other/test_smtlibv2.py index 021b7b2ff..11d4236cf 100644 --- a/tests/other/test_smtlibv2.py +++ b/tests/other/test_smtlibv2.py @@ -93,8 +93,6 @@ class X(object): c = C() c.a = 1 - c.t = 10 - c.b = 2 c.t = 10 From 71dc23c3ce8f362e917e4d2d7a937cf8153c1606 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Tue, 2 Mar 2021 09:24:14 -0500 Subject: [PATCH 07/11] WASM CLI profiler plugin changes to align with ethereum --- manticore/wasm/cli.py | 10 ++++------ tests/wasm/test_examples.py | 1 - 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/manticore/wasm/cli.py b/manticore/wasm/cli.py index 650e51b65..d14a47ef7 100644 --- a/manticore/wasm/cli.py +++ b/manticore/wasm/cli.py @@ -5,6 +5,7 @@ consts = config.get_group("cli") consts.add("target_func", default="main", description="WASM Function to execute") +consts.add("profile", default=False, description="Enable worker profiling mode") def wasm_main(args, _logger): @@ -18,12 +19,9 @@ def wasm_main(args, _logger): policy=args.policy, ) - try: - if consts.profile: - profiler = Profiler() - m.register_plugin(profiler) - except AttributeError: - pass + if consts.profile: + profiler = Profiler() + m.register_plugin(profiler) m.default_invoke(func_name=consts.target_func) diff --git a/tests/wasm/test_examples.py b/tests/wasm/test_examples.py index 39dd73324..61a105313 100644 --- a/tests/wasm/test_examples.py +++ b/tests/wasm/test_examples.py @@ -121,7 +121,6 @@ def test_implicit_call(self): self.assertEqual(sorted(results), [70]) def test_wasm_main(self): - config.get_group("cli").add("profile", False) m = wasm_main( namedtuple("Args", ["argv", "workspace", "policy"])([collatz_file], "mcore_tmp", "ALL"), None, From 888405a64cfea63a0e188dc77b8c0797ca519bc8 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Tue, 2 Mar 2021 09:49:52 -0500 Subject: [PATCH 08/11] Allow double-adding same exact config option --- manticore/utils/config.py | 4 ++++ manticore/wasm/cli.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/manticore/utils/config.py b/manticore/utils/config.py index d9f7b4faa..8310d2e11 100644 --- a/manticore/utils/config.py +++ b/manticore/utils/config.py @@ -103,6 +103,10 @@ def add(self, name: str, default=None, description: str = None): """ if name in self._vars: + # Be kind when double-adding the same exact config + existing = self._vars[name] + if default == existing.default and description == existing.description: + return raise ConfigError(f"{self.name}.{name} already defined.") if name == "name": diff --git a/manticore/wasm/cli.py b/manticore/wasm/cli.py index d14a47ef7..d9d6b06fb 100644 --- a/manticore/wasm/cli.py +++ b/manticore/wasm/cli.py @@ -4,8 +4,8 @@ from ..utils import config consts = config.get_group("cli") -consts.add("target_func", default="main", description="WASM Function to execute") consts.add("profile", default=False, description="Enable worker profiling mode") +consts.add("target_func", default="main", description="WASM Function to execute") def wasm_main(args, _logger): From 73ed092400bcca302642b28799f61a470bd20398 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Tue, 2 Mar 2021 09:53:46 -0500 Subject: [PATCH 09/11] Add test for config double add of exact same option --- tests/other/utils/test_config.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/other/utils/test_config.py b/tests/other/utils/test_config.py index 80f0269ee..3f7d2177d 100644 --- a/tests/other/utils/test_config.py +++ b/tests/other/utils/test_config.py @@ -41,12 +41,17 @@ def test_default_vars(self): self.assertFalse(g._vars["val1"].was_set) self.assertTrue(g._vars["val2"].was_set) - def test_double_add(self): + def test_double_add_different(self): g = config.get_group("test1") g.add("val1", default="foo") with self.assertRaises(config.ConfigError): g.add("val1") + def test_double_add_exact_duplicate(self): + g = config.get_group("test2") + g.add("val1", default="foo", description="Some description") + g.add("val1", default="foo", description="Some description") + def test_update(self): g = config.get_group("update") g.add("val", default="default", description="description") From 11066d7e9bb3f8e5a20b77cdc099be6b72c315ca Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Tue, 2 Mar 2021 10:23:36 -0500 Subject: [PATCH 10/11] Remove unused '#' split suffix on __xslots__ --- manticore/core/smtlib/expression.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/manticore/core/smtlib/expression.py b/manticore/core/smtlib/expression.py index a256b0d0f..009910b9d 100644 --- a/manticore/core/smtlib/expression.py +++ b/manticore/core/smtlib/expression.py @@ -59,9 +59,8 @@ def __new__(cls, clsname, bases, attrs, abstract=False): if abstract: attrs["__slots__"] = tuple() else: - attrs["__slots__"] = tuple(map(lambda attr: attr.split("#", 1)[0], attrs["__xslots__"])) + attrs["__slots__"] = attrs["__xslots__"] attrs["__hash__"] = object.__hash__ - # attrs["__hash__"] = lambda self : hash((clsname, tuple(getattr(self, name) for name in self.__slots__ if name not in ("_concrete_cache", "_written")))) return super().__new__(cls, clsname, bases, attrs) From b2f057bfa5d976c78c1ae455b88c7c07112b0e69 Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Tue, 2 Mar 2021 11:00:15 -0500 Subject: [PATCH 11/11] Remove config code changes that appear in a different PR --- manticore/utils/config.py | 4 ---- manticore/wasm/cli.py | 1 - tests/other/utils/test_config.py | 7 +------ tests/wasm/test_examples.py | 1 + 4 files changed, 2 insertions(+), 11 deletions(-) diff --git a/manticore/utils/config.py b/manticore/utils/config.py index 8310d2e11..d9f7b4faa 100644 --- a/manticore/utils/config.py +++ b/manticore/utils/config.py @@ -103,10 +103,6 @@ def add(self, name: str, default=None, description: str = None): """ if name in self._vars: - # Be kind when double-adding the same exact config - existing = self._vars[name] - if default == existing.default and description == existing.description: - return raise ConfigError(f"{self.name}.{name} already defined.") if name == "name": diff --git a/manticore/wasm/cli.py b/manticore/wasm/cli.py index d9d6b06fb..e474ce732 100644 --- a/manticore/wasm/cli.py +++ b/manticore/wasm/cli.py @@ -4,7 +4,6 @@ from ..utils import config consts = config.get_group("cli") -consts.add("profile", default=False, description="Enable worker profiling mode") consts.add("target_func", default="main", description="WASM Function to execute") diff --git a/tests/other/utils/test_config.py b/tests/other/utils/test_config.py index 3f7d2177d..80f0269ee 100644 --- a/tests/other/utils/test_config.py +++ b/tests/other/utils/test_config.py @@ -41,17 +41,12 @@ def test_default_vars(self): self.assertFalse(g._vars["val1"].was_set) self.assertTrue(g._vars["val2"].was_set) - def test_double_add_different(self): + def test_double_add(self): g = config.get_group("test1") g.add("val1", default="foo") with self.assertRaises(config.ConfigError): g.add("val1") - def test_double_add_exact_duplicate(self): - g = config.get_group("test2") - g.add("val1", default="foo", description="Some description") - g.add("val1", default="foo", description="Some description") - def test_update(self): g = config.get_group("update") g.add("val", default="default", description="description") diff --git a/tests/wasm/test_examples.py b/tests/wasm/test_examples.py index 61a105313..39dd73324 100644 --- a/tests/wasm/test_examples.py +++ b/tests/wasm/test_examples.py @@ -121,6 +121,7 @@ def test_implicit_call(self): self.assertEqual(sorted(results), [70]) def test_wasm_main(self): + config.get_group("cli").add("profile", False) m = wasm_main( namedtuple("Args", ["argv", "workspace", "policy"])([collatz_file], "mcore_tmp", "ALL"), None,