Ejemplo n.º 1
0
 def increment(self):
     self.count += 1
     # reset variable list if we're incrementing our count
     self.variable = BitVec('{1}{0}'.format(self.varName, self.count),
                            ctx=self.ctx,
                            size=self.size,
                            state=self.state)
Ejemplo n.º 2
0
    def __init__(self,
                 varName,
                 ctx,
                 count=None,
                 variable=None,
                 state=None,
                 increment=False):
        assert type(varName) is str
        assert type(ctx) is int
        assert type(count) in [int, type(None)]

        self.size = 16
        self.count = 0 if count is None else count
        self.varName = varName
        self.ctx = ctx
        self.variable = BitVec(
            '{1}{0}'.format(self.varName, self.count),
            ctx=self.ctx,
            size=self.size) if variable is None else variable

        if state is not None:
            self.setState(state)

        if increment:
            self.increment()
Ejemplo n.º 3
0
def test_pyObjectManager_List_setitem():
    b = ast_parse.parse(test1).body
    p = Path(b, source=test1)
    pg = PathGroup(p)

    pg.explore()
    assert len(pg.completed) == 1

    l = pg.completed[0].state.getVar('l')

    s = pg.completed[0].state

    # Base check
    assert l[1].count == 0
    assert type(l[1]) == Real

    # Assign an Int
    l[1] = Int(varName='x', ctx=0, state=s)
    assert l[1].count == 1
    assert type(l[1]) == Int

    # Assign back to Real
    l[1] = Real(varName='x', ctx=0, state=s)
    assert l[1].count == 2
    assert type(l[1]) == Real

    # Assign to BitVec
    l[1] = BitVec(varName='x', ctx=0, size=32, state=s)
    assert l[1].count == 3
    assert type(l[1]) == BitVec

    # Assign List
    l[1] = List(varName='x', ctx=0, state=s)
    #assert l[1].count == 4
    assert type(l[1]) == List
Ejemplo n.º 4
0
    def __setitem__(self, key, value):
        """
        Sets value at index key. Checks for variable type, updates counter according, similar to getVar call
        """
        # Attempt to return variable
        assert type(key) is int
        assert type(value) in [Int, Real, BitVec, List, String]

        # Get that index's current count
        count = self.variables[key].count + 1

        if type(value) is Int:
            logger.debug("__setitem__: setting Int")
            self.variables[key] = Int('{2}{0}[{1}]'.format(
                self.varName, key, self.count),
                                      ctx=self.ctx,
                                      count=count,
                                      state=self.state)
            self.variables[key].setTo(value)

        elif type(value) is Real:
            logger.debug("__setitem__: setting Real")
            self.variables[key] = Real('{2}{0}[{1}]'.format(
                self.varName, key, self.count),
                                       ctx=self.ctx,
                                       count=count,
                                       state=self.state)
            self.variables[key].setTo(value)

        elif type(value) is BitVec:
            logger.debug("__setitem__: setting BitVec")
            self.variables[key] = BitVec('{2}{0}[{1}]'.format(
                self.varName, key, self.count),
                                         ctx=self.ctx,
                                         count=count,
                                         size=value.size,
                                         state=self.state)
            self.variables[key].setTo(value)

        elif type(value) in [List, String]:
            logger.debug("__setitem__: setting {0}".format(type(value)))
            self.variables[key] = value
            #value.count = count

        else:
            err = "__setitem__: Don't know how to set object '{0}'".format(
                value)
            logger.error(err)
            raise Exception(err)
