File size: 1,591 Bytes
b19c92c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import ast, javalang, re
class BugDetector:
    def detect_none_deref_python(self,code):
        issues=[]; 
        try:
            t=ast.parse(code)
            for n in ast.walk(t):
                if isinstance(n,ast.Attribute) and isinstance(n.value,ast.Name):
                    issues.append({'line':n.lineno,'msg':f"Possible None dereference: {n.value.id}"})
        except: pass
        return issues
    def detect_unused_vars_python(self,code):
        issues=[] 
        try:
            t=ast.parse(code);assigned=set();used=set()
            for n in ast.walk(t):
                if isinstance(n,ast.Assign):
                    for t2 in n.targets:
                        if isinstance(t2,ast.Name): assigned.add(t2.id)
                if isinstance(n,ast.Name) and isinstance(n.ctx,ast.Load): used.add(n.id)
            for v in assigned-used: issues.append({'msg':f"Unused variable {v}"})
        except: pass
        return issues
    def detect_null_checks_java(self,code):
        issues=[]
        try:
            for m in re.finditer(r"(\w+)\.\w+\(",code):
                v=m.group(1);ctx=code[max(0,m.start()-200):m.end()+200]
                if not re.search(rf"if *\( *{v} *!= *null",ctx):
                    issues.append({'msg':f"Possible null dereference: {v}"})
        except: pass
        return issues
    def analyze(self,code,lang):
        lang=lang.lower()
        if lang=='python': return self.detect_none_deref_python(code)+self.detect_unused_vars_python(code)
        if lang=='java': return self.detect_null_checks_java(code)
        return []