Ejemplo n.º 1
0
    def setUp(self):
        num_class = Typez(kind='classdef')
        num_class.scope['__add__'] = Typez(kind='funcdef')

        pr_num = Typez(kind='pr_num', __class__=num_class)
        pr_str = Typez(kind='pr_str')
        self.scope = Scope(is_root=True)
        self.scope.update({'xxx': pr_str})

        scope1 = Scope(parent=self.scope)
        scope1.update({'a': pr_num, 'b': pr_str})
        self.type1 = Typez(kind='obj', scope=scope1)

        scope2 = Scope(parent=self.scope)
        scope2.update({'c': pr_num, 'd': pr_str})
        self.type2 = Typez(kind='obj', scope=scope2)
        self.type2 = scope2

        scope12 = Scope(parent=self.scope)
        scope12.update({'a': self.type1, 'b': self.type2})
        self.type12 = Typez(kind='obj', scope=scope12)

        self.scope.update({
            'type1': self.type1,
            'type2': self.type2,
            'type12': self.type12
        })
Ejemplo n.º 2
0
    def exec_Call(self, node, scope):
        '''
        This method is resposible for exectuing calls. For instance : fun(),a.b.c.fun() or A() as a constructor. 
        '''
        #first let's find out which function should be called. This should be easy when doing func()
        #call, but it can be tricky when using constructs such as 'a.b.c.func()'

        #covers func() case
        if isinstance(node.func, ast.Name):
            logger.debug("? exec_Call "+node.func.id +" "+str(node))
            call_type = scope.resolve(node.func.id,'cascade')
            if call_type is None:
                call_type = any_type
        #covers a.b.c.func() case
        elif isinstance(node.func, ast.Attribute):
            logger.debug("? exec_Call "+node.func.attr +" "+str(node))
            call_type = self.eval_code(node.func, scope)
            if call_type == any_type:
                return any_type

        else:
            raise Exception('should not get here')

        #now we know what to invoke. Now we must distinguish whether it is func/method call or 'new'
        #statement.
        #Call-ing function or method
        if call_type.kind == 'funcdef':
            args = [self.eval_code(arg, scope) for arg in node.args]
            keywords = {}
            for keyword in node.keywords:
                keywords[keyword.arg]=self.eval_code(keyword.value, scope)
            counter = 0
            for arg_eval in args:
                if arg_eval is None and hasattr(node.args[counter], 'id'):
                    self.warn(node, "NameError: Name '"+ node.args[counter].id + "' is not defined", node.args[counter].id)
                counter = counter + 1
            if call_type.is_method:
                args = [call_type.self_obj]+args
            return self._exec_fun(call_type, args, keywords, call_type.scope, node=node)

        #Call-ing as a 'new' statement
        if call_type.kind == 'classdef':
            args = [self.eval_code(arg,scope) for arg in node.args]
            keywords = {}
            for keyword in node.keywords:
                keywords[keyword.arg]=self.eval_code(keyword.value, scope)
            new = Typez(kind = 'obj', parent_scope = scope)
            args = [new]+args
            new.scope['__class__'] = call_type
            constructor = call_type.resolve('__init__', 'class')
            if constructor:
                new.obj = self._exec_fun(constructor, args, keywords, new.scope, node=node)
            return new
        if hasattr(node.func, 'id'):
            self.warn(node, message = 'nonexistent_function', symbol = node.func.id)
            return any_type