Ejemplo n.º 5
0
    def append(self, var, kwargs=None):
        """
        Input:
            var = pyObjectManager oject to append (i.e.: Int/Real/etc)
            (optional) kwargs = optional keyword args needed to instantiate type
        Action:
            Resolves object, creates variable if needed
        Returns:
            Nothing
        """
        # Variable names in list are "<verson><varName>[<index>]". This is in addition to base naming conventions

        if type(var) is Int or var is Int:
            logger.debug("append: adding Int")
            self.variables.append(
                Int('{2}{0}[{1}]'.format(self.varName, len(self.variables),
                                         self.count),
                    ctx=self.ctx,
                    state=self.state,
                    **kwargs if kwargs is not None else {}))
            # We're being given an object. Let's make sure we link it to Z3 appropriately
            if type(var) is Int:
                self.variables[-1].setTo(var)

        elif type(var) is Real or var is Real:
            logger.debug("append: adding Real")
            self.variables.append(
                Real('{2}{0}[{1}]'.format(self.varName, len(self.variables),
                                          self.count),
                     ctx=self.ctx,
                     state=self.state))
            if type(var) is Real:
                self.variables[-1].setTo(var)

        elif type(var) is BitVec or var is BitVec:
            logger.debug("append: adding BitVec")
            kwargs = {'size': var.size} if kwargs is None else kwargs
            self.variables.append(
                BitVec('{2}{0}[{1}]'.format(self.varName, len(self.variables),
                                            self.count),
                       ctx=self.ctx,
                       state=self.state,
                       **kwargs if kwargs is not None else {}))
            if type(var) is BitVec:
                self.variables[-1].setTo(var)

        elif type(var) is Char or var is Char:
            logger.debug("append: adding Char")
            self.variables.append(
                Char('{2}{0}[{1}]'.format(self.varName, len(self.variables),
                                          self.count),
                     ctx=self.ctx,
                     state=self.state))
            if type(var) is Char:
                self.variables[-1].setTo(var)

        elif type(var) in [List, String]:
            logger.debug("append: adding {0}".format(type(var)))
            self.variables.append(var)

        else:
            err = "append: Don't know how to append/resolve object '{0}'".format(
                type(var))
            logger.error(err)
            raise Exception(err)
Ejemplo n.º 6
0
class Char:
    """
    Define a Char (Character)
    """
    def __init__(self,
                 varName,
                 ctx,
                 count=None,
                 variable=None,
                 state=None,
                 increment=False):
        assert type(varName) is str
        assert type(ctx) is int
        assert type(count) in [int, type(None)]

        self.size = 16
        self.count = 0 if count is None else count
        self.varName = varName
        self.ctx = ctx
        self.variable = BitVec(
            '{1}{0}'.format(self.varName, self.count),
            ctx=self.ctx,
            size=self.size) if variable is None else variable

        if state is not None:
            self.setState(state)

        if increment:
            self.increment()

    def __deepcopy__(self, _):
        return self.copy()

    def __copy__(self):
        return self.copy()

    def copy(self):
        return Char(
            varName=self.varName,
            ctx=self.ctx,
            count=self.count,
            variable=self.variable.copy(),
            state=self.state if hasattr(self, "state") else None,
        )

    def __str__(self):
        return chr(self.state.any_int(self))

    def setTo(self, var):
        """
        Sets this Char to the variable. Raises exception on failure.
        """
        if type(var) not in [str, String, Char]:
            err = "setTo: Invalid argument type {0}".format(type(var))
            logger.error(err)
            raise Exception(err)

        if (type(var) is String and var.length() != 1) or (type(var) is str
                                                           and len(var) != 1):
            err = "setTo: Cannot set Char element to more than 1 length"
            logger.error(err)
            raise Exception(err)

        # Go ahead and add the constraints
        if type(var) is str:
            self.variable.setTo(ord(var))

        else:
            if type(var) is String:
                var = var[0]

            self.variable.setTo(var.variable)

    def setState(self, state):
        """
        This is a bit strange, but State won't copy correctly due to Z3, so I need to bypass this a bit by setting State each time I copy
        """
        assert type(state) == pyState.State

        self.state = state
        self.variable.setState(state)

    def increment(self):
        self.count += 1
        # reset variable list if we're incrementing our count
        self.variable = BitVec('{1}{0}'.format(self.varName, self.count),
                               ctx=self.ctx,
                               size=self.size,
                               state=self.state)

    def _isSame(self, **args):
        """
        Checks if variables for this object are the same as those entered.
        Assumes checks of type will be done prior to calling.
        """
        return True

    def getZ3Object(self):
        return self.variable.getZ3Object()

    def isStatic(self):
        """
        Returns True if this object is a static variety (i.e.: "a").
        Also returns True if object has only one possibility
        """
        return self.variable.isStatic()
        #if len(self.state.any_n_int(self,2)) == 1:
        #    return True

        #return False

    def getValue(self):
        """
        Resolves the value of this Char. Assumes that isStatic method is called
        before this is called to ensure the value is not symbolic
        """
        #return chr(self.state.any_int(self))
        return chr(self.variable.getValue())

    def mustBe(self, var):
        """
        Return True if this Char must be equivalent to input (str/Char). False otherwise.
        """
        assert type(var) in [str, Char]

        # If we can't be, then mustBe is also False
        if not self.canBe(var):
            return False

        # Utilize the BitVec's methods here
        if type(var) is str:
            return self.variable.mustBe(ord(var))

        if type(var) is Char:
            return self.variable.mustBe(var.variable)

        # If we can be, determine if this is the only option
        #if len(self.state.any_n_int(self,2)) == 1 and len(self.state.any_n_int(var,2)) == 1:
        #    return True

        # Looks like we're only one option
        return False

    def canBe(self, var):
        """
        Test if this Char can be equal to the given variable
        Returns True or False
        """

        assert type(var) in [str, Char]

        if type(var) is str and len(var) != 1:
            return False

        if type(var) is str:
            return self.variable.canBe(ord(var))
            #s = self.state.copy()
            #s.addConstraint(self.getZ3Object() == ord(var))
            #if s.isSat():
            #    return True
            #return False

        elif type(var) is Char:
            return self.variable.canBe(var.variable)
