Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

evm: aggressively check & migrate expressions into current ConstraintSet in case they are global/external #1009

Merged
merged 36 commits into from
Aug 17, 2018

Conversation

feliam
Copy link
Contributor

@feliam feliam commented Jul 31, 2018

this pr introduces advanced functionality (state.migrate_expression, and friends) for migration of potentially external/global ("foreign") expression objects into a particular ConstraintSet. with recent developments in the Ethereum API specifically (global expressions via `ManticoreEVM.make_....1), we expect foreign expressions to be passed into these interfaces fairly frequently now, so that PR "aggressively" adds a call to this function in nearly every interface that accepts an expression object, in order to be as safe as possible

from manticore.ethereum import ManticoreEVM
from manticore.core.smtlib import Operators
from manticore.core.smtlib import solver

m = ManticoreEVM()

contract_src='''
contract Overflow {
  uint public sellerBalance=0;

  function add(uint value)public  returns (bool){
      sellerBalance += value;
  }
}
'''

owner_account=m.create_account(balance=1000)
attacker_account=m.create_account(balance=1000)
contract_account=m.solidity_create_contract(contract_src,
                                            owner=owner_account,
                                            balance=0)

#Some global expression `sym_add1` 
sym_add1 = m.make_symbolic_value(name='sym_add1')
#Let's constraint it on the global fake constraintset
m.constrain(sym_add1>0)
m.constrain(sym_add1<10)
#Symb tx 1
contract_account.add(sym_add1, caller=attacker_account)

# A new!? global expression 
sym_add2 = m.make_symbolic_value(name='sym_add2')
#constraints involve old expression.  Some states may get invalidated by this. Should this be accepted?
m.constrain(sym_add1 > sym_add2)
#Symb tx 2
contract_account.add(sym_add2, caller=attacker_account)

#random concrete tx
contract_account.sellerBalance(caller=attacker_account)

#anooother constraining on the global constraintset. Yet more running states could get unfeasible by this.
m.constrain(sym_add1 > 8)



for state_num, state in enumerate(m.all_states):

    if state.is_feasible():
        #todo merge with some expression got froms state
        print ('feasible state found')
        print ('sym_add1', state.solve_one(sym_add1))
        print ('sym_add2', state.solve_one(sym_add2))
        m.generate_testcase(state, 'test{}'.format(state_num))

This change is Reviewable

@offlinemark
Copy link
Contributor

ConstraintSet.get_variable() 😍

Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a user does something like cs.new_bitvec(name='myvar') then that variable will get a new name like myvar_1 via _get_new_name. that new name is what's used as the dict key. so if a user then goes to do cs.get_variable('myvar') it won't work, right?

@feliam
Copy link
Contributor Author

feliam commented Jul 31, 2018

I guess so. The name= is then a suggestion. User should do a cs.get_variable(var.name) -> var

@offlinemark
Copy link
Contributor

I see. that's very non-obvious :)

why do we need to do the _get_new_name thing? could we throw an error if a name is passed that already exists? or have an optional flag to do the new name thing?

from a user perspective it would be very nice to just pick a name for the variable and be able to use that throughout.

@feliam
Copy link
Contributor Author

feliam commented Jul 31, 2018

If it does not exist the name the user picked would be the same as in the returned var.name.
Throwing when already exists will pull in a lot of try:except:
How would the new signature of new_bitvec? We can also change name for suggestedname :)
pyz3 returns the old variable with the same name on that 🤷‍♀️

@offlinemark
Copy link
Contributor

offlinemark commented Jul 31, 2018

If it does not exist the name the user picked would be the same as in the returned var.name

it looks to me like we unconditionally append digits and change the name

my mistake, didn't read the pr closely enough yet.

name = self._get_new_name(name)

How would the new signature of new_bitvec?

very roughly, here's an idea

# ignoring self, size, taint
def new_bitvec(name, avoid_name_collision=False)
    if avoid_name_collision:
        if name exists:
            name = get_name_name(name)
    else:
        if name exists:
            raise Exception
    return BitVecVariable(name)


@@ -631,7 +631,7 @@ def get_source_for(self, asm_offset, runtime=True):

@property
def signatures(self):
return dict(((b, a) for (a, b) in self._hashes.items()))
return dict(((b.encode(), a) for (a, b) in self._hashes.items()))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we want to ref them as bytes should probably just store them as bytes rather than decoding every item on each access to signatures.

since its a hex string, should probably just be str no? this is where python static typing stuff would be handy

@feliam
Copy link
Contributor Author

feliam commented Aug 1, 2018

rename=True/False instead of avoid_name_collision=True/False ?
Also if "avoid_name_collision=False" should it raise or return the old known version of the variable (In which case we'll need to remove the "new_" from the name) ?

@offlinemark
Copy link
Contributor

rename=True/False instead of avoid_name_collision=True/False ?

i do think avoid_name_collision is pretty clunky, i didn't put much thought into it :) . but i'm not sure if rename is expressive enough. maybe strict=? avoid_collision

alternatively what if we have

new_bitvec(name=None, prefix=None).

if you specify name, it must not exist, otherwise an error will be thrown.
if you specify prefix, you don't care, and things will be appended to it to make it unique.
it is an error to specify both.
if none are specified, and random name default name/prefix will be chosen.

Also if "avoid_name_collision=False" should it raise or return the old known version of the variable (In which case we'll need to remove the "new_" from the name) ?

I think it should raise there. trying to a create a "new" one with an existing name is an error condition imo. users should probably check to see if a name exists before trying to make a new one. i guess they would use get_variable() for this check?

@offlinemark
Copy link
Contributor

offlinemark commented Aug 3, 2018

my understanding is that there two main users of the new_bitvec etc class of functions.

  1. external users
  2. the manticore core

the name= interface is geared for the external users, who have a specific variable in mind they want to create, and want to attach a name to it so they can find it later. since they want to find it later, we should not change it, and raise an exception.

the prefix= interface is meant for the manticore core, for example places like here

aux = temp_cs.new_bitvec(X.size, name='optimized_')

where the name is somewhat auto generated, and doesn't particularly matter to anyone anyway, so it's fine to change it.

this could all be overcomplicating things though. i'm fine with the name=, bool_flag= interface, and i think either rename= or avoid_collisions= would be good. i'm happy with either, @feliam i'll let you choose :)

@feliam feliam changed the title Be mega forgiving on global expression usage - EVM [WIP] Be mega forgiving on global expression usage - EVM Aug 8, 2018
@feliam feliam changed the title [WIP] Be mega forgiving on global expression usage - EVM Be mega forgiving on global expression usage - EVM Aug 9, 2018
Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 5 files reviewed, 2 unresolved discussions (waiting on @feliam)


manticore/core/state.py, line 211 at r4 (raw file):

        label = options.get('label', 'buffer')
        taint = options.get('taint', frozenset())
        expr = self._constraints.new_array(name=label, index_max=nbytes, value_bits=8, taint=taint, avoid_collisions=True)

since this is a user API, I think this should be avoid_collisions=False, if they gave a label/name, otherwise avoid_collissions=True. same below

Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks awesome, really great work! i don't have a lot of really substantial comments. a lot of it is naming/readability related. a few thoughts on use of avoid_collisions

Reviewable status: 0 of 5 files reviewed, 15 unresolved discussions (waiting on @feliam)


manticore/ethereum.py, line 1198 at r4 (raw file):

                                value=100000 )
        '''
        return self.constraints.new_array(index_bits=256, name=name, index_max=size, value_bits=8, taint=frozenset(), avoid_collisions=True)

i'm also thinking avoid_collisions here should depend on whether a name was given


manticore/ethereum.py, line 1239 at r4 (raw file):

                state_constraints = state.constraints

                migration_bindings = state.context.get('migration_bindings')

can be simplified to .get('migration_bindings', {})


manticore/ethereum.py, line 1242 at r4 (raw file):

                if migration_bindings is None:
                    migration_bindings = {}
                migrated_constraint = state_constraints.migrate(constraint, migration_bindings=migration_bindings)

we should use state.migrate_expression here? it looks copypastad


manticore/ethereum.py, line 1784 at r4 (raw file):

        return self.accounts[name]

    def __migrate_tx_expressions(self, state, caller, address, value, data):

nit, i think we should use 1 underscore here. 2 means something special i think


manticore/ethereum.py, line 1796 at r4 (raw file):

            if migration_bindings is None:
                migration_bindings = {}
            if issymbolic(caller):

imo we should add some comments here to explain why, it's not super obvious. I guess the reason is that commonly users will be making these symbolic by creating global symbolic variables via ManticoreEVM.make_.... and those global expressions need to be imported into each state when a tx actually happens


manticore/core/state.py, line 281 at r4 (raw file):

    def can_be_true(self, expr):
        expr = self.migrate_expression(expr)

i wonder if it's necessary to sprinkle this everywhere now. maybe the user should be aware when they are mixing expressions with unrelated states/constraintsets and call migrate_expression first?


manticore/core/smtlib/constraints.py, line 213 at r4 (raw file):

        return self.to_string()

    def _get_new_name(self, name='VAR'):

nit, while we're here maybe we can rename this to _make_unique_name


manticore/core/smtlib/constraints.py, line 219 at r4 (raw file):

        return name

    def migrate(self, expression, migration_bindings=None):

maybe migrate_expression would be a better name here. it took me a bit to understand that the only affect on the state here was adding variables, but didn't automatically apply the expression/constraint. not totally sure about this, maybe migrate is enough. might be enough to just add some more details to the docstring on how this function basically just creates the needed variables in the constraint set


manticore/core/smtlib/constraints.py, line 225 at r4 (raw file):

            :param migration_bindings: a name to name mapping of already migrated variables
        '''
        if migration_bindings is None:

i think this name is also a bit confusing, rather than call them bindings, maybe "map". i think a little more verbose description of what this variable is would be useful.


manticore/core/smtlib/constraints.py, line 231 at r4 (raw file):

        #  Based on the name mapping in migration_bindings build an object to
        #  object mapping to be used in the replacing of variables
        fat_bindings = {}

i think we should choose a better name for fat_bindings, it's not very clear what it is based on the name. it's the actual map from "alient" expression object, to the newly created native object. maybe something like foreign_to_native_expression_map? but that is pretty verbose. i think throughout this code could be made more readable by deciding on a convention like "foreign"/"native" or alien/local etc etc and using those in the variable names throughout. i can submit a PR with what i think could be more readable


manticore/core/smtlib/constraints.py, line 236 at r4 (raw file):

        for old_name in expression_variables:
            migrated_name = migration_bindings.get(old_name)
            if migrated_name in declared_names:

rather than have this declared_names variable, we could use self.get_variable for this check? e.g

native_var = self.get_variable(migrated_name)
if native_var is not None:
  fat_bindings[....] = native_var

it would make this a bit easier to read by reducing the number of local vars


manticore/core/smtlib/constraints.py, line 255 at r4 (raw file):

            if name in self._declarations:
                name = self._get_new_name(var.name + '_migrated')
            if name in self._declarations:

should we use a loop here? the point is to get a unique name right? loop bumping some int until we have a unique name?


manticore/core/smtlib/constraints.py, line 265 at r4 (raw file):

                new_var = self.new_array(index_max=var.index_max, index_bits=var.index_bits, value_bits=var.value_bits, name=name).array
            else:
                raise NotImplemented("Unknown type {}".format(type(var)))

this err msg could be a bit more verbose, "Unknown expression type encountered during expression migration"

@feliam
Copy link
Contributor Author

feliam commented Aug 14, 2018


manticore/core/smtlib/constraints.py, line 220 at r7 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

i understand the theoretical use of the name_migration_map, but im having trouble thinking of an actual use case. i don't think the code even really uses it right now. can you give an example of a use case?

The idea is that when you migrate the same variable twice it maps to the same local variable.

It maps alien names with local declared names.
If there are 2 alien variables (for example from 2 other different constraint sets) with the same name it will be a collision.
This name map get serialized with the state in the state context.

Copy link
Contributor Author

@feliam feliam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 5 of 8 files reviewed, 6 unresolved discussions (waiting on @Mossberg and @feliam)


manticore/core/smtlib/constraints.py, line 215 at r5 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

we should just do if name in self._declarations

Done.


manticore/core/smtlib/constraints.py, line 269 at r5 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

I still don't see why we need to create that list of tuples. get_variables() returns a set. why can't we just iter through the set?

for expression_var in get_variables(expression):
  # blah blah expression_var.name

Done.


manticore/core/smtlib/constraints.py, line 271 at r5 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

ok, i reread this, and i'm still having trouble understanding it exactly.

--

is it correct to say that object_migration_map's keys should ALWAYS be external/foreign expressions, and its values should ALWAYS be internal/local expressions?

if this is the case, this invariant can be violated if

  • expression_var is a local ConstraintSet variable
  • expression_name is in migration_map and it's value corresponds to an expression that is also in this ConstraintSet

in which keys object_migration_map will record a mapping from a local expression to another local expression, which I don't understand, since there is no migration necessary in this case?

--

i'm also confused by this .get() call. is the intention for this loop body to do nothing if expression_name is not in the name_migration_map? right now i can see that it is implicitly doing nothing, because the .get() will return None, which will cause get_variable() to return None. however this is pretty convoluted. if this is the intention, I think we should have an explicit if migrated_name is None: continue line

is it correct to say that object_migration_map's keys should ALWAYS be external/foreign expressions, and its values should ALWAYS be internal/local expressions? that's correct.

Let see how the new arrangement holds up with that invariant in mind.. actually I'm adding it as a comment.


manticore/core/smtlib/constraints.py, line 284 at r5 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

i'm confused by this check in the first place. when would this if succeed?

shouldn't we instead be checking if var exists as a key in object_migration_map? the point here is to check if it already has a replacement assigned, right?

so right now we're checking if it's in the values. from what i see, all of the values in object_migration_map belong to the local ConstraintSet. therefore, they would appear in get_declared_variables, and above get_declared_variables check would succeed. so i don't quite see how we would get past this if.

Done.


manticore/core/smtlib/constraints.py, line 216 at r8 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

i'd like to add a comment here

"the while loop is necessary because appending the result of _get_sid() is not guaranteed to make a unique name on the first try; a colliding name could have been added previously"

Done.

Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great, algorithm looks sound to me now, and i love that it's not 2 loops :)

Reviewed 3 of 3 files at r9.
Reviewable status: all files reviewed, 9 unresolved discussions (waiting on @feliam)


manticore/core/smtlib/constraints.py, line 223 at r9 (raw file):

        return name

    def migrate(self, expression, name_migration_map=None):

ok, i finally understand name_migration_map. it took a while for it to click to me that this is persistently stored in the State and passed into this on each migration. I think to make this code more readable, I'd like to propose renaming name_migration_map to previously_migrated_map


manticore/core/smtlib/constraints.py, line 234 at r9 (raw file):

            ```
            from manticore.core.smtlib import *

now that there's a unit test can we rm this? it will just become bitrotted and outdated.


manticore/core/smtlib/constraints.py, line 261 at r9 (raw file):

            :param expression: the potentially foreign expression
            :param name_migration_map: a name to name mapping of already migrated variables

would like to expand on this:

:param previously_migrated_map: mapping of already migrated variables. maps from string name of foreign variable to its currently existing migrated string name


manticore/core/smtlib/constraints.py, line 278 at r9 (raw file):

            # do nothing if it is a known/declared variable object
            if any(expression_var is x for x in self.get_declared_variables()):

this strikes me as worth being a ConstraintSet method. will make this already complex function easier to read. if self.is_declared(expression_var) or if expression_var in self?


manticore/core/smtlib/constraints.py, line 285 at r9 (raw file):

                migrated_name = name_migration_map[expression_var.name]
                native_var = self.get_variable(migrated_name)
                if native_var is None:

this actually looks more appropriate for an assert to me. this is not an error condition that we expect to ever happen, assert native_var is not None is a strict invariant? it seems like a serious internal error if name_migration_map/previously_migrated_map contains a value which does not exist.


manticore/core/smtlib/constraints.py, line 286 at r9 (raw file):

                native_var = self.get_variable(migrated_name)
                if native_var is None:
                    raise Exception("name_migration_map contains an unknown variable")

i'd say "contains a variable that does not exist in this ConstraintSet" to be very clear


manticore/core/smtlib/constraints.py, line 289 at r9 (raw file):

                object_migration_map[expression_var] = native_var
                #continue if there is already a migrated variable for it
                continue

i think we would also improve the readability by removing the "continue" and using an explicit "else" block for the below block where a new_var is created. what do you think?

if expression_var in self: # or whatever
  continue

# what about this? just for readability I guess. at this point, we've confirmed it's foreign. this naming throughout helps the reader understand the key invariant commented above.
foreign_var = expression_var


if foreign_var.name in previously_migrated_map:
    #
    native_var = ....
else:
    # make new_var

    native_var = new_var
    previously_migrated[foreign_var.name] = new_var.name

object_migration_map[foreign_var] = native_var



manticore/core/smtlib/constraints.py, line 292 at r9 (raw file):

            # expression_var was not found in the local declared variables nor
            # any variable with the dsame name was previously migrated

dsame typo


tests/test_models.py, line 30 at r9 (raw file):

    def _clear_constraints(self):
        self.state.context['migration_map']=None

why is this necessary exactly? should the migration stuff be able to gracefully default if 'migration_map' is not in the context? migration stuff has no relevance to model tests, so i don't really think this should be here.

Copy link
Contributor Author

@feliam feliam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 9 unresolved discussions (waiting on @feliam and @Mossberg)


manticore/core/smtlib/constraints.py, line 234 at r9 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

now that there's a unit test can we rm this? it will just become bitrotted and outdated.

Done.


manticore/core/smtlib/constraints.py, line 278 at r9 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

this strikes me as worth being a ConstraintSet method. will make this already complex function easier to read. if self.is_declared(expression_var) or if expression_var in self?

Done.


manticore/core/smtlib/constraints.py, line 285 at r9 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

this actually looks more appropriate for an assert to me. this is not an error condition that we expect to ever happen, assert native_var is not None is a strict invariant? it seems like a serious internal error if name_migration_map/previously_migrated_map contains a value which does not exist.

Done.


manticore/core/smtlib/constraints.py, line 289 at r9 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

i think we would also improve the readability by removing the "continue" and using an explicit "else" block for the below block where a new_var is created. what do you think?

if expression_var in self: # or whatever
  continue

# what about this? just for readability I guess. at this point, we've confirmed it's foreign. this naming throughout helps the reader understand the key invariant commented above.
foreign_var = expression_var


if foreign_var.name in previously_migrated_map:
    #
    native_var = ....
else:
    # make new_var

    native_var = new_var
    previously_migrated[foreign_var.name] = new_var.name

object_migration_map[foreign_var] = native_var


I tried to pre-filter the list of variable so we do not need to "continue"


manticore/core/smtlib/constraints.py, line 292 at r9 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

dsame typo

Done.


tests/test_models.py, line 30 at r9 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

why is this necessary exactly? should the migration stuff be able to gracefully default if 'migration_map' is not in the context? migration stuff has no relevance to model tests, so i don't really think this should be here.

This is trying to clean the constraints of a constraintset in a state and re use it. If you keep old migration mappings there is trouble. I can skip the test that make problem if you prefer and you fix them later?

Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 7 of 8 files reviewed, 5 unresolved discussions (waiting on @Mossberg and @feliam)


manticore/core/smtlib/constraints.py, line 227 at r10 (raw file):

        if not isinstance(expression_var, Variable):
            raise ValueError("Expression must be a Variable")
        return any(expression_var is x for x in self.get_declared_variables()):

watch out! stray colon!

Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 1 files at r10.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on @feliam)