Ejemplo n.º 3
0
class TestResolve(InferTestCase):  #{{{
    def setUp(self):
        num_class = Typez(kind='classdef')
        num_class.scope['__add__'] = Typez(kind='funcdef')

        pr_num = Typez(kind='pr_num', __class__=num_class)
        pr_str = Typez(kind='pr_str')
        self.scope = Scope(is_root=True)
        self.scope.update({'xxx': pr_str})

        scope1 = Scope(parent=self.scope)
        scope1.update({'a': pr_num, 'b': pr_str})
        self.type1 = Typez(kind='obj', scope=scope1)

        scope2 = Scope(parent=self.scope)
        scope2.update({'c': pr_num, 'd': pr_str})
        self.type2 = Typez(kind='obj', scope=scope2)
        self.type2 = scope2

        scope12 = Scope(parent=self.scope)
        scope12.update({'a': self.type1, 'b': self.type2})
        self.type12 = Typez(kind='obj', scope=scope12)

        self.scope.update({
            'type1': self.type1,
            'type2': self.type2,
            'type12': self.type12
        })

    def test_resolve_type1_in_scope(self):
        res = self.scope.resolve('type1', 'straight')
        self.assertEqual(res, self.type1)

    def test_resolve_in_type(self):
        res = self.type1.resolve('a', 'straight')
        self.assertEqual(res.kind, 'pr_num')
        self.assertEqual(self.scope.resolve('c'), None)

    def test_resolve_cascade(self):
        self.assertRaises(Exception, self.type1.resolve, 'xxx', 'cascade')
        res1 = self.type1.scope.resolve('xxx', 'cascade')
        res2 = self.scope.resolve('xxx', 'straight')
        self.assertEqual(res1, res2)

    def test_resolve_class(self):

        num = self.type1.resolve('a', 'straight')
        self.assertRaises(Exception, num.resolve, '__add__', 'cascade')
        add = num.resolve('__add__', 'straight')
        self.assertEqual(add, None)
        add = num.resolve('__add__', 'class')
        self.assertIsInstance(add, Typez)
        self.assertEqual(add.kind, 'funcdef')
Ejemplo n.º 4
0
class TestResolve(InferTestCase): #{{{

    def setUp(self):
        num_class = Typez(kind = 'classdef')
        num_class.scope['__add__'] = Typez(kind = 'funcdef')

        pr_num = Typez(kind = 'pr_num', __class__ = num_class )
        pr_str = Typez(kind = 'pr_str')
        self.scope = Scope(is_root = True)
        self.scope.update({'xxx':pr_str})

        scope1 = Scope(parent = self.scope)
        scope1.update({'a': pr_num, 'b': pr_str})
        self.type1 = Typez(kind = 'obj', scope = scope1)

        scope2 = Scope(parent = self.scope)
        scope2.update({'c': pr_num, 'd': pr_str})
        self.type2 = Typez(kind = 'obj', scope = scope2)
        self.type2 = scope2

        scope12 = Scope(parent = self.scope)
        scope12.update({'a':self.type1, 'b': self.type2})
        self.type12 = Typez(kind = 'obj', scope = scope12)

        self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12})

    def test_resolve_type1_in_scope(self):
        res = self.scope.resolve('type1', 'straight')
        self.assertEqual(res, self.type1)

    def test_resolve_in_type(self):
        res = self.type1.resolve('a', 'straight')
        self.assertEqual(res.kind,'pr_num')
        self.assertEqual(self.scope.resolve('c'), None)


    def test_resolve_cascade(self):
        self.assertRaises(Exception, self.type1.resolve, 'xxx','cascade')
        res1 = self.type1.scope.resolve('xxx','cascade')
        res2 = self.scope.resolve('xxx','straight')
        self.assertEqual(res1,res2)

    def test_resolve_class(self):

        num = self.type1.resolve('a', 'straight')
        self.assertRaises(Exception, num.resolve, '__add__', 'cascade')
        add = num.resolve('__add__', 'straight')
        self.assertEqual(add, None)
        add = num.resolve('__add__', 'class')
        self.assertIsInstance(add, Typez)
        self.assertEqual(add.kind, 'funcdef')