Ejemplo n.º 7
0
def _handleNum(state, element, value, op):
    """
    Handle the case where we're AugAssigning numbers
    """

    # Find the parent object
    oldTargets = state.resolveObject(element.target)

    # Normalize
    oldTargets = [oldTargets] if type(oldTargets) is not list else oldTargets

    # Resolve calls if we need to
    retObjs = [x for x in oldTargets if type(x) is pyState.ReturnObject]
    if len(retObjs) > 0:
        return retObjs

    ret = []

    # Loop through resolved objects
    for oldTarget in oldTargets:
        parent = state.objectManager.getParent(oldTarget)
        index = parent.index(oldTarget)

        # Basic sanity checks complete. For augment assigns we will always need to update the vars.
        # Grab the old var and create a new now
        #oldTargetVar = oldTarget.getZ3Object()

        # Match up the right hand side
        oldTargetVar, valueVar = z3Helpers.z3_matchLeftAndRight(
            oldTarget, value, op)

        if hasRealComponent(valueVar) or hasRealComponent(oldTargetVar):
            parent[index] = Real(oldTarget.varName, ctx=state.ctx, state=state)
            #newTargetVar = parent[index].getZ3Object(increment=True)

        elif type(valueVar) in [z3.BitVecRef, z3.BitVecNumRef]:
            parent[index] = BitVec(oldTarget.varName,
                                   ctx=state.ctx,
                                   size=valueVar.size(),
                                   state=state)
            #newTargetVar = parent[index].getZ3Object(increment=True)

        else:
            parent[index] = Int(oldTarget.varName, ctx=state.ctx, state=state)
            #newTargetVar = parent[index].getZ3Object(increment=True)

        newTargetObj = parent[index]
        newTargetObj.increment()
        newTargetVar = newTargetObj.getZ3Object()

        # Figure out what the op is and add constraint
        if type(op) == ast.Add:
            if type(newTargetVar) in [z3.BitVecRef, z3.BitVecNumRef]:
                # Check for over and underflows
                state.solver.add(
                    pyState.z3Helpers.bvadd_safe(oldTargetVar, valueVar))

            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() + value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar + valueVar)

        elif type(op) == ast.Sub:
            if type(newTargetVar) in [z3.BitVecRef, z3.BitVecNumRef]:
                # Check for over and underflows
                state.solver.add(
                    pyState.z3Helpers.bvsub_safe(oldTargetVar, valueVar))

            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() - value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar - valueVar)

        elif type(op) == ast.Mult:
            if type(newTargetVar) in [z3.BitVecRef, z3.BitVecNumRef]:
                # Check for over and underflows
                state.solver.add(
                    pyState.z3Helpers.bvmul_safe(oldTargetVar, valueVar))

            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() * value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar * valueVar)

        elif type(op) == ast.Div:
            if type(newTargetVar) in [z3.BitVecRef, z3.BitVecNumRef]:
                # Check for over and underflows
                state.solver.add(
                    pyState.z3Helpers.bvdiv_safe(oldTargetVar, valueVar))

            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() / value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar / valueVar)

        elif type(op) == ast.Mod:
            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() % value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar % valueVar)

        elif type(op) == ast.BitXor:
            logger.debug("{0} = {1} ^ {2}".format(newTargetVar, oldTargetVar,
                                                  valueVar))
            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() ^ value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar ^ valueVar)

        elif type(op) == ast.BitOr:
            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() | value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar | valueVar)

        elif type(op) == ast.BitAnd:
            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() & value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar & valueVar)

        elif type(op) == ast.LShift:
            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() << value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar << valueVar)

        elif type(op) == ast.RShift:
            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue() >> value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar >> valueVar)

        # TODO: This will fail with BitVec objects...
        elif type(op) == ast.Pow:
            # Keep clutter out of z3
            if oldTarget.isStatic() and value.isStatic():
                newTargetObj.setTo(oldTarget.getValue()**value.getValue())
            else:
                state.addConstraint(newTargetVar == oldTargetVar**valueVar)

        else:
            err = "Don't know how to handle op type {0} at line {1} col {2}".format(
                type(op), op.lineno, op.col_offset)
            logger.error(err)
            raise Exception(err)

        ret.append(state)

    # Pop the instruction off
    state.path.pop(0)

    # Return the state
    return ret