manticore/core/smtlib/constraints.py, line 242 at r10 (raw file):

            :param name_migration_map: mapping of already migrated variables. maps from string name of foreign variable to its currently existing migrated string name. this is updated during this migration.
            :return: a migrated expresion where all the variables are fresh BoolVariable. name_migration_map is updated

are all the variables in the returned expression BoolVariable? couldn't they just be regular variables? for example, if a BitVecAdd with 2 BitVec children was "migrated", wouldn't the returned expression look the same? There would be no BoolVariables?


manticore/core/smtlib/constraints.py, line 265 at r10 (raw file):

                assert native_var is not None, "name_migration_map contains a variable that does not exist in this ConstraintSet"
                object_migration_map[foreign_var] = native_var
                #continue if there is already a migrated variable for it

don't need this comment anymore

Copy link
Contributor

@yan yan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @feliam)


manticore/core/smtlib/constraints.py, line 173 at r10 (raw file):

    def get_variable(self, name):
        ''' Returns the variable declared under name or None if it does not exists '''
        if name not in self._declarations:

return self._declarations.get(name, None)?


manticore/core/smtlib/constraints.py, line 275 at r10 (raw file):

                    migrated_name = self._make_unique_name(foreign_var.name + '_migrated')
                # Create and declare a new variable of given type
                if isinstance(foreign_var, Bool):