Ejemplo n.º 5
0
 def _exec_Tuple_Assign(self,lhs,rhs,node,scope,evalR):
     '''
     This method covers cases like a,b = x
     '''
     if evalR:
         rhs_type = self.eval_code(rhs,scope)
     else:
         rhs_type = rhs
     fun_iter = rhs_type.resolve('__iter__','class')
     if fun_iter:
         isTuple = rhs_type.resolve_class(self.extern_scope['inf_tuple'])
         if isTuple:
             stop = False
             for index,e in enumerate(lhs.elts):
                 if stop:
                     self._exec_Assign(e,any_type,node,scope,evalR=False)
                 else:
                     key = Typez(kind='const', value = index, __class__ = self.extern_scope['num'])
                     getItem = rhs_type.resolve('__getitem__','class')
                     item = self._exec_fun(getItem, [rhs_type,key], {}, scope, node=node)
                     if not item.resolve_class(self.extern_scope['PlaceHolder']):
                         self._exec_Assign(e,item,node,scope,evalR=False)
                     else:
                         stop = True
                         self._exec_Assign(e,any_type,node,scope,evalR=False)
                         self.warn(node, 'Need more than %d values to unpack'%(index), 'tuple')
             if index+1<5:
                 key = Typez(kind='const', value = index+1, __class__ = self.extern_scope['num'])
                 getItem = rhs_type.resolve('__getitem__','class')
                 item = self._exec_fun(getItem, [rhs_type,key], {}, scope, node=node)
                 if not item.resolve_class(self.extern_scope['PlaceHolder']):
                     #nerozbalili sa vsetky hodnoty co boli v tuple, malo var na lavej strane
                     self.warn(node, 'too many values to unpack (expected %d)'%(len(lhs.elts)),'tuple')
         else:
             args = [rhs_type]
             iterator = self._exec_fun(fun_iter, args, {}, scope, node=node)
             fun_next = iterator.resolve('__next__','class')
             if fun_next:
                 value = self._exec_fun(fun_next, [iterator], {}, scope, node=node)
                 for e in lhs.elts:
                     self._exec_Assign(e,value,node,scope,evalR=False)
             else:
                 self.warn(node=node,mes="does not support __next__ method",symbol="Iterator")
     else:
         if hasattr(rhs, 'id'):
             self.warn(node,"object is not iterable", rhs.id)
         else:
             symbol = hrs_type.scope['__class__'].node.name
             self.warn(node,"object is not iterable", symbol)
Ejemplo n.º 6
0
class TestResolve(unittest.TestCase): #{{{

    def setUp(self):
        pr_num = Typez(kind = 'obj', node = ast.Num(), klass_name = 'num')
        pr_str = Typez(kind = 'obj', node = ast.Str(), klass_name = 'str')
        self.scope = Scope(is_root = True)
        self.scope.update({'xxx':pr_str})

        scope1 = Scope(parent = self.scope)
        scope1.update({'a': pr_num, 'b': pr_str})
        self.type1 = Typez(kind = 'obj', scope = scope1)

        scope2 = Scope(parent = self.scope)
        scope2.update({'c': pr_num, 'd': pr_str})
        self.type2 = Typez(kind = 'obj', scope = scope2)
        self.type2 = scope2

        scope12 = Scope(parent = self.scope)
        scope12.update({'a':self.type1, 'b': self.type2})
        self.type12 = Typez(kind = 'obj', scope = scope12)

        self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12})

    def test_resolve_type1_in_scope(self):
        res = self.scope.resolve('type1', 'straight')
        self.assertEqual(res, self.type1)

    def test_resolve_in_type(self):
        res = self.type1.resolve('a', 'straight')
        self.assertEqual(res.kind,'obj')
        self.assertIsInstance(res.node, ast.Num)
        self.assertEqual(self.scope.resolve('c'), None)


    def test_resolve_cascade(self):
        self.assertRaises(Exception, self.type1.resolve, 'xxx','cascade')
        res1 = self.type1.scope.resolve('xxx','cascade')
        res2 = self.scope.resolve('xxx','straight')
        self.assertEqual(res1,res2)

    def test_resolve_class(self):
        num = self.type1.resolve('a', 'straight')
        self.assertRaises(Exception, num.resolve, '__add__', 'cascade')
        add = num.resolve('__add__', 'straight')
        self.assertEqual(add, None)
        add = num.resolve('__add__', 'class')
        self.assertIsInstance(add, Typez)
        self.assertEqual(add.kind, 'func')
        self.assertIsInstance(add.node, ast.FunctionDef)
Ejemplo n.º 7
0
 def exec_Set(self, node, scope):
     '''
     Set in our implementation only holds info about one object - representant.
     This can be handful for numerous reasons: adding something in neverending while cycle would cause
     overflow in symbolic execution if we stored full set. Another advantage is quickness of execution.
     '''
     new_set = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_set'])
     init = new_set.resolve('__init__','class')
     self._exec_fun(init, [new_set],{}, new_set.scope, node)
     add =  new_set.resolve('add', 'class')
     for item in node.elts:
         item_val = self.eval_code(item, scope)
         if item_val is not None:
             self._exec_fun(add, [new_set, item_val], {}, scope, node=node) 
     return new_set
