| 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 [] | |