This pattern comes up pretty regularly (in Solver.get_all_values, Solver.get_value, here), should we make a Expression.clone() method that a few relevant classes can override?

Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @feliam)


manticore/core/smtlib/constraints.py, line 275 at r10 (raw file):

Previously, yan (Yan Ivnitskiy) wrote…

This pattern comes up pretty regularly (in Solver.get_all_values, Solver.get_value, here), should we make a Expression.clone() method that a few relevant classes can override?

i generally agree, but i think we should save that for a different PR. this one already has a lot of complexity

Copy link
Contributor Author

@feliam feliam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @feliam, @Mossberg, and @yan)


manticore/core/smtlib/constraints.py, line 242 at r10 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

are all the variables in the returned expression BoolVariable? couldn't they just be regular variables? for example, if a BitVecAdd with 2 BitVec children was "migrated", wouldn't the returned expression look the same? There would be no BoolVariables?

Done.


manticore/core/smtlib/constraints.py, line 265 at r10 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

don't need this comment anymore

Done.


manticore/core/smtlib/constraints.py, line 275 at r10 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

i generally agree, but i think we should save that for a different PR. this one already has a lot of complexity

diff pr

Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewed 1 of 1 files at r11.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @feliam and @yan)


manticore/core/smtlib/constraints.py, line 173 at r10 (raw file):