Ejemplo n.º 8
0
 def exec_Slice(self,node,scope):
     '''
     This method proceeds all the slicing in our implementation.
     The mock object inf_slice is created.
     '''
     new_slice = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_slice'])
     init = new_slice.resolve('__init__','class')
     args=[new_slice]
     if node.upper is not None:
         args.append(self.eval_code(node.upper, scope))
     if node.lower is not None:
         args.append(self.eval_code(node.lower, scope))
     if node.step is not None:
         args.append(self.eval_code(node.step, scope))
     self._exec_fun(init, args,{}, new_slice.scope, node)
     return new_slice
Ejemplo n.º 9
0
 def exec_Name(self, node, scope):
     '''
     Method that proceeds all occurences of name. For instance : x=5 (x is a name)
     There are two cases: name is a constant (None, True, False) or name is a variable that
     has to be resolved.
     '''
     if node.id == 'None':
         return Typez(kind = 'const', node = node, value = 'None')
     if node.id == 'True':
         return Typez(kind = 'const', node = node, value = True, __class__ = self.extern_scope['bool'])
     if node.id == 'False':
         return Typez(kind = 'const', node = node, value = False, __class__ = self.extern_scope['bool'])
     res = scope.resolve(node.id, 'cascade')
     if res is None and isinstance(node.ctx,ast.Load):
         self.warn(node, "NameError: Name '"+ node.id + "' is not defined", node.id)
         return any_type
     return res
Ejemplo n.º 10
0
 def exec_FunctionDef(self, node, scope):
     '''
     This method executes the definition of function. In this case, just the name of function is stored. If the docstring is included inside of definition,
     it is stored in within the corresponding Typez under attribute docstring.
     '''
     scope[node.name] = Typez(kind='funcdef', node = node, scope = scope)
     if isinstance(node.body[0],ast.Expr) and isinstance(node.body[0].value,ast.Str):
         scope[node.name].docstring = node.body[0].value.s
