Beispiel #1
0
 def __init__(self,extern_scope=None):
     self.specials = {}
     self.modules = []
     self.problems = []
     self.visited_ast_nodes=[]
     self.breakpoint = None
     
     if extern_scope is None:
         #f = open("inf/inference/externs.py", "r")
         curr_location = os.path.dirname(os.path.realpath(__file__))
         f = open(curr_location+'/externs.py', 'r')
         source = f.read()
         f.close()
         node = ast.parse(source, filename = 'externs.py', mode = 'exec')
         logger.info('parsing externs')
         self.extern_scope = Scope(is_root = True)
         self.root_scope = Scope(parent = self.extern_scope)
         self.eval_code(node, self.extern_scope)
         logger.info('!!!externs parsed')
         #print('externs parsed')
     else:
         self.extern_scope = extern_scope
         self.root_scope = Scope(parent = self.extern_scope)
     
     self.modules = []
     self.problems = []
Beispiel #2
0
 def setUp(self):
     scope = Scope(is_root=True)
     scope['a'] = 'a'
     scope['b'] = 'b'
     child_scope = Scope(parent=scope)
     child_scope['c'] = 'c'
     self.scope = scope
     self.child_scope = child_scope
Beispiel #3
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})
Beispiel #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')
    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})
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')
Beispiel #7
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)
Beispiel #8
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
Beispiel #9
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]
Beispiel #10
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
        })