Previously, yan (Yan Ivnitskiy) wrote…

return self._declarations.get(name, None)?

+1

Copy link
Contributor Author

@feliam feliam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @yan)


manticore/core/smtlib/constraints.py, line 173 at r10 (raw file):

Previously, mossberg (Mark Mossberg) wrote…

+1

Done.


manticore/core/smtlib/constraints.py, line 275 at r10 (raw file):

Previously, feliam (feliam) wrote…

diff pr

Let's make an issue maybe?

@feliam
Copy link
Contributor Author

feliam commented Aug 16, 2018


manticore/core/smtlib/constraints.py, line 275 at r10 (raw file):

Previously, feliam (feliam) wrote…

Let's make an issue maybe?

#1059
done!

Copy link
Contributor Author

@feliam feliam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 7 of 8 files reviewed, 2 unresolved discussions (waiting on @Mossberg and @yan)


manticore/core/smtlib/constraints.py, line 275 at r10 (raw file):

Previously, feliam (feliam) wrote…

#1059
done!

Done.

Copy link
Contributor

@offlinemark offlinemark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewed 1 of 1 files at r12, 1 of 1 files at r13.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @yan)

@feliam feliam merged commit ec28281 into master Aug 17, 2018
@feliam feliam deleted the dev-research-migration branch August 17, 2018 16:47
yan added a commit that referenced this pull request Sep 6, 2018
* Python 3; optimization / stylization pass
  * cleanup list() from automation tools
  * style; use dict comprehensions
  * style; use set literals