Ejemplo n.º 11
0
 def exec_List(self, node, scope):
     '''
     List in our implementation only holds info about one object - representant.
     This can be handful for numerous reasons: apending something in neverending while cycle would cause
     overflow in symbolic execution if we stored full list. Another advantage is quickness of execution.
     '''
     new_list = Typez(kind = 'obj', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_list'])
     init = new_list.resolve('__init__','class')
     self._exec_fun(init, [new_list],{}, new_list.scope, node)      
     append = new_list.resolve('append', 'class')
     
     for item in node.elts: 
         if append:
             item_val = self.eval_code(item, scope)
             if item_val is None and hasattr(item, "id"):
             #    self.warn(node, "NameError: Name '"+ item.id + "' is not defined", item.id)
                 item_val = any_type
             self._exec_fun(append, [new_list, item_val], {}, scope, node=node) 
     return new_list
Ejemplo n.º 12
0
    def exec_Call(self, node, scope):
        #first let's find out which function should be called. This should be easy when doing func()
        #call, but it can be tricky when using constructs such as 'a.b.c.func()'

        #covers func() case
        if isinstance(node.func, ast.Name):
            logger.debug("? exec_Call "+node.func.id +" "+str(node))
            call_type = scope.resolve(node.func.id,'cascade')
            if call_type is None:
               call_type = any_type
        #covers a.b.c.func() case
        elif isinstance(node.func, ast.Attribute):
            logger.debug("? exec_Call "+node.func.attr +" "+str(node))
            call_type = self.eval_code(node.func, scope)
            if call_type.kind == 'any':
                return any_type

        else:
            raise Exception('should not get here')

        #now we know what to invoke. Now we must distinguish whether it is func/method call or 'new'
        #statement.

        #TODO: dorobit spustanie 'any' kind
        #Call-ing function or method
        if call_type.kind == 'func':
            args = [self.eval_code(arg, scope) for arg in node.args]
            if call_type.is_method:
                args = [call_type.self_obj]+args
            return self._exec_fun(call_type, args, call_type.scope, node=node)

        #Call-ing as a 'new' statement
        if call_type.kind == 'class':
            args = [self.eval_code(arg,scope) for arg in node.args]
            new = Typez(kind = 'obj', parent_scope = scope)
            args = [new]+args
            new.scope['__class__'] = call_type
            constructor = call_type.resolve('__init__', 'class')
            if constructor:
                new.obj = self._exec_fun(constructor, args, new.scope, node=node)
            return new
        self.warn(node, message = 'nonexistent_function', symbol = node.func.id)
Ejemplo n.º 13
0
 def exec_Dict(self, node, scope):
     '''
     Dictionary in our implementation only holds info only about two objects: key and value.
     Reasons are the same like in exec_List.
     '''
     new_dict = Typez(kind = 'obj', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_dict'])
     init = new_dict.resolve('__init__','class')
     self._exec_fun(init, [new_dict],{}, new_dict.scope, node)
     setItem = new_dict.resolve('__setitem__', 'class')
     #self.nondet=False
     for i,item in enumerate(node.values):
         item_val = self.eval_code(item, scope)
         if item_val is None and hasattr(item, "id"):
             #self.warn(node, "NameError: Name '"+ item.id + "' is not defined", item.id)
             item_val = any_type
         key_val = self.eval_code(node.keys[i],scope)
         if key_val is None and hasattr(node.keys[i], "id"):
             #self.warn(node, "NameError: Name '"+ node.keys[i].id + "' is not defined", node.keys[i].id)
             key_val = any_type
         args = [new_dict, key_val, item_val]
         self._exec_fun(setItem, args, {}, scope, node=node)    
     return new_dict
Ejemplo n.º 14
0
    def setUp(self):
        num_class = Typez(kind = 'classdef')
        num_class.scope['__add__'] = Typez(kind = 'funcdef')

        pr_num = Typez(kind = 'pr_num', __class__ = num_class )
        pr_str = Typez(kind = 'pr_str')
        self.scope = Scope(is_root = True)
        self.scope.update({'xxx':pr_str})

        scope1 = Scope(parent = self.scope)
        scope1.update({'a': pr_num, 'b': pr_str})
        self.type1 = Typez(kind = 'obj', scope = scope1)

        scope2 = Scope(parent = self.scope)
        scope2.update({'c': pr_num, 'd': pr_str})
        self.type2 = Typez(kind = 'obj', scope = scope2)
        self.type2 = scope2

        scope12 = Scope(parent = self.scope)
        scope12.update({'a':self.type1, 'b': self.type2})
        self.type12 = Typez(kind = 'obj', scope = scope12)

        self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12})
Ejemplo n.º 15
0
 def exec_Tuple(self, node, scope):
     '''
     Tuple in our implementation is of size 5. That should be enough for executing almost all operations between tuples (pairs,
     triples, adding them together).
     This can be handful for numerous reasons: adding something in neverending while cycle would cause
     overflow in symbolic execution if we stored full tuple. Another advantage is quickness of execution.
     '''
     new_tuple = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_tuple'])
     init = new_tuple.resolve('__init__','class')
     self._exec_fun(init, [new_tuple],{}, new_tuple.scope, node)
     set_item =  new_tuple.resolve('inf__setitem__', 'class')
     i=0
     for item in node.elts:
         item_val = self.eval_code(item, scope)
         if item_val is None:
             item_val = any_type
         else:
             #check whether item_val is a PlaceHolder by adding two tuples together
             if not item_val.resolve_class(self.extern_scope['PlaceHolder']):
                 index = Typez(kind='const', value = i, __class__ = self.extern_scope['num'])
                 self._exec_fun(set_item, [new_tuple, index, item_val], {}, scope, node=node) 
                 i+=1        
     return new_tuple
Ejemplo n.º 16
0
 def exec_ClassDef(self, node, scope):
     '''
     Method that executes the definition of class. Bases are stored in Typez object and furthermore
     'object' is added to bases.
     Every node inside node.body is recursively executed. 
     '''
     class_scope = Scope(parent = scope)
     scope[node.name] = Typez(kind='classdef', node = node, scope = class_scope)
     #docstrings
     if isinstance(node.body[0],ast.Expr) and isinstance(node.body[0].value,ast.Str):
         scope[node.name].docstring = node.body[0].value.s
     for _node in node.body:
         self.eval_code(_node, class_scope)
     bases = [self.eval_code(base, scope) for base in node.bases]
     obj = self.extern_scope['object']
     bases.append(obj)
     class_scope['__bases__'] = bases