Ejemplo n.º 8
0
Archivo: Ctx.py Proyecto: njues/pySym
    def __setitem__(self,key,value):
        """
        Sets value at index key. Checks for variable type, updates counter according, similar to getVar call
        """
        # Attempt to return variable
        assert type(value) in [Int, Real, BitVec, List, String, Char]
        
        # Things get weird if our variable names don't match up...
        #assert key == value.varName

        # Get that index's current count
        if key in self.variables:
            count = self.variables[key].count + 1
        else:
            count = 0

        # If the variable comes in with a higher count, that's the one to use
        #count = max(count,

        #print("Setting",value.getZ3Object())
        #self.variables[key] = value
        #value.count = count
        #print("Set",self.variables[key].getZ3Object())
        #return

        if type(value) is Int:
            logger.debug("__setitem__: setting Int")
            self.variables[key] = Int('{0}'.format(key),ctx=self.ctx,count=count,state=self.state)
            # Don't add a constraint if it's the same thing!
            if self.variables[key].getZ3Object().get_id() != value.getZ3Object().get_id():
                #self.state.addConstraint(self.variables[key].getZ3Object() == value.getZ3Object())
                self.variables[key].setTo(value)

        elif type(value) is Real:
            logger.debug("__setitem__: setting Real")
            self.variables[key] = Real('{0}'.format(key),ctx=self.ctx,count=count,state=self.state)
            # Don't add a constraint if it's the same thing!
            if self.variables[key].getZ3Object().get_id() != value.getZ3Object().get_id():
                #self.state.addConstraint(self.variables[key].getZ3Object() == value.getZ3Object())
                self.variables[key].setTo(value)

        elif type(value) is BitVec:
            logger.debug("__setitem__: setting BitVec")
            self.variables[key] = BitVec('{0}'.format(key),ctx=self.ctx,count=count,size=value.size,state=self.state)
            # Don't add a constraint if it's the same thing!
            if self.variables[key].getZ3Object().get_id() != value.getZ3Object().get_id():
                #self.state.addConstraint(self.variables[key].getZ3Object() == value.getZ3Object())
                self.variables[key].setTo(value)

        elif type(value) in [List, String]:
            logger.debug("__setitem__: setting {0}".format(type(value)))
            self.variables[key] = value.copy()
            self.variables[key].setState(self.state)
            #value.count = count
        
        elif type(value) is Char:
            logger.debug("__setitem__: setting Char")
            self.variables[key] = Char('{0}'.format(key),ctx=self.ctx,count=count,state=self.state)
            # Don't add a constraint if it's the same thing!
            if self.variables[key].getZ3Object().get_id() != value.getZ3Object().get_id():
                #self.state.addConstraint(self.variables[key].getZ3Object() == value.getZ3Object())
                self.variables[key].setTo(value)

        else:
            err = "__setitem__: Don't know how to set object '{0}'".format(value)
            logger.error(err)
            raise Exception(err)