* Experiment reporting the finding at a JUMPI (#949)

* Experiment reporting the finding at a JUMPI

* Fix taint. Detect returned overflowded data

* Fix contract names in benchmark

* Move default plugin registration

* merge

* rm make_evm (#978)

* Yolo dev evm fix address concretization (#1002)

* DAO detector + bugfixes

* The actual benchmark tests

* The actual benchmark tests

* CC

* Experiment reporting the finding at a JUMPI

* Fix taint. Detect returned overflowded data

* DAO -> Reentrancy

* DAO -> reentrancy, C -> Benchmark

* DAO -> reentrancy, C -> Benchmark

* Allow function names to have numbers

* Fix contract names in benchmark

* Fix contract names in benchmark

* Move default plugin registration

* Better regexp

* Fix minimal_bytecode example

* Fix Array Slice and test

* add tests

* correct other bug

* implement bytesM

* BROKEN partial progress

* need bytearray here

* rm cmt

* add basic tests for bytesM and bytes symbolic

* correct bytes symbolic test

* Refactor, clean bytesM handling

* Add initial symbolic 'bytes' handling

* refactor tests

* Unify symbolic/concrete bytes handling in bytesM/bytes

* Rm import

* Rm debug assert

* cc

* Visitor/migrate/simplify fixes to make the seth refactor pass

* Fix concolic?

* Fix concolic?

* CC

* bytesM fix

* Fix address and caller concretization on symb tx

* Fix account policy refactor

* CC

* cleanup

* numbers.Integral

* super()

* remove/update deprecated

* Report test coverage to CodeClimate (#1004)

This PR enables the reporting of test coverage of all the test jobs (`eth` and `tests`) to CodeClimate. This uses S3 to temporarily store results between jobs and later upload them to CC.

Fixes #1000

* codeclimate

* codeclimate - bump similar-code thresh; false positive

* Fix CC coverage (#1007)

This fix does two things:

 1. Ignores non-manticore files from the coverage report to limit what can fail.
 2. Changes how travis runs s3 sync on completion. (Fixes #1006)

* Report test coverage to CodeClimate (#1004)

This PR enables the reporting of test coverage of all the test jobs (`eth` and `tests`) to CodeClimate. This uses S3 to temporarily store results between jobs and later upload them to CC.

Fixes #1000

* Fix CC coverage (#1007)

This fix does two things:

 1. Ignores non-manticore files from the coverage report to limit what can fail.
 2. Changes how travis runs s3 sync on completion. (Fixes #1006)

* re-enable and fix eth regression 808 (#1011)

* cleanup examples (#1010)

* resolves #1008 (#1014)

* Addresses performance issues;
  * reimplement caching for `arithmetic_simplifier` and `constant_folder`
  * optimize `ArithmeticSimplifier.visit_ArraySelect`

* File mode fix - resolves #1018

* Fixes closed file serialization (#955)

Fixes #954

* Add unit test for 954 (#1022)

* Change how we query for version (#1023)

Fixes #1021

This also should decrease how many times we invoke z3. (The instance used to query version should stick around)

* Use capstone 3.0.5 and no longer rc2 (#1026)

* binja cleanup

* fixes docker - resolves #991

* Dev yolo retvalthing (#1001)

* DAO detector + bugfixes

* The actual benchmark tests

* The actual benchmark tests

* CC

* Experiment reporting the finding at a JUMPI

* Fix taint. Detect returned overflowded data

* DAO -> Reentrancy

* DAO -> reentrancy, C -> Benchmark

* DAO -> reentrancy, C -> Benchmark

* Allow function names to have numbers

* Fix contract names in benchmark

* Fix contract names in benchmark

* Move default plugin registration

* Better regexp

* Fix minimal_bytecode example

* Fix Array Slice and test

* add tests

* correct other bug

* implement bytesM

* BROKEN partial progress

* need bytearray here

* rm cmt

* add basic tests for bytesM and bytes symbolic

* correct bytes symbolic test

* Refactor, clean bytesM handling

* Add initial symbolic 'bytes' handling

* refactor tests

* Unify symbolic/concrete bytes handling in bytesM/bytes

* Rm import

* Rm debug assert

* cc

* Visitor/migrate/simplify fixes to make the seth refactor pass

* Fix concolic?

* Fix concolic?

* CC

* bytesM fix

* Fix address and caller concretization on symb tx

* Fix/refactor symbolic address/caller concretization

* Fix caller concretization

* Fix expression visiting

* Fix account policy refactor

* Accept numbers in function names abitypes

* Simplify installation instructions to recommend install manticore only for the current user

* Run some tests in parallel (#970)

This PR splits the current test runner into three environments: 

1. Linux examples
2. Ethereum tests
3. Remaining tests

to faster complete each testing run. Ethereum tests include a number of integration tests that execute scripts to completion, which takes a while. We run them concurrently with other tests to save on execution time. The split is done by naming Ethereum tests differently (`eth_*.py` vs `test_*.py`) and updating what pattern unittest's `discover` uses.

This change also updates the installation script and chooses to forego installing Keystone for EVM tests as it takes a while, and it adds a `setup.cfg` config file so that Nose finds the eth tests as well by default.

* Be less verbose when testing

* Fix slicing wrongly reference to proxyArray. Fix #912

* Only export human/external tx in the testcase (#972)

* Make ManticoreEVM.make_symbolic_value size adjustable (#974)

* Make size adjustable

* Default to 256

* Dev evm yolo fix gas (#975)

* Fix gas stipend on CALL and check dao

* Add order dependence 1

* Going linter. Report/Detect that thing when code does not check returned value

* cleaner example of fail

* Update retval_crazy.sol

* new solc for travis

* CC

* Remove duplicated ReentrancyDetector

* POrt to py3

* POrt to py3

* P0rt to py3

* CC

* Tests doc

* CC

* review changes

* remove stray comment

* missed one

* resolves #992 (#1033)

* resolves #992

* fix sys_write logger output (#1024)

* fix sys_write logger output - resolves #1020
* write/writev/read fixes
* openat((int32)dirfd, ...) resolves #940, syscall logging
* disable E701, interferes with PEP484/526

* readme Ethereum update issue #1003 (#1034)

* readme ethereum update issue #1003

* simplify

* Update README.md

* ignore resource warnings (e.g. unclosed files) (#1038)

* Test manticore on MacOS (#1032)

* Test manticore on MacOS

like test_binaries.py for path to binary to test

* MacOS compatibility achieved

Replacement of /bin/ls in tests
Use of basename in test_load_maps

* Fix gast (#1039)

* Readme updates (#1037)

* add some more heft to the Ethereum section

* no longer needed

* Integrate requirements into installation

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Duplicate commands for docker quick start

* Rm --process-dependency-links note, moved into the faq on the wiki

* Small tweaks

* pedantic formatting

* Emphasize new python requirement (#1041)

* Emphasize new python requirement

* Consistent formatting

* Port remaining examples to py3 (#1042)

* port use_def

* port some scripts, cleanup

* ported `scripts/gdb.py` - untested

* misc

* Manticore 0.2.0 (#1043)

* Bump version

* Initial changelog changes

* Bump version in setup.py

* Add skeleton and externals

* Fill in 0.2.0 readme

* Updates

* Add logo to readme (#1046)

* add logo to README

* Fix missing profiling data (#1057)

* fix missing profiling data - resolves #982
* unit test

* Code cleanup and coverage (#1035)

* dead code elimination, __init__ cleanup
* `binary.Elf` bugfix, add `binary` package tests

* Serialization cleanup (#1048)

* refactor serialization / recursion limit handling

* evm: aggressively check & migrate expressions into current ConstraintSet in case they are global/external (#1009)

* Be mega forgiving on global expression usage - EVM

* Refactor new_bitvector api

* Fix neW_bool

* CC

* rename avoid_collisions collision

* rename avoid_collisions collision

* migrate on state.constraint too..

* Migration bugfixes

* CC bugfixes

* invalid assert removed

* move rep code to method

* reviewing the codes

* CC

* Change variable names

* typo

* Some mini docstrings and a unittest

* Add migration integration testion

* Keep fuzz-refactoring it

* CC

* Bugfixfixfixfix

* CC

* re refactor mig algorithm

* better cleaner stronger. (reviewing)

* CC

* Small refactor and Fix strange strcmp test.

* CC

* re re refactor for readability

* CC

* rev

* forgoten var

* Fix for #1008 (#1063)

* Fix for #1008

* add test for funcall output

* Implements support for function overloading in ethereum (#1049)

* implements `signature` kwarg for overloaded functions - resolves #810

* Fix typo mistake in multi-million word (#1073)

* eth: add selfdestruct detector & misc bug fixes (#1068)

* Don't keep selfdestruct states alive

* Use avoid_collisions=True for internal uses of the .new_ methods

* Better err msgs

* Output pc in hex

* Fix ignored workspace cli flag

* hex pc

* hex pc one last time

* add selfdestruct detector

* Add cli support

* Add ok selfdestruct test

* Add selfdestruct not ok - true positive

* Add selfdestruct crazy - true negative

* Reorganize plugin/detectors. Add LoopDepthLimiter plugin + cli flag

* rename files

* add another test

* Add initial selfdestruct tests

* Move integer overflow detector test into eth_detectors

* cc

* add missing import

* add other missing import

* Added --txnoether option to avoid sending ether to contracts (#1078)

* added --txnoether option

* Improved command line description

* eth: add ether leak detector (#1077)

* Add initial ether leak detector

* Initial test

* correct

* Add another neg

* rm stray print

* initial tests refactoring + ether leak tests

* finding name

* initial refactor

* clean comment

* correct this test

* update tests

* Add fp comment

* add other test

* remove unnecessary payable function

* make LoopDepthLimiter configurable

* Use real pc

* cc

* Add other test

* Add cli interface

* Create readthedocs.yml (#1085)

* Fix rtd (#1086)

* test

* wrong number

* sorry Popen :(

* mocking

* x

* clean

* better explain this arcane stuff

* don't need io

* Improved printing of constructor call with decoded constructor arguments and transaction result (#1080)

* added printing of decoded constructor arguments

* Fixed test

* Add --no-testcases flag (#1083)

* Update the README (#1064)


<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/trailofbits/manticore/1064)
<!-- Reviewable:end -->

* Add detector for plain external call (#1087)

* initial refactor etherleak to also do general external call

* refactor

* Update users

* Update tests

* Update

* Fix tests

* Don't use signed operator, check != 0

* Record constraint

* Record constraint

* Use did_evm_execute

So we don't falsely report if the CALL were to fail

* Revert "Use did_evm_execute"

96a84f2

* simplify deref logic

* clean up derefs; rename backing array

* reduce write calls

* simplify

* add name field

* Detection of environmental and potentially manipulable instruction/data (#1096)

* unittest

* CC

* import fix

* typo

* forgotten test

* eth: new/alternative reentrancy detector (#1082)

* initial second one

* update

* polish

* correct

* Correctly check gas

* Record gas constraint and save in finding

* simplify logic

* Check if destination is a contract

* Revert "Check if destination is a contract"

901be37

* better context key

* Be lenient with Constants

* Add new simpler/less input required reentrancy detector, use in the cli

* Fix bad merge import

* Fix import

* Add final missing import

* add an iter() interface to Memory

* Add env instruction detector to cli (#1105)

* Sha3 rework and performance enhancements (#1031)

* DAO detector + bugfixes

* The actual benchmark tests

* The actual benchmark tests

* CC

* Experiment reporting the finding at a JUMPI

* Fix taint. Detect returned overflowded data

* DAO -> Reentrancy

* DAO -> reentrancy, C -> Benchmark

* DAO -> reentrancy, C -> Benchmark

* Allow function names to have numbers

* Fix contract names in benchmark

* Fix contract names in benchmark

* Move default plugin registration

* Better regexp

* Fix minimal_bytecode example

* Fix Array Slice and test

* add tests

* correct other bug

* implement bytesM

* BROKEN partial progress

* need bytearray here

* rm cmt

* add basic tests for bytesM and bytes symbolic

* correct bytes symbolic test

* Refactor, clean bytesM handling

* Add initial symbolic 'bytes' handling

* refactor tests

* Unify symbolic/concrete bytes handling in bytesM/bytes

* Rm import

* Rm debug assert

* cc

* Visitor/migrate/simplify fixes to make the seth refactor pass

* Fix concolic?

* Fix concolic?

* CC

* bytesM fix

* Fix address and caller concretization on symb tx

* Fix/refactor symbolic address/caller concretization

* Fix caller concretization

* Fix expression visiting

* Fix account policy refactor

* Accept numbers in function names abitypes

* Simplify installation instructions to recommend install manticore only for the current user

* Run some tests in parallel (#970)

This PR splits the current test runner into three environments: 

1. Linux examples
2. Ethereum tests
3. Remaining tests

to faster complete each testing run. Ethereum tests include a number of integration tests that execute scripts to completion, which takes a while. We run them concurrently with other tests to save on execution time. The split is done by naming Ethereum tests differently (`eth_*.py` vs `test_*.py`) and updating what pattern unittest's `discover` uses.

This change also updates the installation script and chooses to forego installing Keystone for EVM tests as it takes a while, and it adds a `setup.cfg` config file so that Nose finds the eth tests as well by default.

* Be less verbose when testing

* Fix slicing wrongly reference to proxyArray. Fix #912

* Only export human/external tx in the testcase (#972)

* Make ManticoreEVM.make_symbolic_value size adjustable (#974)

* Make size adjustable

* Default to 256

* Dev evm yolo fix gas (#975)

* Fix gas stipend on CALL and check dao

* Add order dependence 1

* Going linter. Report/Detect that thing when code does not check returned value

* cleaner example of fail

* Update retval_crazy.sol

* new solc for travis

* CC

* Remove duplicated ReentrancyDetector

* POrt to py3

* POrt to py3

* P0rt to py3

* CC

* Be mega forgiving on global expression usage - EVM

* Tests doc

* Refactor new_bitvector api

* function id to binary

* Fix neW_bool

* CC

* rename avoid_collisions collision

* rename avoid_collisions collision

* migrate on state.constraint too..

* Migration bugfixes

* CC bugfixes

* invalid assert removed

* move rep code to method

* unittets fixes and CC

* CC

* Refactor result_ref out in favor of change_last_result()

* CC

* reviewing the codes

* CC

* Change variable names

* typo

* Basic refactors and output enhancements

* Some minid docstrings and a unittest

* Some mini docstrings and a unittest

* Add migration integration testion

* Keep fuzz-refactoring it

* CC

* Bugfixfixfixfix

* CC

* re refactor mig algorithm

* better cleaner stronger. (reviewing)

* CC

* Small refactor and Fix strange strcmp test.

* CC

* funtion selector abinary

* bugfix.. waiting for migreation PR

* convenient tx abi parsing func

* convenient tx abi parsing func

* convenient tx abi parsing func

* convenient tx abi parsing func

* re re refactor for readability

* CC

* rev

* CC

* forgoten var

* CC

* CC

* review

* typo

* CC

* review

* Adding single example to sha3 trick when there are not know examples

* CC

* review

* CC

* Forgotten rollback

* CC

* Detect the odd delegatecall instruction (#1108)

* DAO detector + bugfixes

* The actual benchmark tests

* The actual benchmark tests

* CC

* Experiment reporting the finding at a JUMPI

* Fix taint. Detect returned overflowded data

* DAO -> Reentrancy

* DAO -> reentrancy, C -> Benchmark

* DAO -> reentrancy, C -> Benchmark

* Allow function names to have numbers

* Fix contract names in benchmark

* Fix contract names in benchmark

* Move default plugin registration

* Better regexp

* Fix minimal_bytecode example

* Fix Array Slice and test

* add tests

* correct other bug

* implement bytesM

* BROKEN partial progress

* need bytearray here

* rm cmt

* add basic tests for bytesM and bytes symbolic

* correct bytes symbolic test

* Refactor, clean bytesM handling

* Add initial symbolic 'bytes' handling

* refactor tests

* Unify symbolic/concrete bytes handling in bytesM/bytes

* Rm import

* Rm debug assert

* cc

* Visitor/migrate/simplify fixes to make the seth refactor pass

* Fix concolic?

* Fix concolic?

* CC

* bytesM fix

* Fix address and caller concretization on symb tx

* Fix/refactor symbolic address/caller concretization

* Fix caller concretization

* Fix expression visiting

* Fix account policy refactor

* Accept numbers in function names abitypes

* Simplify installation instructions to recommend install manticore only for the current user

* Run some tests in parallel (#970)

This PR splits the current test runner into three environments: 

1. Linux examples
2. Ethereum tests
3. Remaining tests

to faster complete each testing run. Ethereum tests include a number of integration tests that execute scripts to completion, which takes a while. We run them concurrently with other tests to save on execution time. The split is done by naming Ethereum tests differently (`eth_*.py` vs `test_*.py`) and updating what pattern unittest's `discover` uses.

This change also updates the installation script and chooses to forego installing Keystone for EVM tests as it takes a while, and it adds a `setup.cfg` config file so that Nose finds the eth tests as well by default.

* Be less verbose when testing

* Fix slicing wrongly reference to proxyArray. Fix #912

* Only export human/external tx in the testcase (#972)

* Make ManticoreEVM.make_symbolic_value size adjustable (#974)

* Make size adjustable

* Default to 256

* Dev evm yolo fix gas (#975)

* Fix gas stipend on CALL and check dao

* Add order dependence 1

* Going linter. Report/Detect that thing when code does not check returned value

* cleaner example of fail

* Update retval_crazy.sol

* new solc for travis

* CC

* Remove duplicated ReentrancyDetector

* POrt to py3

* POrt to py3

* P0rt to py3

* CC

* Be mega forgiving on global expression usage - EVM

* Tests doc

* Refactor new_bitvector api

* function id to binary

* Fix neW_bool

* CC

* rename avoid_collisions collision

* rename avoid_collisions collision

* migrate on state.constraint too..

* Migration bugfixes

* CC bugfixes

* invalid assert removed

* move rep code to method

* unittets fixes and CC

* CC

* Refactor result_ref out in favor of change_last_result()

* CC

* reviewing the codes

* CC

* Change variable names

* typo

* Basic refactors and output enhancements

* Some minid docstrings and a unittest

* Some mini docstrings and a unittest

* Add migration integration testion

* Keep fuzz-refactoring it

* CC

* Bugfixfixfixfix

* CC

* re refactor mig algorithm

* better cleaner stronger. (reviewing)

* CC

* Small refactor and Fix strange strcmp test.

* CC

* funtion selector abinary

* bugfix.. waiting for migreation PR

* convenient tx abi parsing func

* convenient tx abi parsing func

* convenient tx abi parsing func

* convenient tx abi parsing func

* re re refactor for readability

* CC

* rev

* CC

* forgoten var

* CC

* CC

* Delete duplicated detector

* WIP delegatecall. Lot of fixes. Recursion fix.

* review

* typo

* CC

* Sha3 random concre example when none. Concretize SIZE/OFFSET more. Initial calldata size management

* remove debug print

* Add check in constraints.add

* review

* Adding single example to sha3 trick when there are not know examples

* CC

* review

* CC

* about to merge sha3

* cleanups

* make gas budget configurable by user

* cleanups

* cleanups

* CC:

* CC

* Fix typo in tests

* Fix import typo

* pump some gas

* typo in skipping slow/big test

* skipping more test to make travis happy

* skipping more test to make travis happy

* debugging travis like a caveman

* dbg

* dbg

* dbg

* undbg

* undbg

* undbg

* undbg

* undbg and fixed

* undbg and fixed

* CC

* Updates to README.md relating to Python 3 migration and sudo within virtualenv setup (#1109)

* updated README.md to use python3 commands

* updated README.md to add sudo to system pip3 install commands

Line 186 uses a path to the specific pip3 binary (as per https://stackoverflow.com/questions/41429988/inside-virtual-env-sudo-pip-links-to-the-global-python-pip ).

* Manticore 0.2.1 (#1106)

* Bump version num

* changelog skeleton

* Switch to agpl

* readme license update

* update

* gas

* Add dc

* Date update

* Add last minute contributions

* Release 0.2.1c (#1111)

* Fix the versioning hell (#1112)

* Fix version number / release (#1113)

* Manticore 0.2.1-berlin (#1114)

* Manticore 0.2.1-b (#1115)

* manticore 0.2.1.1 (#1116)

* start scan_mem refactor

* Fix DecodeException message

* Only import mapped memory

* get a single value, instead of all, when decoding

* clean up instruction decoding

* simplify scan_mem

* Changed instances of Concretice to Concretize (#1118)

* Fix typo

* rename a field

* Attempt decoding with an arraystore simplifier

* python3 update to linux example makefile (#1122)

Ubuntu 18.04 doesn't alias python to python3

* Update decoding logic

* Simplify [skip] importing read-only maps

* Fix name serialization with anonmaps
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants