W19: plugin_loader hardening — ABI try/catch, path validation, atomic IDs, CLI exit codes (W19.1-W19.5)
Fixes: F-18.3-1 through F-18.3-5 (all CLOSED, findings registry at zero) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -35,10 +35,11 @@
|
||||
#define CLR_BOLD "\033[1m"
|
||||
|
||||
// ---- 退出码 ----
|
||||
// 0=正常退出 1=用户中断(SIGINT/Ctrl+C) 2=致命错误 3=配置错误
|
||||
#define EXIT_OK 0
|
||||
#define EXIT_INIT_FAIL 1
|
||||
#define EXIT_AI_ERROR 2
|
||||
#define EXIT_SVC_UNAVAIL 3
|
||||
#define EXIT_INTERRUPT 1
|
||||
#define EXIT_FATAL 2
|
||||
#define EXIT_CONFIG 3
|
||||
|
||||
// ---- 服务 vtable 指针 ----
|
||||
static const dstalk_ai_service_t* g_ai = nullptr;
|
||||
@@ -48,12 +49,14 @@ static const dstalk_file_io_service_t* g_file_io = nullptr;
|
||||
// ---- 运行时状态 ----
|
||||
static std::string g_current_model;
|
||||
static std::atomic<bool> g_quit_requested{false};
|
||||
static std::atomic<bool> g_quit_via_signal{false};
|
||||
|
||||
// ---- Ctrl+C 信号处理 ----
|
||||
#ifdef _WIN32
|
||||
static BOOL WINAPI on_console_event(DWORD event)
|
||||
{
|
||||
if (event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT) {
|
||||
g_quit_via_signal = true;
|
||||
g_quit_requested = true;
|
||||
return TRUE;
|
||||
}
|
||||
@@ -62,6 +65,7 @@ static BOOL WINAPI on_console_event(DWORD event)
|
||||
#else
|
||||
static void on_signal(int /*sig*/)
|
||||
{
|
||||
g_quit_via_signal = true;
|
||||
g_quit_requested = true;
|
||||
}
|
||||
#endif
|
||||
@@ -154,7 +158,6 @@ static void handle_command(const char* line)
|
||||
// /quit —— 设置退出标志,让控制流自然回到 main 末尾
|
||||
if (std::strcmp(line, "/quit") == 0 || std::strcmp(line, "/q") == 0) {
|
||||
g_quit_requested = true;
|
||||
std::printf("再见!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -442,7 +445,7 @@ int main(int argc, char* argv[])
|
||||
// 初始化主机(加载配置 + 自动扫描 plugins/ 目录加载插件)
|
||||
if (dstalk_init(config_path) != 0) {
|
||||
std::fprintf(stderr, CLR_RED "[dstalk] 初始化失败\n" CLR_RESET);
|
||||
return EXIT_INIT_FAIL;
|
||||
return EXIT_CONFIG;
|
||||
}
|
||||
|
||||
// 查询插件服务
|
||||
@@ -486,12 +489,12 @@ int main(int argc, char* argv[])
|
||||
if (input.empty()) {
|
||||
std::fprintf(stderr, "empty prompt\n");
|
||||
dstalk_shutdown();
|
||||
return 1;
|
||||
return EXIT_FATAL;
|
||||
}
|
||||
if (!g_ai || !g_session) {
|
||||
std::fprintf(stderr, CLR_RED "[ERROR] AI or session service unavailable\n" CLR_RESET);
|
||||
dstalk_shutdown();
|
||||
return EXIT_SVC_UNAVAIL;
|
||||
return EXIT_CONFIG;
|
||||
}
|
||||
int history_count = 0;
|
||||
const dstalk_message_t* history = g_session->history(&history_count);
|
||||
@@ -506,14 +509,17 @@ int main(int argc, char* argv[])
|
||||
result.error ? result.error : "unknown");
|
||||
g_ai->free_result(&result);
|
||||
dstalk_shutdown();
|
||||
return EXIT_AI_ERROR;
|
||||
return EXIT_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[8192];
|
||||
while (true) {
|
||||
// B1: 检查退出标志
|
||||
if (g_quit_requested) break;
|
||||
if (g_quit_requested) {
|
||||
std::printf("再见!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// A1: 提示符带模型名(batch 模式不打印)
|
||||
if (!batch_mode) {
|
||||
@@ -574,7 +580,7 @@ int main(int argc, char* argv[])
|
||||
g_ai->free_result(&result);
|
||||
}
|
||||
|
||||
// B2: 单一退出点,dstalk_shutdown 只在此调用
|
||||
// B2: 单一退出点,dstalk_shutdown 只在此调用(交互模式下)
|
||||
dstalk_shutdown();
|
||||
return EXIT_OK;
|
||||
return g_quit_via_signal ? EXIT_INTERRUPT : EXIT_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user