Ejemplo n.º 17
0
    def setUp(self):
        pr_num = Typez(kind = 'obj', node = ast.Num(), klass_name = 'num')
        pr_str = Typez(kind = 'obj', node = ast.Str(), klass_name = 'str')
        self.scope = Scope(is_root = True)
        self.scope.update({'xxx':pr_str})

        scope1 = Scope(parent = self.scope)
        scope1.update({'a': pr_num, 'b': pr_str})
        self.type1 = Typez(kind = 'obj', scope = scope1)

        scope2 = Scope(parent = self.scope)
        scope2.update({'c': pr_num, 'd': pr_str})
        self.type2 = Typez(kind = 'obj', scope = scope2)
        self.type2 = scope2

        scope12 = Scope(parent = self.scope)
        scope12.update({'a':self.type1, 'b': self.type2})
        self.type12 = Typez(kind = 'obj', scope = scope12)

        self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12})
Ejemplo n.º 18
0
 def exec_List(self, node, scope):
     res = Typez(kind = 'obj', node = node, klass_name = 'inf_list')
     for item in node.elts:
         item_val = self.eval_code(item, scope)
         append = res.resolve('append', 'class')
         self._exec_fun(append, item_val, scope, node=node)
Ejemplo n.º 19
0
    def _exec_fun(self, fun_type, args, keywords, scope, create_scope = True, node = None):
        """
        executes function with given args in the given scope. When create_scope is True, it creates new scope for the function
        executing with parameter scope as its parent. Otherwise, it executes function in the given
        scope.
        
        """
        #if we dont know the fun_type, return any_type
        if fun_type.kind=='any':
            return any_type

        from random import randint
        
        if fun_type == self.extern_scope['inf_hasattr']:
            a=args[0]
            b=args[1]
            if b.value is not None:
                res = a.resolve(b.value)
                if res is None:
                    return Typez(kind='const', value = False, __class__ = self.extern_scope['bool'])
                else:
                    return Typez(kind='const', value = True, __class__ = self.extern_scope['bool'])
            self.nondet=True
            bit = randint(0,1)
            if bit:
                return Typez(kind='const', value = True, __class__ = self.extern_scope['bool'])
            else:
                return Typez(kind='const', value = False, __class__ = self.extern_scope['bool'])
            
        
        if fun_type == self.extern_scope['inf_random']:
            self.nondet=True
            bit = randint(0,1)
            if bit:
                return Typez(kind='const', value = 1, __class__ = self.extern_scope['num'])
            else:
                return Typez(kind='const', value = 0, __class__ = self.extern_scope['num'])
        
        if fun_type == self.extern_scope['inf_equal']:
            a=args[0]
            b=args[1]
            if a.value is not None and b.value is not None:
                left = a.value
                right = b.value
                if isinstance(a.value, bool):
                    if a.value:
                        left = 1
                    else:
                        left = 0      
                if isinstance(b.value, bool):
                    if b.value:
                        right = 1
                    else:
                        right = 0
                if left==right:
                    return Typez(kind='const', value = True, __class__ = self.extern_scope['bool'])
                else:
                    return Typez(kind='const', value = False, __class__ = self.extern_scope['bool'])
            else:
                self.nondet=True
                bit = randint(0,1)
                if bit:
                    return Typez(kind='const', value = True, __class__ = self.extern_scope['bool'])
                else:
                    return Typez(kind='const', value = False, __class__ = self.extern_scope['bool'])
        
        if fun_type == self.extern_scope['inf_is']:
            #we truly determine only if the statement is in form - smth is None
            if is_none(args[1]): 
                if is_none(args[0]):
                    return Typez(kind='const', value = True, __class__ = self.extern_scope['bool'])
                else:
                    return Typez(kind='const', value = False, __class__ = self.extern_scope['bool'])
            else:
                self.nondet=True
                bit = randint(0,1)
                if bit:
                    return Typez(kind='const', value = True, __class__ = self.extern_scope['bool'])
                else:
                    return Typez(kind='const', value = False, __class__ = self.extern_scope['bool'])
        if fun_type == self.extern_scope['isinstance']:
            if isinstance(args[0],Typez) and isinstance(args[1],Typez):
                instance = args[0]
                clazz = args[1]
                
                res = instance.resolve_class(clazz)
                if not res is None:
                    return Typez(kind='const', value = True, __class__ = self.extern_scope['bool'])
                else:
                    return Typez(kind='const', value = False, __class__ = self.extern_scope['bool'])
            else:
                self.warn(node, symbol = 'isinstance error', message = 'isinstance bad arguments')

        if fun_type == self.extern_scope['inf_setattr']:
            attr = args[1]
            if isinstance(attr, Typez) and isinstance(attr.value, str):
                attr = attr.value
            if isinstance(attr, str):
                args[0].scope[attr] = args[2]
               
        if create_scope:
            fun_scope = Scope(parent = scope)
        else:
            fun_scope = scope
        def_args = fun_type.node.args.args
        def_default_args = fun_type.node.args.defaults
        def_args_names = [arg.arg for arg in def_args]
        count_given_args = len(args)+len(keywords)
        if count_given_args > len(def_args) or count_given_args+len(def_default_args)< len(def_args):
            symbol = not_none(safe_resolve(node, 'func.attr'), safe_resolve(node, 'func.id'))
            self.warn(node, symbol = symbol, message = 'bad number of arguments (%d given, %d expected)'%(len(args), len(def_args)))
        for keyword in keywords:
            if not keyword in def_args_names:
                symbol = not_none(safe_resolve(node, 'func.attr'), safe_resolve(node, 'func.id'))
                self.warn(node, symbol = symbol, message = 'unexpected keyword argument %s'%(keyword))
        
        for i,arg in enumerate(def_args):
            if i<len(args):
                if arg.arg in keywords:
                    symbol = not_none(safe_resolve(node, 'func.attr'), safe_resolve(node, 'func.id'))
                    self.warn(node, symbol = symbol, message = 'multiple arguments for keyword argument %s'%(arg.arg))
                fun_scope[arg.arg] = args[i]
            else:
                found=False
                for j,key in enumerate(keywords):
                    if key==arg.arg:
                        found=True
                        fun_scope[arg.arg]=keywords[key]
                if not found:
                    lengthFromEnd = len(def_args)-i
                    if len(def_default_args) >= lengthFromEnd:
                        fun_scope[arg.arg]=self.eval_code(def_default_args[-lengthFromEnd],scope)
                    else:
                        fun_scope[arg.arg] = any_type
        try:
            for _node in fun_type.node.body:
                self.eval_code(_node, fun_scope)
        except ReturnException as e:
            res=e.res
            if isinstance(res, Typez) and  "__class__" in res.scope and (res.scope["__class__"] == self.extern_scope['ProblemException']):    
                error = res.scope["error"]
                message = res.scope["message"]
                #symbol = res.scope["symbol"]
                symbol = None
                for key,val in scope.items():
                    if val==error:
                        symbol = key
                #when error is caused by constant, symbol is its type
                if symbol is None:
                    if hasattr(error.scope['__class__'].node, 'name'):
                        symbol = error.scope['__class__'].node.name
                    else:
                        #default symbol
                        symbol = 'Type error'
                if is_none(message):
                    #default message because it is very often used
                    message_value = "unsupported operand type"
                else:
                    message_value = message.value
                self.warn(node, message_value, symbol)
                return any_type
            
            if isinstance(res, Typez) and  "__class__" in res.scope and (res.scope["__class__"] == self.extern_scope['TypeContainer']):      
                gen_type=res.scope["T"]
                result = Typez(kind='const',__class__ = gen_type)
                return result
 
            return res
        
        if fun_type.kind == 'classdef':
            return args[0]
Ejemplo n.º 20
0
 def exec_Num(self, node, scope):
     '''
     This method proceeds code like : 1,55, etc.
     '''
     return Typez(kind='const', node = node, value = node.n, __class__ = self.extern_scope['num'])
Ejemplo n.º 21
0
 def exec_Str(self, node, scope):
     ''''
     This method proceeds code like : 'some_string_in_input_code'
     '''
     return Typez(kind='const', node = node, value = node.s, __class__ = self.extern_scope['str'])