|
|
"""
|
|
|
C++代码分析器
|
|
|
"""
|
|
|
import re
|
|
|
import os
|
|
|
from typing import List, Dict, Any
|
|
|
from .base_analyzer import BaseAnalyzer
|
|
|
|
|
|
class CppAnalyzer(BaseAnalyzer):
|
|
|
"""C++代码分析器"""
|
|
|
|
|
|
def __init__(self):
|
|
|
super().__init__()
|
|
|
self.name = "C++ Analyzer"
|
|
|
self.version = "1.0.0"
|
|
|
self.supported_extensions = ["cpp", "cc", "cxx", "hpp", "h"]
|
|
|
self.description = "C++代码静态分析器"
|
|
|
|
|
|
async def analyze(self, project_path: str, config: Dict[str, Any] = None) -> List[Dict[str, Any]]:
|
|
|
"""分析C++代码"""
|
|
|
vulnerabilities = []
|
|
|
|
|
|
# 获取所有C++文件
|
|
|
cpp_files = self.get_project_files(project_path)
|
|
|
|
|
|
for file_path in cpp_files:
|
|
|
try:
|
|
|
# 读取文件内容
|
|
|
content = self.read_file_content(file_path)
|
|
|
if not content:
|
|
|
continue
|
|
|
|
|
|
lines = content.split('\n')
|
|
|
|
|
|
# 执行各种检查
|
|
|
vulnerabilities.extend(self._check_memory_issues(lines, file_path))
|
|
|
vulnerabilities.extend(self._check_security_issues(lines, file_path))
|
|
|
vulnerabilities.extend(self._check_performance_issues(lines, file_path))
|
|
|
|
|
|
except Exception as e:
|
|
|
# 分析错误
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP000",
|
|
|
message=f"分析错误: {str(e)}",
|
|
|
file_path=file_path,
|
|
|
severity="high",
|
|
|
category="reliability"
|
|
|
))
|
|
|
|
|
|
return vulnerabilities
|
|
|
|
|
|
def _check_memory_issues(self, lines: List[str], file_path: str) -> List[Dict[str, Any]]:
|
|
|
"""检查内存相关问题"""
|
|
|
vulnerabilities = []
|
|
|
|
|
|
for i, line in enumerate(lines):
|
|
|
line_num = i + 1
|
|
|
line_stripped = line.strip()
|
|
|
|
|
|
# 检查裸指针使用
|
|
|
if re.search(r'\*[a-zA-Z_][a-zA-Z0-9_]*\s*[=;]', line_stripped):
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP101",
|
|
|
message="使用裸指针,建议使用智能指针",
|
|
|
file_path=file_path,
|
|
|
line_number=line_num,
|
|
|
severity="medium",
|
|
|
category="reliability",
|
|
|
code_snippet=line_stripped
|
|
|
))
|
|
|
|
|
|
# 检查malloc/free使用
|
|
|
elif 'malloc(' in line_stripped or 'free(' in line_stripped:
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP102",
|
|
|
message="使用malloc/free,建议使用new/delete或智能指针",
|
|
|
file_path=file_path,
|
|
|
line_number=line_num,
|
|
|
severity="medium",
|
|
|
category="reliability",
|
|
|
code_snippet=line_stripped
|
|
|
))
|
|
|
|
|
|
# 检查数组越界风险
|
|
|
elif re.search(r'\[[a-zA-Z_][a-zA-Z0-9_]*\]', line_stripped):
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP103",
|
|
|
message="数组访问未进行边界检查",
|
|
|
file_path=file_path,
|
|
|
line_number=line_num,
|
|
|
severity="high",
|
|
|
category="reliability",
|
|
|
code_snippet=line_stripped
|
|
|
))
|
|
|
|
|
|
return vulnerabilities
|
|
|
|
|
|
def _check_security_issues(self, lines: List[str], file_path: str) -> List[Dict[str, Any]]:
|
|
|
"""检查安全问题"""
|
|
|
vulnerabilities = []
|
|
|
|
|
|
for i, line in enumerate(lines):
|
|
|
line_num = i + 1
|
|
|
line_stripped = line.strip()
|
|
|
|
|
|
# 检查strcpy使用
|
|
|
if 'strcpy(' in line_stripped:
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP201",
|
|
|
message="使用strcpy(),存在缓冲区溢出风险",
|
|
|
file_path=file_path,
|
|
|
line_number=line_num,
|
|
|
severity="critical",
|
|
|
category="security",
|
|
|
code_snippet=line_stripped
|
|
|
))
|
|
|
|
|
|
# 检查sprintf使用
|
|
|
elif 'sprintf(' in line_stripped:
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP202",
|
|
|
message="使用sprintf(),存在缓冲区溢出风险",
|
|
|
file_path=file_path,
|
|
|
line_number=line_num,
|
|
|
severity="critical",
|
|
|
category="security",
|
|
|
code_snippet=line_stripped
|
|
|
))
|
|
|
|
|
|
# 检查gets使用
|
|
|
elif 'gets(' in line_stripped:
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP203",
|
|
|
message="使用gets(),存在缓冲区溢出风险",
|
|
|
file_path=file_path,
|
|
|
line_number=line_num,
|
|
|
severity="critical",
|
|
|
category="security",
|
|
|
code_snippet=line_stripped
|
|
|
))
|
|
|
|
|
|
# 检查system调用
|
|
|
elif 'system(' in line_stripped:
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP204",
|
|
|
message="使用system()调用,存在命令注入风险",
|
|
|
file_path=file_path,
|
|
|
line_number=line_num,
|
|
|
severity="high",
|
|
|
category="security",
|
|
|
code_snippet=line_stripped
|
|
|
))
|
|
|
|
|
|
return vulnerabilities
|
|
|
|
|
|
def _check_performance_issues(self, lines: List[str], file_path: str) -> List[Dict[str, Any]]:
|
|
|
"""检查性能问题"""
|
|
|
vulnerabilities = []
|
|
|
|
|
|
for i, line in enumerate(lines):
|
|
|
line_num = i + 1
|
|
|
line_stripped = line.strip()
|
|
|
|
|
|
# 检查循环中的字符串连接
|
|
|
if re.search(r'for\s*\([^)]*\)\s*\{', line_stripped):
|
|
|
# 查找循环体中的字符串连接
|
|
|
for j in range(i + 1, min(i + 20, len(lines))): # 检查循环体前20行
|
|
|
loop_line = lines[j].strip()
|
|
|
if loop_line == '}':
|
|
|
break
|
|
|
if '+' in loop_line and ('"' in loop_line or "'" in loop_line):
|
|
|
vulnerabilities.append(self.create_vulnerability(
|
|
|
rule_id="CPP301",
|
|
|
message="循环中使用字符串连接,影响性能",
|
|
|
file_path=file_path,
|
|
|
line_number=j + 1,
|
|
|
severity="low",
|
|
|
category="performance",
|
|
|
code_snippet=loop_line
|
|
|
))
|
|
|
|
|
|
# 检查未使用的头文件包含
|
|
|
elif line_stripped.startswith('#include'):
|
|
|
# 这里可以添加更复杂的检查逻辑
|
|
|
pass
|
|
|
|
|
|
return vulnerabilities
|