parent
df0eb0e075
commit
cd396d0f63
@ -1,4 +1,18 @@
|
||||
# Web UI文件
|
||||
recursive-include webui/templates *.html
|
||||
recursive-include webui/static *.css *.js
|
||||
include webui/README.md
|
||||
|
||||
# 核心C源码
|
||||
recursive-include src *.c *.h
|
||||
include src/*.c
|
||||
include src/*.h
|
||||
|
||||
# 文档和配置
|
||||
include README.md
|
||||
include pyproject.toml
|
||||
include MANIFEST.in
|
||||
|
||||
# 输出目录(示例)
|
||||
recursive-include output *.txt *.json *.html
|
||||
|
||||
|
||||
Binary file not shown.
@ -0,0 +1,289 @@
|
||||
#include "intelligent_analyzer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
// 批量分析配置
|
||||
typedef struct {
|
||||
char input_dir[512];
|
||||
char output_dir[512];
|
||||
char file_pattern[256];
|
||||
int max_concurrent;
|
||||
int priority;
|
||||
ResourceLimits limits;
|
||||
} BatchConfig;
|
||||
|
||||
// 文件信息结构
|
||||
typedef struct {
|
||||
char file_path[512];
|
||||
char file_name[256];
|
||||
time_t modified_time;
|
||||
size_t file_size;
|
||||
int is_c_file;
|
||||
} FileInfo;
|
||||
|
||||
// 批量分析器
|
||||
typedef struct {
|
||||
BatchConfig config;
|
||||
FileInfo* files;
|
||||
int file_count;
|
||||
int max_files;
|
||||
char log_file[512];
|
||||
time_t start_time;
|
||||
} BatchAnalyzer;
|
||||
|
||||
// 初始化批量分析器
|
||||
int init_batch_analyzer(BatchAnalyzer* analyzer, const BatchConfig* config) {
|
||||
memset(analyzer, 0, sizeof(BatchAnalyzer));
|
||||
analyzer->config = *config;
|
||||
analyzer->max_files = 1000;
|
||||
analyzer->files = malloc(sizeof(FileInfo) * analyzer->max_files);
|
||||
|
||||
if (!analyzer->files) {
|
||||
printf("错误: 无法分配内存\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
analyzer->start_time = time(NULL);
|
||||
snprintf(analyzer->log_file, sizeof(analyzer->log_file),
|
||||
"%s/batch_analysis_%ld.log", config->output_dir, analyzer->start_time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 扫描目录中的文件
|
||||
int scan_directory(BatchAnalyzer* analyzer) {
|
||||
DIR* dir = opendir(analyzer->config.input_dir);
|
||||
if (!dir) {
|
||||
printf("错误: 无法打开目录 %s\n", analyzer->config.input_dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL && analyzer->file_count < analyzer->max_files) {
|
||||
// 跳过隐藏文件和目录
|
||||
if (entry->d_name[0] == '.') continue;
|
||||
|
||||
// 构建完整路径
|
||||
char full_path[1024];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s",
|
||||
analyzer->config.input_dir, entry->d_name);
|
||||
|
||||
// 检查是否为文件
|
||||
struct stat file_stat;
|
||||
if (stat(full_path, &file_stat) != 0) continue;
|
||||
if (!S_ISREG(file_stat.st_mode)) continue;
|
||||
|
||||
// 检查文件扩展名
|
||||
char* ext = strrchr(entry->d_name, '.');
|
||||
int is_c_file = 0;
|
||||
if (ext && (strcmp(ext, ".c") == 0 || strcmp(ext, ".cpp") == 0 ||
|
||||
strcmp(ext, ".cc") == 0 || strcmp(ext, ".cxx") == 0)) {
|
||||
is_c_file = 1;
|
||||
}
|
||||
|
||||
// 检查文件模式匹配
|
||||
if (strlen(analyzer->config.file_pattern) > 0) {
|
||||
if (strstr(entry->d_name, analyzer->config.file_pattern) == NULL) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加到文件列表
|
||||
FileInfo* file = &analyzer->files[analyzer->file_count];
|
||||
strncpy(file->file_path, full_path, sizeof(file->file_path) - 1);
|
||||
strncpy(file->file_name, entry->d_name, sizeof(file->file_name) - 1);
|
||||
file->modified_time = file_stat.st_mtime;
|
||||
file->file_size = file_stat.st_size;
|
||||
file->is_c_file = is_c_file;
|
||||
|
||||
analyzer->file_count++;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
printf("扫描完成: 找到 %d 个文件\n", analyzer->file_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 执行批量分析
|
||||
int execute_batch_analysis(BatchAnalyzer* analyzer) {
|
||||
printf("开始批量分析...\n");
|
||||
printf("输入目录: %s\n", analyzer->config.input_dir);
|
||||
printf("输出目录: %s\n", analyzer->config.output_dir);
|
||||
printf("最大并发数: %d\n", analyzer->config.max_concurrent);
|
||||
|
||||
// 初始化并行分析器
|
||||
if (init_parallel_analyzer(analyzer->file_count, &analyzer->config.limits) != 0) {
|
||||
printf("错误: 无法初始化并行分析器\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 添加所有C/C++文件到分析队列
|
||||
int c_file_count = 0;
|
||||
for (int i = 0; i < analyzer->file_count; i++) {
|
||||
FileInfo* file = &analyzer->files[i];
|
||||
if (file->is_c_file) {
|
||||
int task_id = add_analysis_task(file->file_path, analyzer->config.priority);
|
||||
if (task_id >= 0) {
|
||||
c_file_count++;
|
||||
printf("添加任务 %d: %s\n", task_id, file->file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("总共添加了 %d 个C/C++文件到分析队列\n", c_file_count);
|
||||
|
||||
// 启动并行分析
|
||||
if (start_parallel_analysis(analyzer->config.max_concurrent) != 0) {
|
||||
printf("错误: 并行分析启动失败\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 生成批量分析报告
|
||||
char report_file[512];
|
||||
snprintf(report_file, sizeof(report_file), "%s/batch_analysis_report.html",
|
||||
analyzer->config.output_dir);
|
||||
generate_batch_analysis_report(report_file);
|
||||
|
||||
// 获取分析统计
|
||||
int total, completed, failed, running;
|
||||
get_analysis_statistics(&total, &completed, &failed, &running);
|
||||
|
||||
printf("\n=== 批量分析完成 ===\n");
|
||||
printf("总任务数: %d\n", total);
|
||||
printf("已完成: %d\n", completed);
|
||||
printf("失败: %d\n", failed);
|
||||
printf("运行中: %d\n", running);
|
||||
printf("成功率: %.2f%%\n", (double)completed / total * 100.0);
|
||||
printf("报告文件: %s\n", report_file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 生成文件统计报告
|
||||
void generate_file_statistics(BatchAnalyzer* analyzer, const char* output_file) {
|
||||
FILE* file = fopen(output_file, "w");
|
||||
if (!file) return;
|
||||
|
||||
fprintf(file,
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
" <title>文件统计报告</title>\n"
|
||||
" <style>\n"
|
||||
" body { font-family: Arial, sans-serif; margin: 20px; }\n"
|
||||
" .summary { background: #f5f5f5; padding: 15px; border-radius: 5px; margin: 20px 0; }\n"
|
||||
" .file-list { margin: 20px 0; }\n"
|
||||
" .file-item { border: 1px solid #ddd; padding: 10px; margin: 5px 0; border-radius: 3px; }\n"
|
||||
" .c-file { background: #e8f5e8; }\n"
|
||||
" .other-file { background: #f8f8f8; }\n"
|
||||
" </style>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
" <h1>文件统计报告</h1>\n"
|
||||
" \n"
|
||||
" <div class=\"summary\">\n"
|
||||
" <h2>扫描摘要</h2>\n"
|
||||
" <p>扫描目录: %s</p>\n"
|
||||
" <p>总文件数: %d</p>\n"
|
||||
" <p>C/C++文件: %d</p>\n"
|
||||
" <p>其他文件: %d</p>\n"
|
||||
" <p>扫描时间: %s</p>\n"
|
||||
" </div>\n"
|
||||
" \n"
|
||||
" <div class=\"file-list\">\n"
|
||||
" <h2>文件列表</h2>\n",
|
||||
analyzer->config.input_dir,
|
||||
analyzer->file_count,
|
||||
analyzer->file_count, // 这里需要计算C文件数量
|
||||
analyzer->file_count, // 这里需要计算其他文件数量
|
||||
ctime(&analyzer->start_time)
|
||||
);
|
||||
|
||||
// 添加文件详情
|
||||
for (int i = 0; i < analyzer->file_count; i++) {
|
||||
FileInfo* file = &analyzer->files[i];
|
||||
const char* file_class = file->is_c_file ? "c-file" : "other-file";
|
||||
const char* file_type = file->is_c_file ? "C/C++" : "其他";
|
||||
|
||||
fprintf(file,
|
||||
" <div class=\"file-item %s\">\n"
|
||||
" <h3>%s</h3>\n"
|
||||
" <p>类型: %s</p>\n"
|
||||
" <p>大小: %zu 字节</p>\n"
|
||||
" <p>修改时间: %s</p>\n"
|
||||
" </div>\n",
|
||||
file_class,
|
||||
file->file_name,
|
||||
file_type,
|
||||
file->file_size,
|
||||
ctime(&file->modified_time)
|
||||
);
|
||||
}
|
||||
|
||||
fprintf(file,
|
||||
" </div>\n"
|
||||
"</body>\n"
|
||||
"</html>\n"
|
||||
);
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// 清理批量分析器
|
||||
void cleanup_batch_analyzer(BatchAnalyzer* analyzer) {
|
||||
if (analyzer->files) {
|
||||
free(analyzer->files);
|
||||
analyzer->files = NULL;
|
||||
}
|
||||
cleanup_parallel_analyzer();
|
||||
}
|
||||
|
||||
// 主批量分析函数
|
||||
int batch_analyze_files(const char* input_dir, const char* output_dir,
|
||||
const char* file_pattern, int max_concurrent) {
|
||||
// 创建输出目录
|
||||
char mkdir_cmd[1024];
|
||||
snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p %s", output_dir);
|
||||
system(mkdir_cmd);
|
||||
|
||||
// 初始化配置
|
||||
BatchConfig config;
|
||||
strncpy(config.input_dir, input_dir, sizeof(config.input_dir) - 1);
|
||||
strncpy(config.output_dir, output_dir, sizeof(config.output_dir) - 1);
|
||||
strncpy(config.file_pattern, file_pattern, sizeof(config.file_pattern) - 1);
|
||||
config.max_concurrent = max_concurrent;
|
||||
config.priority = 1;
|
||||
|
||||
// 初始化资源限制
|
||||
init_resource_limits(&config.limits);
|
||||
|
||||
// 初始化批量分析器
|
||||
BatchAnalyzer analyzer;
|
||||
if (init_batch_analyzer(&analyzer, &config) != 0) {
|
||||
printf("错误: 无法初始化批量分析器\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 扫描目录
|
||||
if (scan_directory(&analyzer) != 0) {
|
||||
printf("错误: 目录扫描失败\n");
|
||||
cleanup_batch_analyzer(&analyzer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 生成文件统计报告
|
||||
char stats_file[512];
|
||||
snprintf(stats_file, sizeof(stats_file), "%s/file_statistics.html", output_dir);
|
||||
generate_file_statistics(&analyzer, stats_file);
|
||||
|
||||
// 执行批量分析
|
||||
int result = execute_batch_analysis(&analyzer);
|
||||
|
||||
// 清理资源
|
||||
cleanup_batch_analyzer(&analyzer);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
#include "intelligent_analyzer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
// 批量分析CLI工具
|
||||
int main(int argc, char* argv[]) {
|
||||
char input_dir[512] = ".";
|
||||
char output_dir[512] = "output/batch_analysis";
|
||||
char file_pattern[256] = "";
|
||||
int max_concurrent = 4;
|
||||
int help = 0;
|
||||
|
||||
// 命令行选项
|
||||
static struct option long_options[] = {
|
||||
{"input-dir", required_argument, 0, 'i'},
|
||||
{"output-dir", required_argument, 0, 'o'},
|
||||
{"pattern", required_argument, 0, 'p'},
|
||||
{"concurrent", required_argument, 0, 'c'},
|
||||
{"help", no_argument, &help, 1},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int option_index = 0;
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "i:o:p:c:h", long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
strncpy(input_dir, optarg, sizeof(input_dir) - 1);
|
||||
break;
|
||||
case 'o':
|
||||
strncpy(output_dir, optarg, sizeof(output_dir) - 1);
|
||||
break;
|
||||
case 'p':
|
||||
strncpy(file_pattern, optarg, sizeof(file_pattern) - 1);
|
||||
break;
|
||||
case 'c':
|
||||
max_concurrent = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
help = 1;
|
||||
break;
|
||||
case '?':
|
||||
printf("使用 --help 查看帮助信息\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (help) {
|
||||
printf("批量分析工具 - 并行分析多个C/C++文件\n\n");
|
||||
printf("用法: %s [选项]\n\n", argv[0]);
|
||||
printf("选项:\n");
|
||||
printf(" -i, --input-dir DIR 输入目录 (默认: .)\n");
|
||||
printf(" -o, --output-dir DIR 输出目录 (默认: output/batch_analysis)\n");
|
||||
printf(" -p, --pattern PATTERN 文件模式匹配 (默认: 所有文件)\n");
|
||||
printf(" -c, --concurrent NUM 最大并发数 (默认: 4)\n");
|
||||
printf(" -h, --help 显示帮助信息\n\n");
|
||||
printf("示例:\n");
|
||||
printf(" %s -i src -o results -p test -c 8\n", argv[0]);
|
||||
printf(" %s --input-dir /path/to/source --output-dir /path/to/results\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("=== 批量分析工具 ===\n");
|
||||
printf("输入目录: %s\n", input_dir);
|
||||
printf("输出目录: %s\n", output_dir);
|
||||
printf("文件模式: %s\n", strlen(file_pattern) > 0 ? file_pattern : "所有文件");
|
||||
printf("最大并发: %d\n\n", max_concurrent);
|
||||
|
||||
// 执行批量分析
|
||||
int result = batch_analyze_files(input_dir, output_dir, file_pattern, max_concurrent);
|
||||
|
||||
if (result == 0) {
|
||||
printf("\n✅ 批量分析完成!\n");
|
||||
printf("结果保存在: %s\n", output_dir);
|
||||
} else {
|
||||
printf("\n❌ 批量分析失败!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,208 @@
|
||||
#include "intelligent_analyzer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// 批量报告生成器
|
||||
typedef struct {
|
||||
char start_date[32];
|
||||
char end_date[32];
|
||||
char output_dir[256];
|
||||
char package_name[256];
|
||||
int include_archives;
|
||||
int include_reports;
|
||||
int cleanup_old;
|
||||
int days_to_keep;
|
||||
} BatchReportConfig;
|
||||
|
||||
// 默认配置
|
||||
BatchReportConfig default_config = {
|
||||
.start_date = "",
|
||||
.end_date = "",
|
||||
.output_dir = "batch_reports",
|
||||
.package_name = "analysis_batch",
|
||||
.include_archives = 1,
|
||||
.include_reports = 1,
|
||||
.cleanup_old = 0,
|
||||
.days_to_keep = 30
|
||||
};
|
||||
|
||||
// 生成批量报告
|
||||
int generate_batch_reports(BatchReportConfig* config) {
|
||||
printf("=== 批量报告生成器 ===\n");
|
||||
printf("开始时间: %s\n", config->start_date[0] ? config->start_date : "无限制");
|
||||
printf("结束时间: %s\n", config->end_date[0] ? config->end_date : "无限制");
|
||||
printf("输出目录: %s\n", config->output_dir);
|
||||
printf("包名称: %s\n", config->package_name);
|
||||
|
||||
// 创建输出目录
|
||||
mkdir(config->output_dir, 0755);
|
||||
|
||||
// 初始化历史管理器
|
||||
init_global_history_manager("output");
|
||||
|
||||
if (!g_history_manager) {
|
||||
printf("错误: 无法初始化历史管理器\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 生成统计报告
|
||||
char stats_file[512];
|
||||
snprintf(stats_file, sizeof(stats_file), "%s/%s_statistics.txt",
|
||||
config->output_dir, config->package_name);
|
||||
generate_history_statistics(g_history_manager, stats_file);
|
||||
|
||||
// 导出CSV
|
||||
char csv_file[512];
|
||||
snprintf(csv_file, sizeof(csv_file), "%s/%s_history.csv",
|
||||
config->output_dir, config->package_name);
|
||||
export_history_to_csv(g_history_manager, csv_file);
|
||||
|
||||
// 创建批量报告包
|
||||
char package_file[512];
|
||||
snprintf(package_file, sizeof(package_file), "%s/%s_package.tar.gz",
|
||||
config->output_dir, config->package_name);
|
||||
|
||||
int file_count = create_batch_report_package(g_history_manager, package_file,
|
||||
config->start_date[0] ? config->start_date : NULL,
|
||||
config->end_date[0] ? config->end_date : NULL);
|
||||
|
||||
// 生成汇总报告
|
||||
generate_summary_report(config, file_count);
|
||||
|
||||
// 清理旧记录(如果启用)
|
||||
if (config->cleanup_old) {
|
||||
cleanup_old_history(g_history_manager, config->days_to_keep);
|
||||
}
|
||||
|
||||
printf("批量报告生成完成\n");
|
||||
printf("统计报告: %s\n", stats_file);
|
||||
printf("CSV导出: %s\n", csv_file);
|
||||
printf("报告包: %s (包含 %d 个文件)\n", package_file, file_count);
|
||||
|
||||
cleanup_history_manager();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 生成汇总报告
|
||||
void generate_summary_report(BatchReportConfig* config, int file_count) {
|
||||
char summary_file[512];
|
||||
snprintf(summary_file, sizeof(summary_file), "%s/%s_summary.html",
|
||||
config->output_dir, config->package_name);
|
||||
|
||||
FILE* html = fopen(summary_file, "w");
|
||||
if (!html) return;
|
||||
|
||||
fprintf(html, "<!DOCTYPE html>\n");
|
||||
fprintf(html, "<html>\n<head>\n");
|
||||
fprintf(html, "<title>批量分析报告汇总</title>\n");
|
||||
fprintf(html, "<style>\n");
|
||||
fprintf(html, "body { font-family: Arial, sans-serif; margin: 20px; }\n");
|
||||
fprintf(html, ".header { background: #f0f0f0; padding: 20px; border-radius: 5px; }\n");
|
||||
fprintf(html, ".stats { display: flex; justify-content: space-around; margin: 20px 0; }\n");
|
||||
fprintf(html, ".stat-box { background: #e8f4f8; padding: 15px; border-radius: 5px; text-align: center; }\n");
|
||||
fprintf(html, ".files { margin: 20px 0; }\n");
|
||||
fprintf(html, ".file-item { background: #f9f9f9; padding: 10px; margin: 5px 0; border-radius: 3px; }\n");
|
||||
fprintf(html, "</style>\n</head>\n<body>\n");
|
||||
|
||||
fprintf(html, "<div class='header'>\n");
|
||||
fprintf(html, "<h1>批量分析报告汇总</h1>\n");
|
||||
fprintf(html, "<p>生成时间: %s</p>\n", get_current_timestamp());
|
||||
fprintf(html, "<p>时间范围: %s 到 %s</p>\n",
|
||||
config->start_date[0] ? config->start_date : "开始",
|
||||
config->end_date[0] ? config->end_date : "现在");
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 统计信息
|
||||
fprintf(html, "<div class='stats'>\n");
|
||||
fprintf(html, "<div class='stat-box'>\n");
|
||||
fprintf(html, "<h3>总分析次数</h3>\n");
|
||||
fprintf(html, "<p>%d</p>\n", g_history_manager ? g_history_manager->count : 0);
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
fprintf(html, "<div class='stat-box'>\n");
|
||||
fprintf(html, "<h3>包含文件数</h3>\n");
|
||||
fprintf(html, "<p>%d</p>\n", file_count);
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
fprintf(html, "<div class='stat-box'>\n");
|
||||
fprintf(html, "<h3>报告类型</h3>\n");
|
||||
fprintf(html, "<p>HTML, JSON, TXT</p>\n");
|
||||
fprintf(html, "</div>\n");
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 文件列表
|
||||
fprintf(html, "<div class='files'>\n");
|
||||
fprintf(html, "<h2>包含的文件</h2>\n");
|
||||
|
||||
if (g_history_manager) {
|
||||
for (int i = 0; i < g_history_manager->count; i++) {
|
||||
HistoryEntry* entry = &g_history_manager->entries[i];
|
||||
fprintf(html, "<div class='file-item'>\n");
|
||||
fprintf(html, "<strong>%s</strong> - %s<br>\n", entry->archive_id, entry->source_file);
|
||||
fprintf(html, "漏洞数: %d, KLEE确认: %d, 覆盖率: %.2f%%<br>\n",
|
||||
entry->vuln_count, entry->klee_confirmed, entry->coverage_rate);
|
||||
fprintf(html, "分析时间: %ld 毫秒<br>\n", entry->analysis_time_ms);
|
||||
fprintf(html, "</div>\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(html, "</div>\n");
|
||||
fprintf(html, "</body>\n</html>\n");
|
||||
fclose(html);
|
||||
|
||||
printf("汇总报告已生成: %s\n", summary_file);
|
||||
}
|
||||
|
||||
// 命令行批量报告生成器
|
||||
int main(int argc, char* argv[]) {
|
||||
BatchReportConfig config = default_config;
|
||||
|
||||
// 解析命令行参数
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "s:e:o:n:ac:d:h")) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
strncpy(config.start_date, optarg, sizeof(config.start_date) - 1);
|
||||
break;
|
||||
case 'e':
|
||||
strncpy(config.end_date, optarg, sizeof(config.end_date) - 1);
|
||||
break;
|
||||
case 'o':
|
||||
strncpy(config.output_dir, optarg, sizeof(config.output_dir) - 1);
|
||||
break;
|
||||
case 'n':
|
||||
strncpy(config.package_name, optarg, sizeof(config.package_name) - 1);
|
||||
break;
|
||||
case 'a':
|
||||
config.include_archives = 1;
|
||||
break;
|
||||
case 'c':
|
||||
config.cleanup_old = 1;
|
||||
config.days_to_keep = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
config.days_to_keep = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
printf("用法: %s [选项]\n", argv[0]);
|
||||
printf("选项:\n");
|
||||
printf(" -s <开始日期> 开始日期 (YYYY-MM-DD)\n");
|
||||
printf(" -e <结束日期> 结束日期 (YYYY-MM-DD)\n");
|
||||
printf(" -o <输出目录> 输出目录 (默认: batch_reports)\n");
|
||||
printf(" -n <包名称> 包名称 (默认: analysis_batch)\n");
|
||||
printf(" -a 包含归档文件\n");
|
||||
printf(" -c <天数> 清理旧记录并保留指定天数\n");
|
||||
printf(" -d <天数> 保留天数 (默认: 30)\n");
|
||||
printf(" -h 显示帮助\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return generate_batch_reports(&config);
|
||||
}
|
||||
@ -0,0 +1,275 @@
|
||||
#include "intelligent_analyzer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
// 增强的报告生成器
|
||||
typedef struct {
|
||||
char title[100];
|
||||
char content[1000];
|
||||
int priority;
|
||||
} ReportSection;
|
||||
|
||||
// 生成增强的HTML报告
|
||||
void generate_enhanced_html_report(AnalysisResult* result, const char* output_file) {
|
||||
FILE* html = fopen(output_file, "w");
|
||||
if (!html) return;
|
||||
|
||||
fprintf(html, "<!DOCTYPE html>\n");
|
||||
fprintf(html, "<html><head>\n");
|
||||
fprintf(html, "<title>智能符号执行分析报告</title>\n");
|
||||
fprintf(html, "<style>\n");
|
||||
fprintf(html, "body { font-family: Arial, sans-serif; margin: 20px; }\n");
|
||||
fprintf(html, ".header { background: #2c3e50; color: white; padding: 20px; border-radius: 5px; }\n");
|
||||
fprintf(html, ".section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }\n");
|
||||
fprintf(html, ".vulnerability { background: #f8f9fa; margin: 10px 0; padding: 10px; border-left: 4px solid #dc3545; }\n");
|
||||
fprintf(html, ".severity-5 { border-left-color: #dc3545; }\n");
|
||||
fprintf(html, ".severity-4 { border-left-color: #fd7e14; }\n");
|
||||
fprintf(html, ".severity-3 { border-left-color: #ffc107; }\n");
|
||||
fprintf(html, ".metric { display: inline-block; margin: 10px; padding: 10px; background: #e9ecef; border-radius: 3px; }\n");
|
||||
fprintf(html, "</style>\n");
|
||||
fprintf(html, "</head><body>\n");
|
||||
|
||||
// 报告头部
|
||||
fprintf(html, "<div class='header'>\n");
|
||||
fprintf(html, "<h1>🔍 智能符号执行分析报告</h1>\n");
|
||||
fprintf(html, "<p>分析时间: %s</p>\n", result->analysis_timestamp);
|
||||
fprintf(html, "<p>源文件: %s</p>\n", result->source_file ? result->source_file : "未知");
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 执行摘要
|
||||
fprintf(html, "<div class='section'>\n");
|
||||
fprintf(html, "<h2>📊 执行摘要</h2>\n");
|
||||
fprintf(html, "<div class='metric'>漏洞总数: %d</div>\n", result->vuln_count);
|
||||
fprintf(html, "<div class='metric'>KLEE确认: %d</div>\n", count_klee_confirmed(result));
|
||||
fprintf(html, "<div class='metric'>覆盖率: %.1f%%</div>\n", result->klee_analysis.coverage_rate);
|
||||
fprintf(html, "<div class='metric'>分析耗时: %ldms</div>\n", result->analysis_time ? result->analysis_time : 0);
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 漏洞详情
|
||||
fprintf(html, "<div class='section'>\n");
|
||||
fprintf(html, "<h2>🚨 漏洞详情</h2>\n");
|
||||
for (int i = 0; i < result->vuln_count; i++) {
|
||||
VulnerabilityInfo* vuln = &result->vulnerabilities[i];
|
||||
fprintf(html, "<div class='vulnerability severity-%d'>\n", vuln->severity);
|
||||
const char* type_name = get_vulnerability_type_name(vuln->type);
|
||||
fprintf(html, "<h3>%s (严重性: %d/5)</h3>\n", type_name, vuln->severity);
|
||||
fprintf(html, "<p><strong>位置:</strong> %s:%d</p>\n",
|
||||
vuln->file_path ? vuln->file_path : "未知", vuln->line_number);
|
||||
fprintf(html, "<p><strong>描述:</strong> %s</p>\n",
|
||||
vuln->description ? vuln->description : "无描述");
|
||||
fprintf(html, "<p><strong>修复建议:</strong> %s</p>\n",
|
||||
vuln->fix_suggestion ? vuln->fix_suggestion : "无建议");
|
||||
fprintf(html, "<p><strong>置信度:</strong> %d%%</p>\n", vuln->confidence_score);
|
||||
fprintf(html, "<p><strong>KLEE确认:</strong> %s</p>\n", vuln->confirmed_by_klee ? "✅ 是" : "❌ 否");
|
||||
if (vuln->klee_evidence && strlen(vuln->klee_evidence) > 0) {
|
||||
fprintf(html, "<p><strong>KLEE证据:</strong> %s</p>\n", vuln->klee_evidence);
|
||||
}
|
||||
fprintf(html, "</div>\n");
|
||||
}
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 性能分析
|
||||
fprintf(html, "<div class='section'>\n");
|
||||
fprintf(html, "<h2>⚡ 性能分析</h2>\n");
|
||||
fprintf(html, "<div class='metric'>KLEE执行时间: %ldms</div>\n", result->klee_analysis.execution_time);
|
||||
fprintf(html, "<div class='metric'>内存使用: %ldMB</div>\n", result->klee_analysis.memory_usage);
|
||||
fprintf(html, "<div class='metric'>CPU使用率: %.1f%%</div>\n", result->klee_analysis.cpu_usage);
|
||||
fprintf(html, "<div class='metric'>总指令数: %d</div>\n", result->klee_analysis.total_instructions);
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 代码质量指标
|
||||
fprintf(html, "<div class='section'>\n");
|
||||
fprintf(html, "<h2>📈 代码质量指标</h2>\n");
|
||||
fprintf(html, "<div class='metric'>圈复杂度: %d</div>\n", result->quality_metrics.cyclomatic_complexity);
|
||||
fprintf(html, "<div class='metric'>函数数量: %d</div>\n", result->quality_metrics.function_count);
|
||||
fprintf(html, "<div class='metric'>平均函数长度: %.1f行</div>\n", result->quality_metrics.avg_function_length);
|
||||
fprintf(html, "<div class='metric'>注释覆盖率: %.1f%%</div>\n", result->quality_metrics.comment_coverage);
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 安全评分
|
||||
int security_score = calculate_security_score(result);
|
||||
fprintf(html, "<div class='section'>\n");
|
||||
fprintf(html, "<h2>🛡️ 安全评分</h2>\n");
|
||||
fprintf(html, "<div class='metric'>总体安全评分: %d/100</div>\n", security_score);
|
||||
fprintf(html, "<div class='metric'>风险等级: %s</div>\n", get_risk_level(security_score));
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 修复优先级
|
||||
fprintf(html, "<div class='section'>\n");
|
||||
fprintf(html, "<h2>🔧 修复优先级</h2>\n");
|
||||
generate_repair_priority_html(result, html);
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
// 工具推荐
|
||||
fprintf(html, "<div class='section'>\n");
|
||||
fprintf(html, "<h2>🛠️ 推荐工具</h2>\n");
|
||||
generate_tool_recommendations_html(result, html);
|
||||
fprintf(html, "</div>\n");
|
||||
|
||||
fprintf(html, "</body></html>\n");
|
||||
fclose(html);
|
||||
printf("增强HTML报告已生成: %s\n", output_file);
|
||||
}
|
||||
|
||||
// 获取漏洞类型名称
|
||||
const char* get_vulnerability_type_name(VulnerabilityType type) {
|
||||
switch (type) {
|
||||
case VULN_BUFFER_OVERFLOW: return "缓冲区溢出";
|
||||
case VULN_NULL_POINTER_DEREF: return "空指针解引用";
|
||||
case VULN_DIVISION_BY_ZERO: return "除零错误";
|
||||
case VULN_MEMORY_LEAK: return "内存泄漏";
|
||||
case VULN_ARRAY_BOUNDS: return "数组越界";
|
||||
case VULN_UNINITIALIZED_VAR: return "未初始化变量";
|
||||
case VULN_INTEGER_OVERFLOW: return "整数溢出";
|
||||
case VULN_USE_AFTER_FREE: return "使用已释放内存";
|
||||
case VULN_FORMAT_STRING: return "格式化字符串漏洞";
|
||||
case VULN_PATH_TRAVERSAL: return "路径遍历";
|
||||
case VULN_RACE_CONDITION: return "竞态条件";
|
||||
case VULN_DEEP_RECURSION: return "深度递归";
|
||||
case VULN_DEADLOCK: return "死锁";
|
||||
// 扩展规则库新增漏洞类型
|
||||
case VULN_DOUBLE_FREE: return "双重释放";
|
||||
case VULN_ALIGNMENT_ISSUE: return "内存对齐问题";
|
||||
case VULN_TYPE_CONFUSION: return "类型混淆";
|
||||
case VULN_STACK_OVERFLOW: return "栈溢出";
|
||||
case VULN_CONCURRENCY_ISSUE: return "并发安全问题";
|
||||
case VULN_SIGNAL_SAFETY: return "信号安全问题";
|
||||
default: return "未知漏洞";
|
||||
}
|
||||
}
|
||||
|
||||
// 生成JSON报告
|
||||
void generate_enhanced_json_report(AnalysisResult* result, const char* output_file) {
|
||||
FILE* json = fopen(output_file, "w");
|
||||
if (!json) return;
|
||||
|
||||
fprintf(json, "{\n");
|
||||
fprintf(json, " \"analysis_summary\": {\n");
|
||||
fprintf(json, " \"timestamp\": \"%s\",\n", result->analysis_timestamp);
|
||||
fprintf(json, " \"source_file\": \"%s\",\n", result->source_file ? result->source_file : "未知");
|
||||
fprintf(json, " \"analysis_time_ms\": %ld,\n", result->analysis_time ? result->analysis_time : 0);
|
||||
fprintf(json, " \"total_vulnerabilities\": %d,\n", result->vuln_count);
|
||||
fprintf(json, " \"klee_confirmed\": %d,\n", count_klee_confirmed(result));
|
||||
fprintf(json, " \"coverage_rate\": %.2f\n", result->klee_analysis.coverage_rate);
|
||||
fprintf(json, " },\n");
|
||||
|
||||
// 漏洞详情
|
||||
fprintf(json, " \"vulnerabilities\": [\n");
|
||||
for (int i = 0; i < result->vuln_count; i++) {
|
||||
VulnerabilityInfo* vuln = &result->vulnerabilities[i];
|
||||
fprintf(json, " {\n");
|
||||
fprintf(json, " \"id\": %d,\n", i + 1);
|
||||
const char* type_name = get_vulnerability_type_name(vuln->type);
|
||||
fprintf(json, " \"type\": \"%s\",\n", type_name);
|
||||
fprintf(json, " \"severity\": %d,\n", vuln->severity);
|
||||
fprintf(json, " \"line_number\": %d,\n", vuln->line_number);
|
||||
fprintf(json, " \"description\": \"%s\",\n", vuln->description);
|
||||
fprintf(json, " \"fix_suggestion\": \"%s\",\n", vuln->fix_suggestion);
|
||||
fprintf(json, " \"confidence_score\": %d,\n", vuln->confidence_score);
|
||||
fprintf(json, " \"confirmed_by_klee\": %s,\n", vuln->confirmed_by_klee ? "true" : "false");
|
||||
fprintf(json, " \"klee_evidence\": \"%s\"\n", vuln->klee_evidence);
|
||||
fprintf(json, " }%s\n", i < result->vuln_count - 1 ? "," : "");
|
||||
}
|
||||
fprintf(json, " ],\n");
|
||||
|
||||
// 性能指标
|
||||
fprintf(json, " \"performance_metrics\": {\n");
|
||||
fprintf(json, " \"klee_execution_time_ms\": %ld,\n", result->klee_analysis.execution_time);
|
||||
fprintf(json, " \"memory_usage_mb\": %ld,\n", result->klee_analysis.memory_usage);
|
||||
fprintf(json, " \"cpu_usage_percent\": %.2f,\n", result->klee_analysis.cpu_usage);
|
||||
fprintf(json, " \"total_instructions\": %d,\n", result->klee_analysis.total_instructions);
|
||||
fprintf(json, " \"completed_paths\": %d,\n", result->klee_analysis.completed_paths);
|
||||
fprintf(json, " \"partial_paths\": %d\n", result->klee_analysis.partial_paths);
|
||||
fprintf(json, " },\n");
|
||||
|
||||
// 代码质量
|
||||
fprintf(json, " \"code_quality\": {\n");
|
||||
fprintf(json, " \"cyclomatic_complexity\": %d,\n", result->quality_metrics.cyclomatic_complexity);
|
||||
fprintf(json, " \"function_count\": %d,\n", result->quality_metrics.function_count);
|
||||
fprintf(json, " \"avg_function_length\": %.2f,\n", result->quality_metrics.avg_function_length);
|
||||
fprintf(json, " \"comment_coverage\": %.2f,\n", result->quality_metrics.comment_coverage);
|
||||
fprintf(json, " \"code_duplication\": %.2f\n", result->quality_metrics.code_duplication);
|
||||
fprintf(json, " },\n");
|
||||
|
||||
// 安全评分
|
||||
int security_score = calculate_security_score(result);
|
||||
fprintf(json, " \"security_score\": {\n");
|
||||
fprintf(json, " \"overall_score\": %d,\n", security_score);
|
||||
fprintf(json, " \"risk_level\": \"%s\"\n", get_risk_level(security_score));
|
||||
fprintf(json, " }\n");
|
||||
|
||||
fprintf(json, "}\n");
|
||||
fclose(json);
|
||||
printf("增强JSON报告已生成: %s\n", output_file);
|
||||
}
|
||||
|
||||
// 辅助函数
|
||||
int count_klee_confirmed(AnalysisResult* result) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < result->vuln_count; i++) {
|
||||
if (result->vulnerabilities[i].confirmed_by_klee) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int calculate_security_score(AnalysisResult* result) {
|
||||
int score = 100;
|
||||
|
||||
// 根据漏洞数量和严重性扣分
|
||||
for (int i = 0; i < result->vuln_count; i++) {
|
||||
score -= result->vulnerabilities[i].severity * 10;
|
||||
}
|
||||
|
||||
// 根据覆盖率调整
|
||||
if (result->klee_analysis.coverage_rate < 50) {
|
||||
score -= 20;
|
||||
}
|
||||
|
||||
return max(0, score);
|
||||
}
|
||||
|
||||
const char* get_risk_level(int score) {
|
||||
if (score >= 80) return "低风险";
|
||||
if (score >= 60) return "中等风险";
|
||||
if (score >= 40) return "高风险";
|
||||
return "极高风险";
|
||||
}
|
||||
|
||||
void generate_repair_priority_html(AnalysisResult* result, FILE* html) {
|
||||
// 按严重性排序漏洞
|
||||
VulnerabilityInfo sorted_vulns[100]; // 使用固定大小
|
||||
memcpy(sorted_vulns, result->vulnerabilities, sizeof(VulnerabilityInfo) * result->vuln_count);
|
||||
|
||||
// 简单冒泡排序
|
||||
for (int i = 0; i < result->vuln_count - 1; i++) {
|
||||
for (int j = 0; j < result->vuln_count - i - 1; j++) {
|
||||
if (sorted_vulns[j].severity < sorted_vulns[j + 1].severity) {
|
||||
VulnerabilityInfo temp = sorted_vulns[j];
|
||||
sorted_vulns[j] = sorted_vulns[j + 1];
|
||||
sorted_vulns[j + 1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(html, "<ol>\n");
|
||||
for (int i = 0; i < result->vuln_count; i++) {
|
||||
const char* type_name = get_vulnerability_type_name(sorted_vulns[i].type);
|
||||
fprintf(html, "<li><strong>%s</strong> (严重性: %d) - %s</li>\n",
|
||||
type_name, sorted_vulns[i].severity, sorted_vulns[i].description);
|
||||
}
|
||||
fprintf(html, "</ol>\n");
|
||||
}
|
||||
|
||||
void generate_tool_recommendations_html(AnalysisResult* result, FILE* html) {
|
||||
fprintf(html, "<ul>\n");
|
||||
fprintf(html, "<li><strong>静态分析工具:</strong> cppcheck, clang-tidy, PVS-Studio</li>\n");
|
||||
fprintf(html, "<li><strong>动态分析工具:</strong> Valgrind, AddressSanitizer, ThreadSanitizer</li>\n");
|
||||
fprintf(html, "<li><strong>符号执行工具:</strong> KLEE, SAGE, DART</li>\n");
|
||||
fprintf(html, "<li><strong>模糊测试工具:</strong> AFL, libFuzzer, honggfuzz</li>\n");
|
||||
fprintf(html, "<li><strong>代码审查工具:</strong> SonarQube, CodeQL, Semgrep</li>\n");
|
||||
fprintf(html, "</ul>\n");
|
||||
}
|
||||
@ -0,0 +1,197 @@
|
||||
#include "intelligent_analyzer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
// 历史管理CLI工具
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("用法: %s <command> [options]\n", argv[0]);
|
||||
printf("命令:\n");
|
||||
printf(" list - 列出所有历史记录\n");
|
||||
printf(" search <hash|file> - 搜索历史记录\n");
|
||||
printf(" export <output.csv> - 导出历史记录到CSV\n");
|
||||
printf(" package <output.tar.gz> - 创建批量报告包\n");
|
||||
printf(" stats <output.txt> - 生成统计报告\n");
|
||||
printf(" cleanup <days> - 清理旧记录\n");
|
||||
printf(" archive <id> - 查看特定归档\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char* command = argv[1];
|
||||
|
||||
// 初始化历史管理器
|
||||
init_global_history_manager("output");
|
||||
|
||||
if (strcmp(command, "list") == 0) {
|
||||
list_history_records();
|
||||
} else if (strcmp(command, "search") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("请提供搜索参数 (hash 或 file)\n");
|
||||
return 1;
|
||||
}
|
||||
search_history_records(argv[2]);
|
||||
} else if (strcmp(command, "export") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("请提供输出文件名\n");
|
||||
return 1;
|
||||
}
|
||||
export_history_to_csv(g_history_manager, argv[2]);
|
||||
} else if (strcmp(command, "package") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("请提供输出文件名\n");
|
||||
return 1;
|
||||
}
|
||||
create_batch_report_package(g_history_manager, argv[2], NULL, NULL);
|
||||
} else if (strcmp(command, "stats") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("请提供输出文件名\n");
|
||||
return 1;
|
||||
}
|
||||
generate_history_statistics(g_history_manager, argv[2]);
|
||||
} else if (strcmp(command, "cleanup") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("请提供保留天数\n");
|
||||
return 1;
|
||||
}
|
||||
int days = atoi(argv[2]);
|
||||
cleanup_old_history(g_history_manager, days);
|
||||
} else if (strcmp(command, "archive") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("请提供归档ID\n");
|
||||
return 1;
|
||||
}
|
||||
show_archive_details(argv[2]);
|
||||
} else {
|
||||
printf("未知命令: %s\n", command);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cleanup_history_manager();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 列出所有历史记录
|
||||
void list_history_records() {
|
||||
if (!g_history_manager) {
|
||||
printf("历史管理器未初始化\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("=== 分析历史记录 ===\n");
|
||||
printf("总记录数: %d\n\n", g_history_manager->count);
|
||||
|
||||
for (int i = 0; i < g_history_manager->count; i++) {
|
||||
HistoryEntry* entry = &g_history_manager->entries[i];
|
||||
printf("记录 %d:\n", i + 1);
|
||||
printf(" 归档ID: %s\n", entry->archive_id);
|
||||
printf(" 时间戳: %s\n", entry->timestamp);
|
||||
printf(" 源文件: %s\n", entry->source_file);
|
||||
printf(" 文件哈希: %s\n", entry->file_hash);
|
||||
printf(" 漏洞数量: %d\n", entry->vuln_count);
|
||||
printf(" KLEE确认: %d\n", entry->klee_confirmed);
|
||||
printf(" 覆盖率: %.2f%%\n", entry->coverage_rate);
|
||||
printf(" 分析时间: %ld 毫秒\n", entry->analysis_time_ms);
|
||||
printf(" 归档路径: %s\n", entry->archive_path);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索历史记录
|
||||
void search_history_records(const char* query) {
|
||||
if (!g_history_manager) {
|
||||
printf("历史管理器未初始化\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("=== 搜索结果 ===\n");
|
||||
int found = 0;
|
||||
|
||||
for (int i = 0; i < g_history_manager->count; i++) {
|
||||
HistoryEntry* entry = &g_history_manager->entries[i];
|
||||
|
||||
// 按文件哈希搜索
|
||||
if (strstr(entry->file_hash, query) != NULL) {
|
||||
printf("匹配记录 (按哈希):\n");
|
||||
print_entry_details(entry);
|
||||
found++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 按文件名搜索
|
||||
if (strstr(entry->source_file, query) != NULL) {
|
||||
printf("匹配记录 (按文件名):\n");
|
||||
print_entry_details(entry);
|
||||
found++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 按归档ID搜索
|
||||
if (strstr(entry->archive_id, query) != NULL) {
|
||||
printf("匹配记录 (按归档ID):\n");
|
||||
print_entry_details(entry);
|
||||
found++;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
printf("未找到匹配的记录\n");
|
||||
} else {
|
||||
printf("找到 %d 条匹配记录\n", found);
|
||||
}
|
||||
}
|
||||
|
||||
// 打印记录详情
|
||||
void print_entry_details(HistoryEntry* entry) {
|
||||
printf(" 归档ID: %s\n", entry->archive_id);
|
||||
printf(" 时间戳: %s\n", entry->timestamp);
|
||||
printf(" 源文件: %s\n", entry->source_file);
|
||||
printf(" 文件哈希: %s\n", entry->file_hash);
|
||||
printf(" 漏洞数量: %d\n", entry->vuln_count);
|
||||
printf(" KLEE确认: %d\n", entry->klee_confirmed);
|
||||
printf(" 覆盖率: %.2f%%\n", entry->coverage_rate);
|
||||
printf(" 分析时间: %ld 毫秒\n", entry->analysis_time_ms);
|
||||
printf(" 归档路径: %s\n", entry->archive_path);
|
||||
printf(" 报告文件:\n");
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (access(entry->report_paths[i], F_OK) == 0) {
|
||||
printf(" - %s\n", entry->report_paths[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// 显示归档详情
|
||||
void show_archive_details(const char* archive_id) {
|
||||
if (!g_history_manager) {
|
||||
printf("历史管理器未初始化\n");
|
||||
return;
|
||||
}
|
||||
|
||||
HistoryEntry* entry = NULL;
|
||||
for (int i = 0; i < g_history_manager->count; i++) {
|
||||
if (strcmp(g_history_manager->entries[i].archive_id, archive_id) == 0) {
|
||||
entry = &g_history_manager->entries[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
printf("未找到归档ID: %s\n", archive_id);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("=== 归档详情 ===\n");
|
||||
print_entry_details(entry);
|
||||
|
||||
// 检查归档文件是否存在
|
||||
if (access(entry->archive_path, F_OK) == 0) {
|
||||
struct stat st;
|
||||
stat(entry->archive_path, &st);
|
||||
printf("归档文件大小: %ld 字节\n", st.st_size);
|
||||
printf("归档文件修改时间: %s\n", ctime(&st.st_mtime));
|
||||
} else {
|
||||
printf("归档文件不存在: %s\n", entry->archive_path);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,174 @@
|
||||
#include "intelligent_analyzer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// KLEE参数优化配置
|
||||
typedef struct {
|
||||
char name[50];
|
||||
int max_time;
|
||||
int max_memory;
|
||||
int max_instructions;
|
||||
int max_solver_time;
|
||||
int max_forks;
|
||||
int max_stack_frames;
|
||||
int max_sym_array_size;
|
||||
int batch_instructions;
|
||||
char search_strategy[20];
|
||||
bool use_merge;
|
||||
bool use_batching;
|
||||
bool use_optimize;
|
||||
bool use_independent_solver;
|
||||
} KLEEConfig;
|
||||
|
||||
// 预定义的KLEE配置
|
||||
static KLEEConfig klee_configs[] = {
|
||||
{
|
||||
"fast", // 快速模式
|
||||
300, // 5分钟
|
||||
16384, // 16GB
|
||||
5000000, // 500万指令
|
||||
60, // 1分钟求解时间
|
||||
500, // 500个分支
|
||||
30, // 30层栈
|
||||
500, // 500字节符号数组
|
||||
200, // 200指令批处理
|
||||
"dfs", // 深度优先搜索
|
||||
true, // 使用合并
|
||||
true, // 使用批处理
|
||||
true, // 使用优化
|
||||
true // 使用独立求解器
|
||||
},
|
||||
{
|
||||
"balanced", // 平衡模式
|
||||
1200, // 20分钟 - 增加时间
|
||||
65536, // 64GB - 增加内存
|
||||
20000000, // 2000万指令 - 增加指令数
|
||||
300, // 5分钟求解时间 - 增加求解时间
|
||||
2000, // 2000个分支 - 增加分支数
|
||||
100, // 100层栈 - 增加栈深度
|
||||
2000, // 2000字节符号数组 - 增加数组大小
|
||||
1000, // 1000指令批处理 - 增加批处理
|
||||
"nurs:covnew", // 覆盖率优先搜索 - 更好的搜索策略
|
||||
true, // 使用合并
|
||||
true, // 使用批处理
|
||||
true, // 使用优化
|
||||
true // 使用独立求解器
|
||||
},
|
||||
{
|
||||
"thorough", // 彻底模式
|
||||
1200, // 20分钟
|
||||
65536, // 64GB
|
||||
50000000, // 5000万指令
|
||||
300, // 5分钟求解时间
|
||||
2000, // 2000个分支
|
||||
100, // 100层栈
|
||||
2000, // 2000字节符号数组
|
||||
1000, // 1000指令批处理
|
||||
"nurs:icnt", // 指令计数NURS
|
||||
true, // 使用合并
|
||||
true, // 使用批处理
|
||||
true, // 使用优化
|
||||
true // 使用独立求解器
|
||||
}
|
||||
};
|
||||
|
||||
// 根据文件大小和复杂度选择最佳配置
|
||||
KLEEConfig* select_optimal_config(const char* source_file) {
|
||||
FILE* file = fopen(source_file, "r");
|
||||
if (!file) return &klee_configs[1]; // 默认平衡模式
|
||||
|
||||
int line_count = 0;
|
||||
int function_count = 0;
|
||||
int complexity_score = 0;
|
||||
char line[1024];
|
||||
|
||||
while (fgets(line, sizeof(line), file)) {
|
||||
line_count++;
|
||||
|
||||
// 计算函数数量
|
||||
if (strstr(line, "int ") && strstr(line, "(")) function_count++;
|
||||
if (strstr(line, "void ") && strstr(line, "(")) function_count++;
|
||||
if (strstr(line, "char ") && strstr(line, "(")) function_count++;
|
||||
|
||||
// 计算复杂度分数
|
||||
if (strstr(line, "if ")) complexity_score += 2;
|
||||
if (strstr(line, "while ")) complexity_score += 3;
|
||||
if (strstr(line, "for ")) complexity_score += 3;
|
||||
if (strstr(line, "switch ")) complexity_score += 4;
|
||||
if (strstr(line, "malloc")) complexity_score += 2;
|
||||
if (strstr(line, "free")) complexity_score += 2;
|
||||
if (strstr(line, "printf")) complexity_score += 1;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// 根据文件特征选择配置
|
||||
if (line_count < 100 && function_count < 5 && complexity_score < 20) {
|
||||
return &klee_configs[0]; // 快速模式
|
||||
} else if (line_count < 500 && function_count < 15 && complexity_score < 50) {
|
||||
return &klee_configs[1]; // 平衡模式
|
||||
} else {
|
||||
return &klee_configs[2]; // 彻底模式
|
||||
}
|
||||
}
|
||||
|
||||
// 生成优化的KLEE命令
|
||||
void generate_optimized_klee_command(char* command, size_t size,
|
||||
const char* bitcode_file,
|
||||
const char* output_dir,
|
||||
bool has_posix_runtime) {
|
||||
KLEEConfig* config = select_optimal_config(bitcode_file);
|
||||
|
||||
if (has_posix_runtime) {
|
||||
snprintf(command, size,
|
||||
"klee --posix-runtime --output-dir=%s "
|
||||
"--max-time=%d --max-memory=%d --max-instructions=%d "
|
||||
"--max-solver-time=%d --max-forks=%d --max-stack-frames=%d "
|
||||
"--max-sym-array-size=%d --batch-instructions=%d "
|
||||
"--search=%s --rng-seed=%d %s %s %s %s %s",
|
||||
output_dir,
|
||||
config->max_time,
|
||||
config->max_memory,
|
||||
config->max_instructions,
|
||||
config->max_solver_time,
|
||||
config->max_forks,
|
||||
config->max_stack_frames,
|
||||
config->max_sym_array_size,
|
||||
config->batch_instructions,
|
||||
config->search_strategy,
|
||||
rand() % 1000,
|
||||
config->use_merge ? "--use-merge" : "",
|
||||
config->use_batching ? "--use-batching-search" : "",
|
||||
config->use_optimize ? "--optimize" : "",
|
||||
config->use_independent_solver ? "--use-independent-solver" : "",
|
||||
bitcode_file);
|
||||
} else {
|
||||
snprintf(command, size,
|
||||
"klee --output-dir=%s "
|
||||
"--max-time=%d --max-memory=%d --max-instructions=%d "
|
||||
"--max-solver-time=%d --max-forks=%d --max-stack-frames=%d "
|
||||
"--max-sym-array-size=%d --batch-instructions=%d "
|
||||
"--search=%s --rng-seed=%d %s %s %s %s %s",
|
||||
output_dir,
|
||||
config->max_time,
|
||||
config->max_memory,
|
||||
config->max_instructions,
|
||||
config->max_solver_time,
|
||||
config->max_forks,
|
||||
config->max_stack_frames,
|
||||
config->max_sym_array_size,
|
||||
config->batch_instructions,
|
||||
config->search_strategy,
|
||||
rand() % 1000,
|
||||
config->use_merge ? "--use-merge" : "",
|
||||
config->use_batching ? "--use-batching-search" : "",
|
||||
config->use_optimize ? "--optimize" : "",
|
||||
config->use_independent_solver ? "--use-independent-solver" : "",
|
||||
bitcode_file);
|
||||
}
|
||||
|
||||
printf("选择KLEE配置: %s\n", config->name);
|
||||
printf("参数: 时间=%ds, 内存=%dMB, 指令=%d, 分支=%d\n",
|
||||
config->max_time, config->max_memory/1024,
|
||||
config->max_instructions, config->max_forks);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,20 +1,19 @@
|
||||
klee --output-dir=klee_output --max-time=1200 --max-memory=65536 --max-instructions=50000000 --max-solver-time=300 --use-merge --use-batching-search --batch-instructions=1000 --search=random-path --rng-seed=608 --optimize --disable-inlining --max-forks=2000 --max-stack-frames=100 --max-sym-array-size=2000 --use-independent-solver advanced_test.c.bc
|
||||
PID: 853
|
||||
klee --posix-runtime --output-dir=klee_output --max-time=1200 --max-memory=65536 --max-instructions=20000000 --max-solver-time=300 --max-forks=2000 --max-stack-frames=100 --max-sym-array-size=2000 --batch-instructions=1000 --search=nurs:covnew --rng-seed=773 --use-merge --use-batching-search --optimize --use-independent-solver comprehensive_vulnerability_test.c.bc
|
||||
PID: 9252
|
||||
Using monotonic steady clock with 1/1000000000s resolution
|
||||
Started: 2025-10-16 14:43:30
|
||||
Started: 2025-10-28 14:59:09
|
||||
BEGIN searcher description
|
||||
MergingSearcher
|
||||
END searcher description
|
||||
Finished: 2025-10-16 14:43:31
|
||||
Elapsed: 00:00:01
|
||||
KLEE: done: explored paths = 24
|
||||
KLEE: done: avg. constructs per query = 47
|
||||
KLEE: done: total queries = 48
|
||||
Finished: 2025-10-28 14:59:09
|
||||
Elapsed: 00:00:00
|
||||
KLEE: done: explored paths = 1
|
||||
KLEE: done: total queries = 0
|
||||
KLEE: done: valid queries = 0
|
||||
KLEE: done: invalid queries = 48
|
||||
KLEE: done: query cex = 48
|
||||
KLEE: done: invalid queries = 0
|
||||
KLEE: done: query cex = 0
|
||||
|
||||
KLEE: done: total instructions = 434
|
||||
KLEE: done: total instructions = 2817
|
||||
KLEE: done: completed paths = 0
|
||||
KLEE: done: partially completed paths = 24
|
||||
KLEE: done: partially completed paths = 1
|
||||
KLEE: done: generated tests = 1
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
KLEE: Using Z3 solver backend
|
||||
KLEE: Deterministic allocator: Using quarantine queue size 8
|
||||
KLEE: Deterministic allocator: globals (start-address=0x758fac200000 size=10 GiB)
|
||||
KLEE: Deterministic allocator: constants (start-address=0x758d2c200000 size=10 GiB)
|
||||
KLEE: Deterministic allocator: heap (start-address=0x748d2c200000 size=1024 GiB)
|
||||
KLEE: Deterministic allocator: stack (start-address=0x746d2c200000 size=128 GiB)
|
||||
KLEE: ERROR: advanced_test.c:66: external call with symbolic argument: printf
|
||||
KLEE: Deterministic allocator: globals (start-address=0x7914c2a00000 size=10 GiB)
|
||||
KLEE: Deterministic allocator: constants (start-address=0x791242a00000 size=10 GiB)
|
||||
KLEE: Deterministic allocator: heap (start-address=0x781242a00000 size=1024 GiB)
|
||||
KLEE: Deterministic allocator: stack (start-address=0x77f242a00000 size=128 GiB)
|
||||
KLEE: ERROR: comprehensive_vulnerability_test.c:178: memory error: out of bound pointer
|
||||
KLEE: NOTE: now ignoring this error at this location
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,12 +1 @@
|
||||
array a[4] : w32 -> w8 = symbolic
|
||||
array b[4] : w32 -> w8 = symbolic
|
||||
array c[4] : w32 -> w8 = symbolic
|
||||
(query [(Slt 0
|
||||
N0:(ReadLSB w32 0 a))
|
||||
(Slt 0
|
||||
N1:(ReadLSB w32 0 b))
|
||||
(Slt 0
|
||||
N2:(ReadLSB w32 0 c))
|
||||
(Slt 100
|
||||
(Add w32 (Add w32 N0 N1) N2))]
|
||||
false)
|
||||
(query [] false)
|
||||
|
||||
Binary file not shown.
@ -0,0 +1,13 @@
|
||||
Error: memory error: out of bound pointer
|
||||
File: comprehensive_vulnerability_test.c
|
||||
Line: 178
|
||||
assembly.ll line: 981
|
||||
State: 1
|
||||
Stack:
|
||||
#000000981 in test_buffer_overflow_vulnerabilities() at comprehensive_vulnerability_test.c:178
|
||||
#100000875 in __klee_posix_wrapped_main(1, 132260340695040) at comprehensive_vulnerability_test.c:93
|
||||
#200000828 in main(1, 133138124636160, 133138124636176) at runtime/POSIX/klee_init_env.c:244
|
||||
Info:
|
||||
address: 131918890795028
|
||||
next: object at 131892047249408 of size 4
|
||||
MO382[4] allocated at __klee_posix_wrapped_main(): %4 = alloca i32, align 4
|
||||
@ -1,2 +1,28 @@
|
||||
KLEE: WARNING: undefined reference to function: atoi
|
||||
KLEE: WARNING: undefined reference to function: fclose
|
||||
KLEE: WARNING: undefined reference to function: fgets
|
||||
KLEE: WARNING: undefined reference to function: fopen
|
||||
KLEE: WARNING: undefined reference to function: fprintf
|
||||
KLEE: WARNING: undefined reference to function: gets
|
||||
KLEE: WARNING: undefined reference to function: printf
|
||||
KLEE: WARNING: undefined reference to function: pthread_create
|
||||
KLEE: WARNING: undefined reference to function: pthread_join
|
||||
KLEE: WARNING: undefined reference to function: pthread_mutex_lock
|
||||
KLEE: WARNING: undefined reference to function: pthread_mutex_unlock
|
||||
KLEE: WARNING: undefined reference to function: pthread_self
|
||||
KLEE: WARNING: undefined reference to function: rand
|
||||
KLEE: WARNING: undefined reference to function: signal
|
||||
KLEE: WARNING: undefined reference to function: snprintf
|
||||
KLEE: WARNING: undefined reference to function: sprintf
|
||||
KLEE: WARNING: undefined reference to function: srand
|
||||
KLEE: WARNING: undefined reference to function: strcat
|
||||
KLEE: WARNING: undefined reference to function: strcpy
|
||||
KLEE: WARNING: undefined reference to function: strlen
|
||||
KLEE: WARNING: undefined reference to function: strncmp
|
||||
KLEE: WARNING ONCE: Alignment of memory from call "malloc" is not modelled. Using alignment of 8.
|
||||
KLEE: WARNING ONCE: calling external: syscall(4, 133121347420160, 131938218147840) at runtime/POSIX/fd.c:530 5
|
||||
KLEE: WARNING ONCE: calling external: printf(133125709496320) at comprehensive_vulnerability_test.c:78 5
|
||||
KLEE: WARNING ONCE: calling external: signal(2, 133122521825280) at comprehensive_vulnerability_test.c:82 5
|
||||
KLEE: WARNING ONCE: calling external: strcpy(131912448344064, 131936070664192) at comprehensive_vulnerability_test.c:168 10
|
||||
KLEE: WARNING ONCE: calling external: strcat(131921038278656, 133125306843136) at comprehensive_vulnerability_test.c:172 10
|
||||
KLEE: WARNING ONCE: calling external: sprintf(131910300860416, 133123595567104, 131936070664192) at comprehensive_vulnerability_test.c:176 9
|
||||
|
||||
Binary file not shown.
@ -0,0 +1,25 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"total_entries": 1,
|
||||
"last_updated": "2025-10-28 14:59:09",
|
||||
"entries": [
|
||||
{
|
||||
"archive_id": "analysis_1761634749_0",
|
||||
"timestamp": "2025-10-28_14-59-09",
|
||||
"source_file": "comprehensive_vulnerability_test.c",
|
||||
"file_hash": "21207_1761036648",
|
||||
"vuln_count": 100,
|
||||
"klee_confirmed": 0,
|
||||
"coverage_rate": 42.00,
|
||||
"analysis_time_ms": 536,
|
||||
"reports": {
|
||||
"html": "output/reports/analysis_1761634749_0_static_analysis_report.html",
|
||||
"json": "output/reports/analysis_1761634749_0_static_analysis_report.json",
|
||||
"txt": "output/reports/analysis_1761634749_0_static_analysis_report.txt",
|
||||
"enhanced_html": "output/reports/analysis_1761634749_0_enhanced_analysis_report.html",
|
||||
"enhanced_json": "output/reports/analysis_1761634749_0_enhanced_analysis_report.json"
|
||||
},
|
||||
"archive_path": "output/archives/analysis_1761634749_0_archive.tar.gz"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,422 @@
|
||||
#include "intelligent_analyzer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
// 分析任务结构
|
||||
typedef struct {
|
||||
char source_file[512];
|
||||
char output_dir[512];
|
||||
int priority;
|
||||
time_t created_time;
|
||||
int task_id;
|
||||
AnalysisResult* result;
|
||||
int status; // 0=pending, 1=running, 2=completed, 3=failed
|
||||
pthread_t thread_id;
|
||||
} AnalysisTask;
|
||||
|
||||
// ResourceLimits 结构体已在头文件中定义
|
||||
|
||||
// 分析队列管理器
|
||||
typedef struct {
|
||||
AnalysisTask* tasks;
|
||||
int task_count;
|
||||
int max_tasks;
|
||||
int head;
|
||||
int tail;
|
||||
pthread_mutex_t queue_mutex;
|
||||
sem_t task_semaphore;
|
||||
sem_t resource_semaphore;
|
||||
ResourceLimits limits;
|
||||
int running_tasks;
|
||||
int completed_tasks;
|
||||
int failed_tasks;
|
||||
time_t start_time;
|
||||
char log_file[512];
|
||||
} ParallelAnalyzer;
|
||||
|
||||
// 全局分析器实例
|
||||
static ParallelAnalyzer* g_analyzer = NULL;
|
||||
|
||||
// 初始化资源限制
|
||||
void init_resource_limits(ResourceLimits* limits) {
|
||||
limits->max_memory_mb = 2048; // 2GB
|
||||
limits->max_cpu_cores = 4; // 4个CPU核心
|
||||
limits->max_concurrent_tasks = 4; // 4个并发任务
|
||||
}
|
||||
|
||||
// 初始化并行分析器
|
||||
int init_parallel_analyzer(int max_tasks, const ResourceLimits* limits) {
|
||||
if (g_analyzer) {
|
||||
printf("警告: 分析器已初始化\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_analyzer = malloc(sizeof(ParallelAnalyzer));
|
||||
if (!g_analyzer) return -1;
|
||||
|
||||
memset(g_analyzer, 0, sizeof(ParallelAnalyzer));
|
||||
g_analyzer->max_tasks = max_tasks;
|
||||
g_analyzer->tasks = malloc(sizeof(AnalysisTask) * max_tasks);
|
||||
|
||||
if (!g_analyzer->tasks) {
|
||||
free(g_analyzer);
|
||||
g_analyzer = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 初始化互斥锁和信号量
|
||||
pthread_mutex_init(&g_analyzer->queue_mutex, NULL);
|
||||
sem_init(&g_analyzer->task_semaphore, 0, 0);
|
||||
sem_init(&g_analyzer->resource_semaphore, 0, limits->max_concurrent_tasks);
|
||||
|
||||
// 设置资源限制
|
||||
g_analyzer->limits = *limits;
|
||||
g_analyzer->start_time = time(NULL);
|
||||
|
||||
// 设置日志文件
|
||||
snprintf(g_analyzer->log_file, sizeof(g_analyzer->log_file),
|
||||
"output/parallel_analysis_%ld.log", g_analyzer->start_time);
|
||||
|
||||
printf("并行分析器初始化完成: 最大任务数=%d, 并发数=%d\n",
|
||||
max_tasks, limits->max_concurrent_tasks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 检查系统资源
|
||||
int check_system_resources() {
|
||||
if (!g_analyzer) return -1;
|
||||
|
||||
// 检查内存使用
|
||||
FILE* meminfo = fopen("/proc/meminfo", "r");
|
||||
if (meminfo) {
|
||||
char line[256];
|
||||
long total_mem = 0, free_mem = 0;
|
||||
|
||||
while (fgets(line, sizeof(line), meminfo)) {
|
||||
if (sscanf(line, "MemTotal: %ld kB", &total_mem) == 1) {
|
||||
// 转换为MB
|
||||
total_mem /= 1024;
|
||||
} else if (sscanf(line, "MemAvailable: %ld kB", &free_mem) == 1) {
|
||||
free_mem /= 1024;
|
||||
}
|
||||
}
|
||||
fclose(meminfo);
|
||||
|
||||
if (free_mem < g_analyzer->limits.max_memory_mb) {
|
||||
printf("警告: 可用内存不足 (%ldMB < %ldMB)\n",
|
||||
free_mem, g_analyzer->limits.max_memory_mb);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 添加分析任务到队列
|
||||
int add_analysis_task(const char* source_file, int priority) {
|
||||
if (!g_analyzer) return -1;
|
||||
|
||||
pthread_mutex_lock(&g_analyzer->queue_mutex);
|
||||
|
||||
if (g_analyzer->task_count >= g_analyzer->max_tasks) {
|
||||
pthread_mutex_unlock(&g_analyzer->queue_mutex);
|
||||
printf("错误: 任务队列已满\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
AnalysisTask* task = &g_analyzer->tasks[g_analyzer->task_count];
|
||||
strncpy(task->source_file, source_file, sizeof(task->source_file) - 1);
|
||||
task->source_file[sizeof(task->source_file) - 1] = '\0';
|
||||
|
||||
snprintf(task->output_dir, sizeof(task->output_dir),
|
||||
"output/task_%d_%ld", g_analyzer->task_count, time(NULL));
|
||||
|
||||
task->priority = priority;
|
||||
task->created_time = time(NULL);
|
||||
task->task_id = g_analyzer->task_count;
|
||||
task->status = 0; // pending
|
||||
task->result = NULL;
|
||||
|
||||
g_analyzer->task_count++;
|
||||
g_analyzer->tail = (g_analyzer->tail + 1) % g_analyzer->max_tasks;
|
||||
|
||||
pthread_mutex_unlock(&g_analyzer->queue_mutex);
|
||||
|
||||
// 释放任务信号量
|
||||
sem_post(&g_analyzer->task_semaphore);
|
||||
|
||||
printf("任务已添加到队列: %s (优先级: %d)\n", source_file, priority);
|
||||
return task->task_id;
|
||||
}
|
||||
|
||||
// 获取下一个待处理任务
|
||||
AnalysisTask* get_next_task() {
|
||||
if (!g_analyzer) return NULL;
|
||||
|
||||
pthread_mutex_lock(&g_analyzer->queue_mutex);
|
||||
|
||||
for (int i = 0; i < g_analyzer->task_count; i++) {
|
||||
AnalysisTask* task = &g_analyzer->tasks[i];
|
||||
if (task->status == 0) { // pending
|
||||
task->status = 1; // running
|
||||
g_analyzer->running_tasks++;
|
||||
pthread_mutex_unlock(&g_analyzer->queue_mutex);
|
||||
return task;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&g_analyzer->queue_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 执行单个分析任务
|
||||
void* execute_analysis_task(void* arg) {
|
||||
AnalysisTask* task = (AnalysisTask*)arg;
|
||||
|
||||
printf("开始执行任务 %d: %s\n", task->task_id, task->source_file);
|
||||
|
||||
// 创建输出目录
|
||||
char mkdir_cmd[1024];
|
||||
snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p %s", task->output_dir);
|
||||
system(mkdir_cmd);
|
||||
|
||||
// 分配结果结构
|
||||
task->result = malloc(sizeof(AnalysisResult));
|
||||
if (!task->result) {
|
||||
task->status = 3; // failed
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 执行分析
|
||||
task->result = analyze_code_with_klee(task->source_file);
|
||||
|
||||
if (task->result) {
|
||||
task->status = 2; // completed
|
||||
printf("任务 %d 完成: %s\n", task->task_id, task->source_file);
|
||||
} else {
|
||||
task->status = 3; // failed
|
||||
printf("任务 %d 失败: %s\n", task->task_id, task->source_file);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 工作线程函数
|
||||
void* worker_thread(void* arg) {
|
||||
(void)arg; // 未使用参数
|
||||
|
||||
while (1) {
|
||||
// 等待任务信号量
|
||||
sem_wait(&g_analyzer->task_semaphore);
|
||||
|
||||
// 等待资源信号量
|
||||
sem_wait(&g_analyzer->resource_semaphore);
|
||||
|
||||
// 检查系统资源
|
||||
if (check_system_resources() != 0) {
|
||||
sem_post(&g_analyzer->resource_semaphore);
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取下一个任务
|
||||
AnalysisTask* task = get_next_task();
|
||||
if (!task) {
|
||||
sem_post(&g_analyzer->resource_semaphore);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 执行任务
|
||||
execute_analysis_task(task);
|
||||
|
||||
// 释放资源
|
||||
sem_post(&g_analyzer->resource_semaphore);
|
||||
|
||||
// 更新统计
|
||||
pthread_mutex_lock(&g_analyzer->queue_mutex);
|
||||
if (task->status == 2) {
|
||||
g_analyzer->completed_tasks++;
|
||||
} else if (task->status == 3) {
|
||||
g_analyzer->failed_tasks++;
|
||||
}
|
||||
g_analyzer->running_tasks--;
|
||||
pthread_mutex_unlock(&g_analyzer->queue_mutex);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 启动并行分析
|
||||
int start_parallel_analysis(int num_workers) {
|
||||
if (!g_analyzer) return -1;
|
||||
|
||||
printf("启动并行分析: %d 个工作线程\n", num_workers);
|
||||
|
||||
// 创建工作线程
|
||||
pthread_t* workers = malloc(sizeof(pthread_t) * num_workers);
|
||||
if (!workers) return -1;
|
||||
|
||||
for (int i = 0; i < num_workers; i++) {
|
||||
if (pthread_create(&workers[i], NULL, worker_thread, NULL) != 0) {
|
||||
printf("错误: 无法创建工作线程 %d\n", i);
|
||||
free(workers);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 等待所有任务完成
|
||||
int all_completed = 0;
|
||||
while (!all_completed) {
|
||||
pthread_mutex_lock(&g_analyzer->queue_mutex);
|
||||
|
||||
int pending = 0;
|
||||
for (int i = 0; i < g_analyzer->task_count; i++) {
|
||||
if (g_analyzer->tasks[i].status == 0 || g_analyzer->tasks[i].status == 1) {
|
||||
pending = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
all_completed = !pending;
|
||||
pthread_mutex_unlock(&g_analyzer->queue_mutex);
|
||||
|
||||
if (!all_completed) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 等待工作线程结束
|
||||
for (int i = 0; i < num_workers; i++) {
|
||||
pthread_cancel(workers[i]);
|
||||
pthread_join(workers[i], NULL);
|
||||
}
|
||||
|
||||
free(workers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取分析统计
|
||||
void get_analysis_statistics(int* total, int* completed, int* failed, int* running) {
|
||||
if (!g_analyzer) {
|
||||
*total = *completed = *failed = *running = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&g_analyzer->queue_mutex);
|
||||
*total = g_analyzer->task_count;
|
||||
*completed = g_analyzer->completed_tasks;
|
||||
*failed = g_analyzer->failed_tasks;
|
||||
*running = g_analyzer->running_tasks;
|
||||
pthread_mutex_unlock(&g_analyzer->queue_mutex);
|
||||
}
|
||||
|
||||
// 生成批量分析报告
|
||||
void generate_batch_analysis_report(const char* output_file) {
|
||||
if (!g_analyzer) return;
|
||||
|
||||
FILE* file = fopen(output_file, "w");
|
||||
if (!file) return;
|
||||
|
||||
fprintf(file,
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
" <title>批量分析报告</title>\n"
|
||||
" <style>\n"
|
||||
" body { font-family: Arial, sans-serif; margin: 20px; }\n"
|
||||
" .summary { background: #f5f5f5; padding: 15px; border-radius: 5px; margin: 20px 0; }\n"
|
||||
" .task-list { margin: 20px 0; }\n"
|
||||
" .task-item { border: 1px solid #ddd; padding: 10px; margin: 5px 0; border-radius: 3px; }\n"
|
||||
" .status-completed { background: #d4edda; }\n"
|
||||
" .status-failed { background: #f8d7da; }\n"
|
||||
" .status-running { background: #fff3cd; }\n"
|
||||
" </style>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
" <h1>批量分析报告</h1>\n"
|
||||
" \n"
|
||||
" <div class=\"summary\">\n"
|
||||
" <h2>分析摘要</h2>\n"
|
||||
" <p>总任务数: %d</p>\n"
|
||||
" <p>已完成: %d</p>\n"
|
||||
" <p>失败: %d</p>\n"
|
||||
" <p>运行中: %d</p>\n"
|
||||
" <p>成功率: %.2f%%</p>\n"
|
||||
" </div>\n"
|
||||
" \n"
|
||||
" <div class=\"task-list\">\n"
|
||||
" <h2>任务详情</h2>\n",
|
||||
g_analyzer->task_count,
|
||||
g_analyzer->completed_tasks,
|
||||
g_analyzer->failed_tasks,
|
||||
g_analyzer->running_tasks,
|
||||
(double)g_analyzer->completed_tasks / g_analyzer->task_count * 100.0
|
||||
);
|
||||
|
||||
// 添加任务详情
|
||||
for (int i = 0; i < g_analyzer->task_count; i++) {
|
||||
AnalysisTask* task = &g_analyzer->tasks[i];
|
||||
const char* status_class = "";
|
||||
const char* status_text = "";
|
||||
|
||||
switch (task->status) {
|
||||
case 0: status_class = ""; status_text = "等待中"; break;
|
||||
case 1: status_class = "status-running"; status_text = "运行中"; break;
|
||||
case 2: status_class = "status-completed"; status_text = "已完成"; break;
|
||||
case 3: status_class = "status-failed"; status_text = "失败"; break;
|
||||
}
|
||||
|
||||
fprintf(file,
|
||||
" <div class=\"task-item %s\">\n"
|
||||
" <h3>任务 %d: %s</h3>\n"
|
||||
" <p>状态: %s</p>\n"
|
||||
" <p>优先级: %d</p>\n"
|
||||
" <p>创建时间: %s</p>\n"
|
||||
" </div>\n",
|
||||
status_class,
|
||||
task->task_id,
|
||||
task->source_file,
|
||||
status_text,
|
||||
task->priority,
|
||||
ctime(&task->created_time)
|
||||
);
|
||||
}
|
||||
|
||||
fprintf(file,
|
||||
" </div>\n"
|
||||
"</body>\n"
|
||||
"</html>\n"
|
||||
);
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// 清理并行分析器
|
||||
void cleanup_parallel_analyzer() {
|
||||
if (!g_analyzer) return;
|
||||
|
||||
// 清理任务结果
|
||||
for (int i = 0; i < g_analyzer->task_count; i++) {
|
||||
if (g_analyzer->tasks[i].result) {
|
||||
free(g_analyzer->tasks[i].result);
|
||||
}
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
if (g_analyzer->tasks) {
|
||||
free(g_analyzer->tasks);
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&g_analyzer->queue_mutex);
|
||||
sem_destroy(&g_analyzer->task_semaphore);
|
||||
sem_destroy(&g_analyzer->resource_semaphore);
|
||||
|
||||
free(g_analyzer);
|
||||
g_analyzer = NULL;
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// 测试整数溢出
|
||||
int test_integer_overflow() {
|
||||
int a = 2147483647; // INT_MAX
|
||||
int b = a + 1; // 整数溢出
|
||||
return b;
|
||||
}
|
||||
|
||||
// 测试双重释放
|
||||
void test_double_free() {
|
||||
int* ptr = malloc(sizeof(int));
|
||||
free(ptr);
|
||||
free(ptr); // 双重释放
|
||||
}
|
||||
|
||||
// 测试竞态条件
|
||||
int global_counter = 0;
|
||||
void* increment_counter(void* arg) {
|
||||
global_counter++; // 竞态条件
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 测试格式化字符串漏洞
|
||||
void test_format_string(char* user_input) {
|
||||
printf("%s", user_input); // 修复格式化字符串漏洞
|
||||
}
|
||||
|
||||
// 测试内存对齐问题
|
||||
void test_alignment_issue() {
|
||||
char* ptr = malloc(100);
|
||||
int* int_ptr = (int*)ptr; // 可能的内存对齐问题
|
||||
*int_ptr = 42;
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
// 测试类型混淆
|
||||
void test_type_confusion() {
|
||||
int value = 42;
|
||||
char* ptr = (char*)&value; // 类型强制转换
|
||||
printf("Value: %s\n", ptr);
|
||||
}
|
||||
|
||||
// 测试高级内存管理
|
||||
void test_advanced_memory() {
|
||||
char buffer[10];
|
||||
strcpy(buffer, "This is a very long string that will overflow"); // 缓冲区溢出
|
||||
|
||||
// 使用alloca可能导致栈溢出
|
||||
char* stack_ptr = alloca(1000000);
|
||||
strcpy(stack_ptr, "Large allocation on stack");
|
||||
}
|
||||
|
||||
// 测试并发安全问题
|
||||
volatile int shared_var = 0;
|
||||
void test_concurrency_issue() {
|
||||
shared_var = shared_var + 1; // volatile变量竞态
|
||||
}
|
||||
|
||||
// 测试信号安全问题
|
||||
void signal_handler(int sig) {
|
||||
printf("Signal received: %d\n", sig); // 信号处理函数中的不安全操作
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("=== 扩展规则库测试程序 ===\n");
|
||||
|
||||
// 测试各种漏洞类型
|
||||
test_integer_overflow();
|
||||
test_double_free();
|
||||
test_format_string("User input: %s");
|
||||
test_alignment_issue();
|
||||
test_type_confusion();
|
||||
test_advanced_memory();
|
||||
test_concurrency_issue();
|
||||
|
||||
// 设置信号处理
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
// 测试多线程竞态条件
|
||||
pthread_t threads[5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
pthread_create(&threads[i], NULL, increment_counter, NULL);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
printf("Global counter: %d\n", global_counter);
|
||||
printf("测试完成\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,26 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// 简单的测试文件,避免复杂功能
|
||||
int main() {
|
||||
printf("=== 简单规则库测试 ===\n");
|
||||
|
||||
// 测试整数溢出
|
||||
int a = 2147483647;
|
||||
int b = a + 1; // 整数溢出
|
||||
|
||||
// 测试内存泄漏
|
||||
char* ptr = malloc(100);
|
||||
// 忘记释放内存
|
||||
|
||||
// 测试缓冲区溢出
|
||||
char buffer[10];
|
||||
strcpy(buffer, "This is a very long string"); // 缓冲区溢出
|
||||
|
||||
// 测试空指针解引用
|
||||
char* null_ptr = NULL;
|
||||
// *null_ptr = 'a'; // 空指针解引用(注释掉避免崩溃)
|
||||
|
||||
printf("测试完成\n");
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "intelligent_analyzer.h"
|
||||
|
||||
// 简化的测试程序,验证内存分配修复
|
||||
int main() {
|
||||
printf("=== 测试内存分配修复 ===\n");
|
||||
|
||||
// 创建测试用的漏洞数组
|
||||
VulnerabilityInfo vulnerabilities[10];
|
||||
int max_vulns = 10;
|
||||
|
||||
// 测试简化规则库
|
||||
printf("测试简化规则库漏洞检测...\n");
|
||||
int vuln_count = detect_vulnerabilities_simple("test_file.c", vulnerabilities, max_vulns);
|
||||
|
||||
printf("检测到 %d 个漏洞\n", vuln_count);
|
||||
|
||||
// 清理内存
|
||||
for (int i = 0; i < vuln_count; i++) {
|
||||
if (vulnerabilities[i].file_path) free(vulnerabilities[i].file_path);
|
||||
if (vulnerabilities[i].code_line) free(vulnerabilities[i].code_line);
|
||||
if (vulnerabilities[i].description) free(vulnerabilities[i].description);
|
||||
if (vulnerabilities[i].fix_suggestion) free(vulnerabilities[i].fix_suggestion);
|
||||
if (vulnerabilities[i].test_case) free(vulnerabilities[i].test_case);
|
||||
if (vulnerabilities[i].klee_evidence) free(vulnerabilities[i].klee_evidence);
|
||||
}
|
||||
|
||||
printf("测试完成,没有段错误!\n");
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
#include "intelligent_analyzer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// 简化的测试程序,用于验证修复
|
||||
int main() {
|
||||
printf("=== 简化规则库测试 ===\n");
|
||||
|
||||
// 创建测试漏洞数组
|
||||
VulnerabilityInfo vulnerabilities[10];
|
||||
int max_vulns = 10;
|
||||
|
||||
// 测试简化规则库检测
|
||||
int vuln_count = detect_vulnerabilities_simple("comprehensive_vulnerability_test.c", vulnerabilities, max_vulns);
|
||||
|
||||
printf("检测完成,发现 %d 个漏洞\n", vuln_count);
|
||||
|
||||
// 输出发现的漏洞
|
||||
for (int i = 0; i < vuln_count; i++) {
|
||||
printf("漏洞 %d:\n", i + 1);
|
||||
printf(" 文件: %s\n", vulnerabilities[i].file_path);
|
||||
printf(" 行号: %d\n", vulnerabilities[i].line_number);
|
||||
printf(" 类型: %d\n", vulnerabilities[i].type);
|
||||
printf(" 严重性: %d\n", vulnerabilities[i].severity);
|
||||
printf(" 描述: %s\n", vulnerabilities[i].description);
|
||||
printf(" 修复建议: %s\n", vulnerabilities[i].fix_suggestion);
|
||||
printf(" 置信度: %d\n", vulnerabilities[i].confidence_score);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,46 @@
|
||||
MANIFEST.in
|
||||
README.md
|
||||
pyproject.toml
|
||||
src/advanced_path_exploration.c
|
||||
src/advanced_test.c
|
||||
src/api.c
|
||||
src/api.h
|
||||
src/comprehensive_symbolic_test.c
|
||||
src/comprehensive_test.c
|
||||
src/enhanced_report_generator.c
|
||||
src/enhanced_test.c
|
||||
src/enhanced_vulnerability_detector.c
|
||||
src/formal_verifier.c
|
||||
src/formal_verifier.h
|
||||
src/intelligent_analyzer.c
|
||||
src/intelligent_analyzer.h
|
||||
src/klee_config_optimizer.c
|
||||
src/klee_friendly_test.c
|
||||
src/mega_long_test.c
|
||||
src/mega_test.c
|
||||
src/path_analyzer.c
|
||||
src/path_analyzer.h
|
||||
src/simple_klee_test.c
|
||||
src/smart_scheduler.c
|
||||
src/smart_scheduler.h
|
||||
src/srs_compliant_main.c
|
||||
src/taint_analyzer.c
|
||||
src/taint_analyzer.h
|
||||
src/test_analyzer.c
|
||||
src/vulnerability_test.c
|
||||
symbolic_cli/cli.py
|
||||
symbolic_engine_enhanced.egg-info/PKG-INFO
|
||||
symbolic_engine_enhanced.egg-info/SOURCES.txt
|
||||
symbolic_engine_enhanced.egg-info/dependency_links.txt
|
||||
symbolic_engine_enhanced.egg-info/entry_points.txt
|
||||
symbolic_engine_enhanced.egg-info/requires.txt
|
||||
symbolic_engine_enhanced.egg-info/top_level.txt
|
||||
webui/README.md
|
||||
webui/__init__.py
|
||||
webui/app.py
|
||||
webui/static/style.css
|
||||
webui/templates/base.html
|
||||
webui/templates/index.html
|
||||
webui/templates/result.html
|
||||
webui/templates/uploads.html
|
||||
webui/templates/view_source.html
|
||||
@ -0,0 +1 @@
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
[console_scripts]
|
||||
symbolic-engine = symbolic_cli.cli:main
|
||||
symbolic-engine-enhanced = symbolic_cli.cli:main
|
||||
symbolic-engine-webui = webui.app:main
|
||||
@ -0,0 +1,2 @@
|
||||
flask==2.3.3
|
||||
werkzeug==2.3.7
|
||||
@ -0,0 +1,2 @@
|
||||
symbolic_cli
|
||||
webui
|
||||
Loading…
Reference in new issue