docs: 整理文档——修复全部 file:// 失效链接、补齐缺失模块 README
- 将 7 个文档中的 mac 绝对路径链接(file:///Users/qingsong/...)转换为仓库相对路径, 并修正错误目标:aibox 入口 main.py → aibox.py、pymsg C++ 实现 → libmsg/inc/us/Msg.hpp、 bot4cj cpp/cnn → cuda - 主 README 补 liblogc 基础库条目与 confs2 归档说明,安装顺序补 ca - 新增 liblogc / libtry / confs2 / 3d / memdb README - 同步 db2 脚本迁移(db/create_sqlite3.sql → db2/scripts/)导致的失效引用
This commit is contained in:
1 parent
7072e33d6f
commit
7467e7bd42
13 files changed
+158
-92
No files matched your search
@@ -0,0 +1,6 @@
|
||||
# 3d — bot4cj 机器人 3D 打印模型
|
||||
|
||||
Dashun 蜘蛛机器人平台的 3D 打印/加工件模型文件(STL / STEP / SLDPRT),与 [bot4cj](../bot4cj/) 硬件项目配套。
|
||||
|
||||
- STL — 3D 打印件(`leg*.stl` / `支臂.stl` / `支臂_mirror.stl` 等)
|
||||
- STEP / SLDPRT — 机械设计源文件(`手臂.SLDPRT` / `爪手.STEP` / `配件*.STEP` 等)
|
||||
@@ -106,7 +106,7 @@
|
||||
- **前置转发**:无 `Target-Url` 为公开请求(剥身份头直转 gateway);有 `Target-Url` 为受保护请求(验签后注入 `X-Auth-User`/`X-Auth-Admin` 转发,strip-then-set 契约剥离客户端伪造值);上游不可达统一 502。
|
||||
- **CAPTCHA**:`GET /captcha/image` 为 captcha 服务(pymsg/TCP :8009)的图形验证码代理路由;`/login` 强制 CAPTCHA。
|
||||
- **速率限制**:登录 5 次/5 分钟、注册 3 次/10 分钟、发码 IP 级 + 邮箱级双窗口,按 `X-Forwarded-For`(WAF 注入)客户端 IP 计数。
|
||||
- **用户表**:`Users` 表由 [db/create_sqlite3.sql](db/create_sqlite3.sql) 建立,无默认管理员账号,首位注册者即为管理员。
|
||||
- **用户表**:`Users` 表由 [db2/scripts/create_sqlite3.sql](db2/scripts/create_sqlite3.sql) 建立,无默认管理员账号,首位注册者即为管理员。
|
||||
- 详见 [ca/README.md](ca/README.md)。
|
||||
|
||||
### gateway(应用层网关 · v0.9.0)
|
||||
@@ -207,7 +207,7 @@
|
||||
|
||||
### confs(统一配置服务 · 已内嵌进 core)
|
||||
|
||||
- 独立 Python `confs` 服务已废弃(不再部署),配置分发逻辑已内嵌进 `core`(`ConfsTask`,由 `--confs 8010` 启用,协议与 Python 版字节级兼容,消费方零改动)。
|
||||
- 独立 Python `confs` 服务已废弃(不再部署),配置分发逻辑已内嵌进 `core`(`ConfsTask`,由 `--confs 8010` 启用,协议与 Python 版字节级兼容,消费方零改动);C++20 重写版 [confs2/](confs2/) 目录保留为开发存档。
|
||||
- 集中存放各服务的配置文件(`confs/configs/`),基于 pymsg(RpcServer,TCP 长度前缀帧 + JSON)分发。
|
||||
- pymsg 路由:`get`(取配置文件全文;带 `key` 时按键提取,ini 用 `Section.option`、json 用点号路径)、`list`(列出全部配置及元信息)、`reload`(重载指定配置,缺省清空全部缓存)、`health`。
|
||||
- 内存缓存 + 文件 mtime 变化自动重载,改配置无需重启;配置名校验(basename + realpath 前缀 + 扩展名白名单)防路径遍历。
|
||||
@@ -264,6 +264,7 @@
|
||||
| [libcrypt](libcrypt/) | 加密库:`AES_CBC`、`MyRSA`、`SHA256`、`Base64`、`Crypto_Basic` |
|
||||
| [libsqlite3](libsqlite3/) | SQLite3 C++ 封装(Header-only) |
|
||||
| [libmsg](libmsg/) | 消息通信库:pymsg 协议 C++ 实现(4B 大端长度前缀 + UTF-8 载荷),提供 `MsgClient`/`MsgServer`/`AsyncQueue`/`RpcClient`/`RpcServer`,与 Python pymsg 字节级兼容 |
|
||||
| [liblogc](liblogc/) | 统一集中式日志客户端(C++ 版,`us/LogC.hpp`),对应 Python `log_client.py`:pymsg/TCP 异步批量写入 db2 Logs 表,队列上限 1 万条 + 级别过滤 + fail-safe,ca/core/gateway/captcha2/smtp3 等 C++ 服务共用 |
|
||||
| [libtry](libtry/) | 嵌入式脚本解释器(~741 行 C),手写递归下降词法/语法/执行引擎,支持变量/数组/函数/控制流,宽字符(中文标识符),用于嵌入式操作界面 shell |
|
||||
|
||||
### Python 共享组件
|
||||
@@ -326,7 +327,7 @@ bash _setup.deb.sh # Debian/Ubuntu
|
||||
# 或
|
||||
bash _setup.rhel.sh # RHEL/CentOS/Rocky/Fedora
|
||||
|
||||
# 2. 依次安装各模块(libth -> libhttp -> libcrypt -> libsqlite3 -> libmsg -> liblogc -> gateway -> waf -> static -> fsys -> dnfs -> dnfs2 -> db -> db2 -> smtp -> smtp3 -> captcha -> captcha2 -> confs -> ai_review -> aibox -> redirect80 -> core;legacy Python 版与 C++ 重写版均构建,生产由 core 按 services.yaml 拉起新版)
|
||||
# 2. 依次安装各模块(libth -> libhttp -> libcrypt -> libsqlite3 -> libmsg -> liblogc -> gateway -> waf -> ca -> static -> fsys -> dnfs -> dnfs2 -> db -> db2 -> smtp -> smtp3 -> captcha -> captcha2 -> confs -> ai_review -> aibox -> redirect80 -> core;legacy Python 版与 C++ 重写版均构建,生产由 core 按 services.yaml 拉起新版)
|
||||
bash _inst.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -469,7 +469,7 @@ CREATE TABLE memos (
|
||||
|
||||
### 9.4 技能格式规范
|
||||
|
||||
详见 [SKILLS_FORMAT.md](file:///Users/qingsong/micro_servers/aibox/SKILLS_FORMAT.md)
|
||||
详见 [SKILLS_FORMAT.md](SKILLS_FORMAT.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -805,19 +805,19 @@ sqlite3 ~/.aibox/memos.db "SELECT * FROM memos WHERE status='pending';"
|
||||
|
||||
### A. 配置文件示例
|
||||
|
||||
完整默认配置见 [main.py:1100-1180](file:///Users/qingsong/micro_servers/aibox/main.py#L1100-L1180)
|
||||
完整默认配置见 [aibox.py:1100-1180](aibox.py#L1100-L1180)
|
||||
|
||||
### B. 数据库 Schema
|
||||
|
||||
完整建表语句见:
|
||||
- 记忆库:[main.py](file:///Users/qingsong/micro_servers/aibox/main.py) 中 `MemoryManager._init_db()`
|
||||
- 任务库:[main.py](file:///Users/qingsong/micro_servers/aibox/main.py) 中 `MemoScheduler._init_db()`
|
||||
- 记忆库:[aibox.py](aibox.py) 中 `MemoryManager._init_db()`
|
||||
- 任务库:[aibox.py](aibox.py) 中 `MemoScheduler._init_db()`
|
||||
|
||||
### C. 参考文档
|
||||
|
||||
- [DeepSeek API 文档](https://platform.deepseek.com/docs)
|
||||
- [websockets 库文档](https://websockets.readthedocs.io/)
|
||||
- [SKILLS_FORMAT.md](file:///Users/qingsong/micro_servers/aibox/SKILLS_FORMAT.md)
|
||||
- [SKILLS_FORMAT.md](SKILLS_FORMAT.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -317,7 +317,7 @@ cat scripts/std.mt | bash _run.sh
|
||||
|
||||
## 神经网络支持
|
||||
|
||||
项目内置了全连接层 Nn1([math/nn.cj](src/math/nn.cj))与 CNN([math/cnn.cj](src/math/cnn.cj) + [cpp/cnn/](src/cpp/cnn/)):
|
||||
项目内置了全连接层 Nn1([math/nn.cj](src/math/nn.cj))与 CNN([math/cnn.cj](src/math/cnn.cj) + [cuda/](src/cuda/)):
|
||||
|
||||
- **Nn1**:多层感知机,支持前向传播、反向传播、权重更新
|
||||
- **CNN**:Conv → ReLU → Pool → GA-Pool → Flatten → FC
|
||||
@@ -374,7 +374,7 @@ main.cj 中预留了 DRL 流程(注释状态):加载预训练权重 →
|
||||
## 相关资源
|
||||
|
||||
- [Dashun 蜘蛛机器人建模](https://github.com/gopsc/Dashun)
|
||||
- [深度分析报告](docs/Reports/analysis_20260525_00.md)(28 章节,1280 行)
|
||||
- [深度分析报告](../docs/reports/bot4cj_analysis_20260525_00.md)(28 章节,1280 行)
|
||||
- [仓颉编程语言](https://cangjie-lang.org/)
|
||||
- [PCA9685 数据手册](https://www.nxp.com/docs/en/data-sheet/PCA9685.pdf)
|
||||
- [MPU6050 数据手册](https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# confs2 — 统一配置服务(C++20 重写,已归档)
|
||||
|
||||
confs 的 C++20 重写实现,基于 libmsg `RpcServer`,协议与 Python 版 confs 完全兼容(`get` / `list` / `reload` / `health`),消费方零改动。
|
||||
|
||||
> **状态:已归档**。配置分发逻辑已合并进 `core` 的 `ConfsTask`(`--confs <port>` 启用,如 `./nidus.out -i . --serve 5200 --confs 8010`),不再独立部署。本目录保留为开发存档,开发文档见 [docs/reports/confs2_cpp_rewrite_dev_doc.md](../docs/reports/confs2_cpp_rewrite_dev_doc.md)。
|
||||
|
||||
配套黑盒测试:`python3 test_confs2.py`。
|
||||
+2
-2
@@ -29,7 +29,7 @@ Dendrachy Network File-System,基于父子关系(pid)组织的树状节点
|
||||
|
||||
## 数据模型
|
||||
|
||||
对应 `db` 服务中的 `Notes` 表(见 [db/create_sqlite3.sql](../db/create_sqlite3.sql)):
|
||||
对应 `db` 服务中的 `Notes` 表(见 [db2/scripts/create_sqlite3.sql](../db2/scripts/create_sqlite3.sql)):
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
@@ -324,7 +324,7 @@ bash _run.sh # 启动服务(waitress)
|
||||
- 现两函数均已加 `@_handle_exp`([dnfs.py:469](dnfs.py#L469)、[dnfs.py:572](dnfs.py#L572)),异常统一返回结构化 JSON,不再出 Flask 默认 500 页。
|
||||
|
||||
4. **有子节点的父节点可能被删除(树结构完整性保护缺陷)** — ❌ 未修复
|
||||
- **数据库层缺失外键约束**: Notes 表 `pid` 列未定义 `FOREIGN KEY ... ON DELETE RESTRICT`([db/create_sqlite3.sql](../db/create_sqlite3.sql))。
|
||||
- **数据库层缺失外键约束**: Notes 表 `pid` 列未定义 `FOREIGN KEY ... ON DELETE RESTRICT`([db2/scripts/create_sqlite3.sql](../db2/scripts/create_sqlite3.sql))。
|
||||
- **应用层 TOCTOU 竞态**: 子节点查询(SELECT)与删除(DELETE)是两个独立 RPC,无事务保护。
|
||||
- **错误处理缺陷**: 多处直接访问 `notes['data']` 而未先确认 `success`(如 [dnfs.py:387](dnfs.py#L387)、[L519](dnfs.py#L519)),`success=False` 时可能抛 KeyError。
|
||||
|
||||
|
||||
@@ -26,16 +26,16 @@
|
||||
|
||||
- **位置**: 历史版本 L399-455 等位置
|
||||
- **当前状态**: ✅ 已修复(2026-08-06)
|
||||
- **修复**: 新增 `_validate_col` 静态方法 [db2.cpp L443-449](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L443-L449),对所有列名(where keys、columns、order_by、INSERT/UPDATE values keys)校验其存在于表 schema 的 `col_map` 中,不存在则抛 `"unknown column"` 错误。5 个注入点全部修复。
|
||||
- **修复**: 新增 `_validate_col` 静态方法 [db2.cpp L443-449](../../db2/src/db2.cpp#L443-L449),对所有列名(where keys、columns、order_by、INSERT/UPDATE values keys)校验其存在于表 schema 的 `col_map` 中,不存在则抛 `"unknown column"` 错误。5 个注入点全部修复。
|
||||
|
||||
`sqlite3_prepare_v2` 只编译单条语句(`; DROP TABLE` 不会执行),但**单语句内注入**在修复前仍然可行。修复后列名必须是真实存在的列名,注入不可能。
|
||||
|
||||
- **注入点覆盖**:
|
||||
- `where` 的 key → `_build_where` [L473-475](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L473-L475)
|
||||
- `columns` 数组元素 → `_do_select` [L588-590](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L588-L590)
|
||||
- `order_by[].column` → `_do_select` [L611-612](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L611-L612)
|
||||
- INSERT `values` 的 key → `_do_insert` [L691-693](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L691-L693)
|
||||
- UPDATE SET `values` 的 key → `_do_update` [L734-736](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L734-L736)
|
||||
- `where` 的 key → `_build_where` [L473-475](../../db2/src/db2.cpp#L473-L475)
|
||||
- `columns` 数组元素 → `_do_select` [L588-590](../../db2/src/db2.cpp#L588-L590)
|
||||
- `order_by[].column` → `_do_select` [L611-612](../../db2/src/db2.cpp#L611-L612)
|
||||
- INSERT `values` 的 key → `_do_insert` [L691-693](../../db2/src/db2.cpp#L691-L693)
|
||||
- UPDATE SET `values` 的 key → `_do_update` [L734-736](../../db2/src/db2.cpp#L734-L736)
|
||||
|
||||
---
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
- **位置**: `_build_where` `in` 运算符分支
|
||||
- **当前状态**: ✅ 已修复(2026-08-06)
|
||||
- **修复**: [L503-506](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L503-L506) 空 `in` 数组现在生成恒假条件 `parts.push_back("0")`,使 WHERE 子句匹配零行,与 Python 版 SQLAlchemy `column.in_([])` 行为一致。
|
||||
- **修复**: [L503-506](../../db2/src/db2.cpp#L503-L506) 空 `in` 数组现在生成恒假条件 `parts.push_back("0")`,使 WHERE 子句匹配零行,与 Python 版 SQLAlchemy `column.in_([])` 行为一致。
|
||||
|
||||
---
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
- **位置**: 历史版本 `_coerce_value` / `_bind_value`
|
||||
- **当前状态**: ✅ 已修复(2026-08-06)
|
||||
- **修复**:
|
||||
- `_coerce_value` [L414-420](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L414-L420) 现在返回 `boost::json::value`,仅对字符串做 `$now` 替换,其他类型保持原样。
|
||||
- 新增 `_bind_value` [L422-440](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L422-L440),按 JSON 类型分别调用 `sqlite3_bind_int64` / `sqlite3_bind_double` / `sqlite3_bind_text` / `sqlite3_bind_null` / `sqlite3_bind_int` (bool)。
|
||||
- `_coerce_value` [L414-420](../../db2/src/db2.cpp#L414-L420) 现在返回 `boost::json::value`,仅对字符串做 `$now` 替换,其他类型保持原样。
|
||||
- 新增 `_bind_value` [L422-440](../../db2/src/db2.cpp#L422-L440),按 JSON 类型分别调用 `sqlite3_bind_int64` / `sqlite3_bind_double` / `sqlite3_bind_text` / `sqlite3_bind_null` / `sqlite3_bind_int` (bool)。
|
||||
- `WhereClause::params` 改为 `std::vector<json::value>`,保留原始类型。
|
||||
|
||||
修复后 INTEGER/REAL 等数值类型以原生 SQLite 存储类写入,避免 TEXT 列上的字符串比较问题,行为与 Python 版一致。
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
- **位置**: 历史版本 `utc_now` + `_do_cleanup`
|
||||
- **当前状态**: ✅ 已修复(2026-08-07)
|
||||
- **修复**: [L863-865](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L863-L865) 清理 SQL 改用 `strftime('%Y-%m-%dT%H:%M:%S','now','-N days')`,与 `utc_now()` 的 `T` 分隔格式完全对齐。
|
||||
- **修复**: [L863-865](../../db2/src/db2.cpp#L863-L865) 清理 SQL 改用 `strftime('%Y-%m-%dT%H:%M:%S','now','-N days')`,与 `utc_now()` 的 `T` 分隔格式完全对齐。
|
||||
|
||||
---
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
- **位置**: 历史版本 `load_config`
|
||||
- **当前状态**: ✅ 已修复(2026-08-07)
|
||||
- **修复**: [L159-175](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L159-L175) 在 INI 解析后,对 7 个必需字段做必填校验,缺失任一则 `fprintf` 明确错误信息后 `exit(1)`。
|
||||
- **修复**: [L159-175](../../db2/src/db2.cpp#L159-L175) 在 INI 解析后,对 7 个必需字段做必填校验,缺失任一则 `fprintf` 明确错误信息后 `exit(1)`。
|
||||
|
||||
---
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
- **位置**: `_cleanup_loop`、`load_config`
|
||||
- **当前状态**: ✅ 已修复(2026-08-07)
|
||||
- **修复**: [db2.cpp L207-L227](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L207-L227) 在 `load_config` 返回前(所有配置来源——INI、环境变量、命令行参数——都加载完毕后)统一增加数值范围校验,非法值立即 `fprintf` 明确错误信息后 `exit(1)`。
|
||||
- **修复**: [db2.cpp L207-L227](../../db2/src/db2.cpp#L207-L227) 在 `load_config` 返回前(所有配置来源——INI、环境变量、命令行参数——都加载完毕后)统一增加数值范围校验,非法值立即 `fprintf` 明确错误信息后 `exit(1)`。
|
||||
- **校验项**:
|
||||
- `listen_port`: 1-65535
|
||||
- `workers`: ≥ 1
|
||||
@@ -98,22 +98,22 @@
|
||||
|
||||
| # | 问题 | 位置 | 说明 |
|
||||
|---|------|------|------|
|
||||
| P3-1 | schema 缓存永不失效 | 历史版本 | ✅ 已修复:缓存项携带 `PRAGMA schema_version` [L270-273](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L270-L273),每次取 schema 前比对版本号;DDL 变更后自动失效并重新反射 |
|
||||
| P3-1 | schema 缓存永不失效 | 历史版本 | ✅ 已修复:缓存项携带 `PRAGMA schema_version` [L270-273](../../db2/src/db2.cpp#L270-L273),每次取 schema 前比对版本号;DDL 变更后自动失效并重新反射 |
|
||||
| P3-2 | `_coerce_value` 对 null 返回 `""` | 历史版本 | ✅ 已修复:`_coerce_value` 改为返回 `json::value`,null 保持为 null |
|
||||
| P3-3 | `limit`/`offset` 未校验负值 | 历史版本 | ✅ 已修复:[L622-632](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L622-L632) 非负校验 |
|
||||
| P3-4 | WHERE 条件数 / IN 数组大小无上限 | 历史版本 | ✅ 已修复:[L463-467](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L463-L467) 64 条件上限、[L507-511](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L507-L511) IN 元素 1000 上限 |
|
||||
| P3-5 | 空 `values` 对象导致 INSERT/UPDATE 语法错误 | 历史版本 | ✅ 已修复:[L680-682](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L680-L682)、[L724-726](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L724-L726) 前置校验 |
|
||||
| P3-6 | 未知 WHERE 运算符被静默跳过 | 历史版本 | ✅ 已修复:[L519-521](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L519-L521) 未知运算符抛错 |
|
||||
| **P3-7** | **`utc_now()` 使用非线程安全的 `gmtime()`** | [L58-66](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L58-L66) | ✅ 已修复(2026-08-07,第五轮):改用 `gmtime_r(&t, &tmbuf)` 线程安全版本,消除多线程并发调用时的静态缓冲区数据竞争 |
|
||||
| **P3-8** | **其他数值配置无范围校验** | [L186-L191](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L186-L191) | ✅ 已修复(2026-08-07,与 P2-3 一同):[L207-L227](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L207-L227) 所有数值配置项范围校验覆盖:port 1-65535、workers ≥1、cleanup_interval ≥1、retention_days ≥0、max_records ≥1 |
|
||||
| **P3-9** | **`columns` 数组中非字符串元素未检查类型** | [L633-636](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L633-L636) | ✅ 已修复(2026-08-07,第五轮):添加 `if (!c.is_string()) throw "columns array must contain only strings"` 类型校验,非字符串元素抛清晰错误而非 boost 原始异常 |
|
||||
| **P3-10** | **`DbConn` 析构使用 `sqlite3_close` 而非 `sqlite3_close_v2`** | [L254-256](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L254-L256) | ✅ 已修复(2026-08-07,第五轮):改用 `sqlite3_close_v2`,异常路径存在未 finalize 的 stmt 时标记为 zombie 状态,等所有 stmt 释放后自动关闭,更鲁棒 |
|
||||
| **P3-11** | **`std::stoi/stoll` 解析配置失败无友好错误提示** | [L72-87](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L72-L87)、[L163](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L163)、[L208-214](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L208-L214)、[L218-219](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L218-L219)、[L226-227](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L226-L227) | ✅ 已修复(2026-08-07,第五轮):引入 `safe_stoi(s, field_name)` 辅助函数,所有 `std::stoi` 调用点(CONFS_PORT、INI 配置、环境变量、命令行参数共 9 处)替换为 `safe_stoi`,失败时抛带字段名的友好错误(如 `"invalid [server] port: 'abc' (stoi)"`) |
|
||||
| **P3-12**(新) | **`_log_internal` 静默吞掉所有异常** | [L898-900](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L898-L900) | ✅ 已修复(2026-08-07,第五轮):`catch (...)` 改为 `catch (const std::exception& e)`,并 `fprintf(stderr, "[db2] _log_internal failed: %s", e.what())`,便于排查日志写入失败原因,仍不阻塞业务 |
|
||||
| **P3-13**(新) | **`_do_cleanup` COUNT 查询 prepare 失败静默跳过** | [L947-951](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L947-L951) | ✅ 已修复(2026-08-07,第五轮):prepare 失败时 `fprintf(stderr, ...)` 记录 sqlite3_errmsg,同时简化 finalize 逻辑为单一出口 `if (stmt) sqlite3_finalize(stmt)`,避免重复 finalize 风险 |
|
||||
| **P3-14**(新) | **`order_by` 非法元素静默跳过** | [L654-671](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L654-L671) | ✅ 已修复(2026-08-07,第五轮):非 object 元素、缺少 `column` 字段、`column` 非 string、`desc` 非 bool 均改为抛 `runtime_error` 明确报错,不再静默跳过,避免掩盖客户端错误 |
|
||||
| **P3-15**(新) | **`action` 字段非 string 静默默认为 "select"** | [L596-600](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L596-L600) | ✅ 已修复(2026-08-07,第五轮):`action` 字段存在但非 string 类型时抛 `"'action' must be a string"`,不再静默回退为 "select" 导致意外执行查询 |
|
||||
| **P3-16**(新) | **`order_by` 的 `column`/`desc` 字段类型未校验** | [L658-668](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L658-L668) | ✅ 已修复(2026-08-07,第五轮,与 P3-14 一同):`column` 字段检查 `is_string()`,`desc` 字段检查 `is_bool()`,类型不符时抛清晰错误而非 boost 原始异常 |
|
||||
| P3-3 | `limit`/`offset` 未校验负值 | 历史版本 | ✅ 已修复:[L622-632](../../db2/src/db2.cpp#L622-L632) 非负校验 |
|
||||
| P3-4 | WHERE 条件数 / IN 数组大小无上限 | 历史版本 | ✅ 已修复:[L463-467](../../db2/src/db2.cpp#L463-L467) 64 条件上限、[L507-511](../../db2/src/db2.cpp#L507-L511) IN 元素 1000 上限 |
|
||||
| P3-5 | 空 `values` 对象导致 INSERT/UPDATE 语法错误 | 历史版本 | ✅ 已修复:[L680-682](../../db2/src/db2.cpp#L680-L682)、[L724-726](../../db2/src/db2.cpp#L724-L726) 前置校验 |
|
||||
| P3-6 | 未知 WHERE 运算符被静默跳过 | 历史版本 | ✅ 已修复:[L519-521](../../db2/src/db2.cpp#L519-L521) 未知运算符抛错 |
|
||||
| **P3-7** | **`utc_now()` 使用非线程安全的 `gmtime()`** | [L58-66](../../db2/src/db2.cpp#L58-L66) | ✅ 已修复(2026-08-07,第五轮):改用 `gmtime_r(&t, &tmbuf)` 线程安全版本,消除多线程并发调用时的静态缓冲区数据竞争 |
|
||||
| **P3-8** | **其他数值配置无范围校验** | [L186-L191](../../db2/src/db2.cpp#L186-L191) | ✅ 已修复(2026-08-07,与 P2-3 一同):[L207-L227](../../db2/src/db2.cpp#L207-L227) 所有数值配置项范围校验覆盖:port 1-65535、workers ≥1、cleanup_interval ≥1、retention_days ≥0、max_records ≥1 |
|
||||
| **P3-9** | **`columns` 数组中非字符串元素未检查类型** | [L633-636](../../db2/src/db2.cpp#L633-L636) | ✅ 已修复(2026-08-07,第五轮):添加 `if (!c.is_string()) throw "columns array must contain only strings"` 类型校验,非字符串元素抛清晰错误而非 boost 原始异常 |
|
||||
| **P3-10** | **`DbConn` 析构使用 `sqlite3_close` 而非 `sqlite3_close_v2`** | [L254-256](../../db2/src/db2.cpp#L254-L256) | ✅ 已修复(2026-08-07,第五轮):改用 `sqlite3_close_v2`,异常路径存在未 finalize 的 stmt 时标记为 zombie 状态,等所有 stmt 释放后自动关闭,更鲁棒 |
|
||||
| **P3-11** | **`std::stoi/stoll` 解析配置失败无友好错误提示** | [L72-87](../../db2/src/db2.cpp#L72-L87)、[L163](../../db2/src/db2.cpp#L163)、[L208-214](../../db2/src/db2.cpp#L208-L214)、[L218-219](../../db2/src/db2.cpp#L218-L219)、[L226-227](../../db2/src/db2.cpp#L226-L227) | ✅ 已修复(2026-08-07,第五轮):引入 `safe_stoi(s, field_name)` 辅助函数,所有 `std::stoi` 调用点(CONFS_PORT、INI 配置、环境变量、命令行参数共 9 处)替换为 `safe_stoi`,失败时抛带字段名的友好错误(如 `"invalid [server] port: 'abc' (stoi)"`) |
|
||||
| **P3-12**(新) | **`_log_internal` 静默吞掉所有异常** | [L898-900](../../db2/src/db2.cpp#L898-L900) | ✅ 已修复(2026-08-07,第五轮):`catch (...)` 改为 `catch (const std::exception& e)`,并 `fprintf(stderr, "[db2] _log_internal failed: %s", e.what())`,便于排查日志写入失败原因,仍不阻塞业务 |
|
||||
| **P3-13**(新) | **`_do_cleanup` COUNT 查询 prepare 失败静默跳过** | [L947-951](../../db2/src/db2.cpp#L947-L951) | ✅ 已修复(2026-08-07,第五轮):prepare 失败时 `fprintf(stderr, ...)` 记录 sqlite3_errmsg,同时简化 finalize 逻辑为单一出口 `if (stmt) sqlite3_finalize(stmt)`,避免重复 finalize 风险 |
|
||||
| **P3-14**(新) | **`order_by` 非法元素静默跳过** | [L654-671](../../db2/src/db2.cpp#L654-L671) | ✅ 已修复(2026-08-07,第五轮):非 object 元素、缺少 `column` 字段、`column` 非 string、`desc` 非 bool 均改为抛 `runtime_error` 明确报错,不再静默跳过,避免掩盖客户端错误 |
|
||||
| **P3-15**(新) | **`action` 字段非 string 静默默认为 "select"** | [L596-600](../../db2/src/db2.cpp#L596-L600) | ✅ 已修复(2026-08-07,第五轮):`action` 字段存在但非 string 类型时抛 `"'action' must be a string"`,不再静默回退为 "select" 导致意外执行查询 |
|
||||
| **P3-16**(新) | **`order_by` 的 `column`/`desc` 字段类型未校验** | [L658-668](../../db2/src/db2.cpp#L658-L668) | ✅ 已修复(2026-08-07,第五轮,与 P3-14 一同):`column` 字段检查 `is_string()`,`desc` 字段检查 `is_bool()`,类型不符时抛清晰错误而非 boost 原始异常 |
|
||||
|
||||
---
|
||||
|
||||
@@ -121,31 +121,31 @@
|
||||
|
||||
### ND-1(P2): `start()` 异常路径导致 `std::terminate()` 硬崩溃
|
||||
|
||||
- **位置**: `start()` [L341-355](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L341-L355)
|
||||
- **位置**: `start()` [L341-355](../../db2/src/db2.cpp#L341-L355)
|
||||
- **当前状态**: ✅ 已修复(2026-08-07,第六轮)
|
||||
- **问题**: 清理线程 [L343](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L343) 启动后,若 `rpc.start()` 抛出异常(socket/bind/listen 失败如端口被占用,或事件循环异常经 `MsgServer::start()` 重新抛出),原有的 `_cleanup_running=false; notify; join` 正常清理路径被跳过。栈展开时 `DB2Server` 析构,`std::thread` 成员仍 joinable → `std::terminate()` 进程硬崩溃,并掩盖真实错误(本应干净退出返回错误码)。
|
||||
- **修复**: 引入 RAII 作用域守卫 `CleanupGuard` [L348-355](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L348-L355),析构时停止并 join 清理线程。无论 `rpc.start()` 正常返回还是抛出,清理线程都被优雅回收,异常沿调用链传播到 `main` 的 catch 返回错误码。
|
||||
- **问题**: 清理线程 [L343](../../db2/src/db2.cpp#L343) 启动后,若 `rpc.start()` 抛出异常(socket/bind/listen 失败如端口被占用,或事件循环异常经 `MsgServer::start()` 重新抛出),原有的 `_cleanup_running=false; notify; join` 正常清理路径被跳过。栈展开时 `DB2Server` 析构,`std::thread` 成员仍 joinable → `std::terminate()` 进程硬崩溃,并掩盖真实错误(本应干净退出返回错误码)。
|
||||
- **修复**: 引入 RAII 作用域守卫 `CleanupGuard` [L348-355](../../db2/src/db2.cpp#L348-L355),析构时停止并 join 清理线程。无论 `rpc.start()` 正常返回还是抛出,清理线程都被优雅回收,异常沿调用链传播到 `main` 的 catch 返回错误码。
|
||||
|
||||
### ND-4(P3): `limit`/`offset`/`where` 类型不符被静默忽略
|
||||
|
||||
- **位置**: `_do_select` limit/offset [L692-708](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L692-L708)、`_handle_execute` where [L626-630](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L626-L630)
|
||||
- **位置**: `_do_select` limit/offset [L692-708](../../db2/src/db2.cpp#L692-L708)、`_handle_execute` where [L626-630](../../db2/src/db2.cpp#L626-L630)
|
||||
- **当前状态**: ✅ 已修复(2026-08-07,第六轮)
|
||||
- **问题**: `limit`/`offset` 仅当 `is_int64()` 才应用,`where` 仅当 `is_object()` 才解析;调用方传错类型(字符串/浮点/数组)时字段被静默丢弃,出现"看似生效实则未生效"的静默偏差,掩盖客户端错误。
|
||||
- **修复**: `limit`/`offset` 存在但非整型、`where` 存在但非对象时抛清晰错误(与 P3-15 action 校验一致)。
|
||||
|
||||
### ND-5(P3): `_bind_value` uint64 超 INT64_MAX 截断溢出
|
||||
|
||||
- **位置**: `_bind_value` [L480-485](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L480-L485)
|
||||
- **位置**: `_bind_value` [L480-485](../../db2/src/db2.cpp#L480-L485)
|
||||
- **当前状态**: ✅ 已修复(2026-08-07,第六轮)
|
||||
- **问题**: `jv.as_uint64()` 经 `static_cast<sqlite3_int64>` 直接截断,超出 INT64_MAX 的 uint64 值发生回绕,数值静默失真。
|
||||
- **修复**: [L480-483](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L480-L483) 绑定前校验 `u > INT64_MAX` 则抛错,防止静默数值截断。
|
||||
- **修复**: [L480-483](../../db2/src/db2.cpp#L480-L483) 绑定前校验 `u > INT64_MAX` 则抛错,防止静默数值截断。
|
||||
|
||||
### ND-6(P3): `in` 运算符非数组值被静默当作空数组
|
||||
|
||||
- **位置**: `_build_where` in 分支 [L558-562](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L558-L562)
|
||||
- **位置**: `_build_where` in 分支 [L558-562](../../db2/src/db2.cpp#L558-L562)
|
||||
- **当前状态**: ✅ 已修复(2026-08-07,第六轮)
|
||||
- **问题**: `in` 值为字符串/数字等非数组时被当作空数组 → 恒假条件,静默掩盖客户端错误。
|
||||
- **修复**: [L558-559](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L558-L559) 非数组立即抛 `"'in' operator requires an array value"`;仅空数组保留恒假 `0` 语义(与 Python 版 `column.in_([])` 一致)。
|
||||
- **修复**: [L558-559](../../db2/src/db2.cpp#L558-L559) 非数组立即抛 `"'in' operator requires an array value"`;仅空数组保留恒假 `0` 语义(与 Python 版 `column.in_([])` 一致)。
|
||||
|
||||
### 已知限制(设计决策,非缺陷)
|
||||
|
||||
@@ -156,26 +156,26 @@
|
||||
|
||||
## 已有安全机制(正确实现)
|
||||
|
||||
1. **表名校验** — [L558-562](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L558-L562):仅允许 `[A-Za-z0-9_]`,防止表名级 SQL 注入
|
||||
2. **列名白名单校验** — `_validate_col` [L443-449](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L443-L449):5 个拼接点全部覆盖,列名必须存在于表 schema
|
||||
3. **值参数化绑定** — `_bind_value` [L422-440](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L422-L440):按 JSON 类型分别 `sqlite3_bind_*`,无值级 SQL 注入
|
||||
4. **per-thread 连接** — [L337-341](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L337-L341):`thread_local` 独占连接,避免跨线程共享 prepared statement
|
||||
1. **表名校验** — [L558-562](../../db2/src/db2.cpp#L558-L562):仅允许 `[A-Za-z0-9_]`,防止表名级 SQL 注入
|
||||
2. **列名白名单校验** — `_validate_col` [L443-449](../../db2/src/db2.cpp#L443-L449):5 个拼接点全部覆盖,列名必须存在于表 schema
|
||||
3. **值参数化绑定** — `_bind_value` [L422-440](../../db2/src/db2.cpp#L422-L440):按 JSON 类型分别 `sqlite3_bind_*`,无值级 SQL 注入
|
||||
4. **per-thread 连接** — [L337-341](../../db2/src/db2.cpp#L337-L341):`thread_local` 独占连接,避免跨线程共享 prepared statement
|
||||
5. **异常脱敏** — `RpcServer::_sanitize_error`(libmsg):正则替换绝对路径为 `<redacted>`
|
||||
6. **仅操作已有表** — `PRAGMA table_info` 反射,无法建表/删表/执行 DDL
|
||||
7. **空 `in` 恒假条件** — [L503-506](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L503-L506):空数组不忽略 WHERE,匹配零行
|
||||
8. **SQLite PRAGMA 优化** — [L223-228](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L223-L228):WAL + synchronous=NORMAL + foreign_keys=ON + busy_timeout=5000 + mmap_size=256MB
|
||||
9. **schema 缓存加锁 + 版本感知失效** — `_schema_mtx` [L326](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L326) 保护缓存;`PRAGMA schema_version` 自动感知 DDL 变更
|
||||
10. **配置完整性校验** — [L159-175](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L159-L175):7 个必需字段缺失则 `exit(1)`
|
||||
7. **空 `in` 恒假条件** — [L503-506](../../db2/src/db2.cpp#L503-L506):空数组不忽略 WHERE,匹配零行
|
||||
8. **SQLite PRAGMA 优化** — [L223-228](../../db2/src/db2.cpp#L223-L228):WAL + synchronous=NORMAL + foreign_keys=ON + busy_timeout=5000 + mmap_size=256MB
|
||||
9. **schema 缓存加锁 + 版本感知失效** — `_schema_mtx` [L326](../../db2/src/db2.cpp#L326) 保护缓存;`PRAGMA schema_version` 自动感知 DDL 变更
|
||||
10. **配置完整性校验** — [L159-175](../../db2/src/db2.cpp#L159-L175):7 个必需字段缺失则 `exit(1)`
|
||||
11. **confs 引导重试** — `retry_on_refused=true`,不要求服务启动顺序
|
||||
12. **日志内部直写** — `_log_internal` [L814-843](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L814-L843) 绕过 RPC 防递归,异常静默不阻塞业务
|
||||
13. **后台清理线程** — 条件变量优雅停止 [L847-856](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L847-L856),时间+条数双策略清理,时间戳格式 T 对齐
|
||||
12. **日志内部直写** — `_log_internal` [L814-843](../../db2/src/db2.cpp#L814-L843) 绕过 RPC 防递归,异常静默不阻塞业务
|
||||
13. **后台清理线程** — 条件变量优雅停止 [L847-856](../../db2/src/db2.cpp#L847-L856),时间+条数双策略清理,时间戳格式 T 对齐
|
||||
14. **空 values 前置校验** — INSERT/UPDATE 空 values 立即报错
|
||||
15. **WHERE 运算符白名单** — 未知运算符立即抛错,不静默跳过
|
||||
16. **`limit`/`offset` 非负校验** — 负值直接报错
|
||||
17. **WHERE / IN 输入规模上限** — 64 条件 / 1000 IN 元素,防资源耗尽
|
||||
18. **日志截断** — `kMaxMessage=8192`、`kMaxExtra=4096`,防止超长日志耗尽内存
|
||||
19. **不可拷贝连接** — `DbConn` 显式 `= delete` 拷贝构造/赋值,防止 double free
|
||||
20. **数值配置范围校验** — [L207-L227](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L207-L227):listen_port 1-65535、workers ≥1、cleanup_interval ≥1、retention_days ≥0、max_records ≥1,非法值立即 `exit(1)`,防止误配置导致 busy loop/绑定失败等异常行为
|
||||
20. **数值配置范围校验** — [L207-L227](../../db2/src/db2.cpp#L207-L227):listen_port 1-65535、workers ≥1、cleanup_interval ≥1、retention_days ≥0、max_records ≥1,非法值立即 `exit(1)`,防止误配置导致 busy loop/绑定失败等异常行为
|
||||
21. **线程安全时间函数** — `utc_now()` 使用 `gmtime_r` 而非 `gmtime`,消除多线程并发写日志时的静态缓冲区数据竞争(P3-7 修复)
|
||||
22. **安全 sqlite3 关闭** — `DbConn` 析构使用 `sqlite3_close_v2`,异常路径未 finalize 的 stmt 不会导致连接泄漏(P3-10 修复)
|
||||
23. **友好配置解析错误** — `safe_stoi(s, field_name)` 包装所有 `std::stoi` 调用点,失败时抛带字段名的错误信息(P3-11 修复)
|
||||
@@ -302,9 +302,9 @@ Cleanup thread → thread_local DbConn (sqlite3*)
|
||||
|
||||
| 机制 | 位置 | 效果 |
|
||||
|------|------|------|
|
||||
| **WAL 模式** | [L223](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L223) | 读不阻塞写、写不阻塞读 |
|
||||
| **per-thread 连接** | [L337-341](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L337-L341) | 无跨线程共享,零连接池锁 |
|
||||
| **busy_timeout=5000** | [L226](file:///Users/qingsong/Documents/blackbird/db2/src/db2.cpp#L226) | 写-写冲突自动等锁最多 5 秒 |
|
||||
| **WAL 模式** | [L223](../../db2/src/db2.cpp#L223) | 读不阻塞写、写不阻塞读 |
|
||||
| **per-thread 连接** | [L337-341](../../db2/src/db2.cpp#L337-L341) | 无跨线程共享,零连接池锁 |
|
||||
| **busy_timeout=5000** | [L226](../../db2/src/db2.cpp#L226) | 写-写冲突自动等锁最多 5 秒 |
|
||||
| **无 GIL** | — | C++ 线程真并行 |
|
||||
|
||||
### 瓶颈与风险
|
||||
|
||||
@@ -126,9 +126,9 @@
|
||||
|
||||
| 文件 | 变更内容 |
|
||||
| --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [MsgServer.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/MsgServer.hpp) | **P1修复**: 引入 `ConnectionLock` 结构(mutex + atomic active),`reply()`/`broadcast()` 获取锁后检查 `active`,`_remove_client()`/`_close_all_clients()` close 前设置 `active=false`,彻底消除残余竞态(P1-3);**P2修复**: `_server_fd` 改为 `std::atomic<int>`,所有访问使用 `.load()`/`.store()`/`.exchange()`(P2-7);**P2修复**: `start()` 校验 `on_message` 非空(P2-8);**P3修复**: `_accept_client()` 中 setsockopt 移到加入 `_clients` 之前(P3-3) |
|
||||
| [RpcServer.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/RpcServer.hpp) | **P3修复**: `_dispatch()` 区分 `_route` 字段缺失和类型不符的错误信息(P3-2) |
|
||||
| [Msg.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/Msg.hpp) | **文档**: `pmsg_send` 添加 SO_SNDTIMEO 前置条件警告(L-10) |
|
||||
| [MsgServer.hpp](../../libmsg/inc/us/MsgServer.hpp) | **P1修复**: 引入 `ConnectionLock` 结构(mutex + atomic active),`reply()`/`broadcast()` 获取锁后检查 `active`,`_remove_client()`/`_close_all_clients()` close 前设置 `active=false`,彻底消除残余竞态(P1-3);**P2修复**: `_server_fd` 改为 `std::atomic<int>`,所有访问使用 `.load()`/`.store()`/`.exchange()`(P2-7);**P2修复**: `start()` 校验 `on_message` 非空(P2-8);**P3修复**: `_accept_client()` 中 setsockopt 移到加入 `_clients` 之前(P3-3) |
|
||||
| [RpcServer.hpp](../../libmsg/inc/us/RpcServer.hpp) | **P3修复**: `_dispatch()` 区分 `_route` 字段缺失和类型不符的错误信息(P3-2) |
|
||||
| [Msg.hpp](../../libmsg/inc/us/Msg.hpp) | **文档**: `pmsg_send` 添加 SO_SNDTIMEO 前置条件警告(L-10) |
|
||||
|
||||
### 2026-08-07(第三轮审计修复)
|
||||
|
||||
@@ -136,8 +136,8 @@
|
||||
|
||||
| 文件 | 变更内容 |
|
||||
| --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [MsgServer.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/MsgServer.hpp) | **P1修复**: `_accept_client()` 对新连接设置 `SO_SNDTIMEO=5s`,慢客户端不读数据时 send 超时抛异常,防服务级 DoS(P1-2);**P2修复**: `reply()` 发送失败标记 `_failed`,由主循环清理连接(P2-6) |
|
||||
| [RpcClient.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/RpcClient.hpp) | **P3修复**: `call()` 调用 `as_bool()` 前校验 `success` 字段为 bool,类型不符抛 RpcError(P3-1) |
|
||||
| [MsgServer.hpp](../../libmsg/inc/us/MsgServer.hpp) | **P1修复**: `_accept_client()` 对新连接设置 `SO_SNDTIMEO=5s`,慢客户端不读数据时 send 超时抛异常,防服务级 DoS(P1-2);**P2修复**: `reply()` 发送失败标记 `_failed`,由主循环清理连接(P2-6) |
|
||||
| [RpcClient.hpp](../../libmsg/inc/us/RpcClient.hpp) | **P3修复**: `call()` 调用 `as_bool()` 前校验 `success` 字段为 bool,类型不符抛 RpcError(P3-1) |
|
||||
|
||||
### 2026-08-07(第二轮审计修复)
|
||||
|
||||
@@ -145,11 +145,11 @@
|
||||
|
||||
| 文件 | 变更内容 |
|
||||
| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Msg.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/Msg.hpp) | 新增 isValidUtf8()/validateTimeout()/validatePort();recvFrameDeadline 添加参数校验和UTF-8校验;openConnection 添加 port/timeout 校验;pmsg_recv(int) 添加UTF-8校验和文档警告;MsgClient 构造/call 添加参数校验 |
|
||||
| [MsgServer.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/MsgServer.hpp) | **P0修复**: \_close_all_clients() 改为持 send_lock 关闭并 shutdown;构造函数添加全量配置校验 |
|
||||
| [AsyncQueue.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/AsyncQueue.hpp) | 添加 <stdexcept>/<string> 头文件;构造函数校验 handler 非空、batch_size、flush_interval、poll_timeout 范围 |
|
||||
| [RpcClient.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/RpcClient.hpp) | 构造函数校验 timeout、retry_interval 范围 |
|
||||
| [RpcServer.hpp](file:///Users/qingsong/Documents/blackbird/libmsg/inc/us/RpcServer.hpp) | add_route() 校验 name 非空、handler 非空 |
|
||||
| [Msg.hpp](../../libmsg/inc/us/Msg.hpp) | 新增 isValidUtf8()/validateTimeout()/validatePort();recvFrameDeadline 添加参数校验和UTF-8校验;openConnection 添加 port/timeout 校验;pmsg_recv(int) 添加UTF-8校验和文档警告;MsgClient 构造/call 添加参数校验 |
|
||||
| [MsgServer.hpp](../../libmsg/inc/us/MsgServer.hpp) | **P0修复**: \_close_all_clients() 改为持 send_lock 关闭并 shutdown;构造函数添加全量配置校验 |
|
||||
| [AsyncQueue.hpp](../../libmsg/inc/us/AsyncQueue.hpp) | 添加 <stdexcept>/<string> 头文件;构造函数校验 handler 非空、batch_size、flush_interval、poll_timeout 范围 |
|
||||
| [RpcClient.hpp](../../libmsg/inc/us/RpcClient.hpp) | 构造函数校验 timeout、retry_interval 范围 |
|
||||
| [RpcServer.hpp](../../libmsg/inc/us/RpcServer.hpp) | add_route() 校验 name 非空、handler 非空 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# liblogc — 统一集中式日志客户端(C++ 版)
|
||||
|
||||
C++20 统一日志客户端库,对应 Python 侧的 `log_client.py`:通过 pymsg/TCP 调用 `db2:8005` 的 `execute` 路由,逐条 INSERT 到 `Logs` 表,实现集中式日志收集。
|
||||
|
||||
命名空间 `qing`,库文件 `libus_logc.so`,头文件安装至 `/usr/include/us/LogC.hpp`。被 `ca` / `core` / `gateway` / `captcha2` / `smtp3` 等 C++ 服务依赖。
|
||||
|
||||
## 设计要点
|
||||
|
||||
- **异步非阻塞**:基于 `pmc::net::AsyncQueue` 内存队列 + 后台线程批量推送,不阻塞业务。
|
||||
- **缓冲批量**:队列满 50 条或超时 2 秒自动 flush。
|
||||
- **背压保护**:队列上限 10000 条,满时丢弃最旧日志,防止内存无限增长。
|
||||
- **级别过滤**:`set_level()` 设定阈值,低于阈值的日志直接丢弃。
|
||||
- **fail-safe**:db2 不可用时静默丢弃(仅 stderr 提示),绝不影响业务。
|
||||
- **可配置**:`set_endpoint()` / `set_service_name()`,各服务复用同一份库。
|
||||
|
||||
## 用法
|
||||
|
||||
```cpp
|
||||
#include <us/LogC.hpp>
|
||||
|
||||
// 启动时配置(默认 127.0.0.1:8005)
|
||||
qing::LogC::instance().set_endpoint("127.0.0.1", 8005);
|
||||
qing::LogC::instance().set_service_name("gateway-log");
|
||||
qing::LogC::instance().set_level("warn");
|
||||
|
||||
qing::LogC::instance().info("gateway", "启动完成");
|
||||
qing::LogC::instance().error("gateway", "连接失败", std::nullopt, R"({"errno":111})");
|
||||
|
||||
// 进程退出前调用(幂等)
|
||||
qing::LogC::instance().shutdown();
|
||||
```
|
||||
|
||||
## 构建安装
|
||||
|
||||
```bash
|
||||
bash _set.sh
|
||||
```
|
||||
@@ -0,0 +1,10 @@
|
||||
# libtry — 嵌入式脚本解释器
|
||||
|
||||
基于 C 语言手写的教学级脚本解释器(~741 行),魔改自 GitHub 上的 tryC 项目,用于解析 `.try` 脚本,设计目标为嵌入式操作界面 shell。
|
||||
|
||||
- **零依赖**:仅标准 C 库 + `console.h` 输出接口。
|
||||
- **递归下降**:手写词法/语法/执行引擎,边解析边执行。
|
||||
- **宽字符**:`wchar_t` 支持中文/多语言脚本。
|
||||
- **嵌入式 API**:`init_tryc` / `enqueue_tryc` / `eval_tryc` / `free_tryc` 四个核心入口(单文件 [try.c](try.c) + `console.h` 输出接口)。
|
||||
|
||||
详细技术手册(含局限性与改进路线)见 [README.robot.md](README.robot.md)。
|
||||
+13
-13
@@ -580,20 +580,20 @@ puts("1");
|
||||
|
||||
| ID | 位置 | 描述 | 影响 |
|
||||
|----|------|------|------|
|
||||
| L1 | [L20](file:///Users/qingsong/micro_servers/libtry/try.c#L20) | **缓冲区大小固定**:`POOLSIZE = 128` 字节,无法修改 | 长脚本将溢出 |
|
||||
| L2 | [L702](file:///Users/qingsong/micro_servers/libtry/try.c#L702) | **`__exit()` 死循环**:`while(1);` 错误时直接挂死程序 | 无法恢复 |
|
||||
| L3 | [L186](file:///Users/qingsong/micro_servers/libtry/try.c#L186) | **字符串内存泄漏**:`malloc` 分配的字符串在重新赋值时未释放 | 长期运行泄漏 |
|
||||
| L4 | [L528](file:///Users/qingsong/micro_servers/libtry/try.c#L528) | **数组越界**:无越界检查 | 未定义行为 |
|
||||
| L1 | [L20](try.c#L20) | **缓冲区大小固定**:`POOLSIZE = 128` 字节,无法修改 | 长脚本将溢出 |
|
||||
| L2 | [L702](try.c#L702) | **`__exit()` 死循环**:`while(1);` 错误时直接挂死程序 | 无法恢复 |
|
||||
| L3 | [L186](try.c#L186) | **字符串内存泄漏**:`malloc` 分配的字符串在重新赋值时未释放 | 长期运行泄漏 |
|
||||
| L4 | [L528](try.c#L528) | **数组越界**:无越界检查 | 未定义行为 |
|
||||
|
||||
### 🟡 中等问题
|
||||
|
||||
| ID | 位置 | 描述 |
|
||||
|----|------|------|
|
||||
| L5 | [L598](file:///Users/qingsong/micro_servers/libtry/try.c#L598) | **`puts` 实现存疑**:原 `wprintf` 被注释,改用 `printtovga` |
|
||||
| L6 | [L518](file:///Users/qingsong/micro_servers/libtry/try.c#L518) | **`clearThis()` 被注释**:作者注释说"不知为何需要注释了才能跑" |
|
||||
| L7 | [L706](file:///Users/qingsong/micro_servers/libtry/try.c#L706) | **文件模式仅限 `_DEBUG`**:正常构建时 `main()` 不编译 |
|
||||
| L8 | [L103](file:///Users/qingsong/micro_servers/libtry/try.c#L103) | **栈缓冲区溢出风险**:`nameBuffer[16]` 但标识符长度限制由 `MAXNAMESIZE=16` 控制 |
|
||||
| L9 | [L21](file:///Users/qingsong/micro_servers/libtry/try.c#L21) | **符号表大小固定**:`SYMTABSIZE = 128` 个符号 |
|
||||
| L5 | [L598](try.c#L598) | **`puts` 实现存疑**:原 `wprintf` 被注释,改用 `printtovga` |
|
||||
| L6 | [L518](try.c#L518) | **`clearThis()` 被注释**:作者注释说"不知为何需要注释了才能跑" |
|
||||
| L7 | [L706](try.c#L706) | **文件模式仅限 `_DEBUG`**:正常构建时 `main()` 不编译 |
|
||||
| L8 | [L103](try.c#L103) | **栈缓冲区溢出风险**:`nameBuffer[16]` 但标识符长度限制由 `MAXNAMESIZE=16` 控制 |
|
||||
| L9 | [L21](try.c#L21) | **符号表大小固定**:`SYMTABSIZE = 128` 个符号 |
|
||||
|
||||
### 🟢 轻微问题
|
||||
|
||||
@@ -609,7 +609,7 @@ puts("1");
|
||||
|
||||
#### 优先级 1(安全相关)
|
||||
|
||||
1. **修复数组越界**:在 [L528](file:///Users/qingsong/micro_servers/libtry/try.c#L528) 添加检查
|
||||
1. **修复数组越界**:在 [L528](try.c#L528) 添加检查
|
||||
```c
|
||||
if (index < 0 || index >= s->value) {
|
||||
printtovga(L"Array index out of bounds\n");
|
||||
@@ -650,7 +650,7 @@ puts("1");
|
||||
|
||||
### 8.1 添加新关键字
|
||||
|
||||
在 [init_tryc()](file:///Users/qingsong/micro_servers/libtry/try.c#L650) 中添加:
|
||||
在 [init_tryc()](try.c#L650) 中添加:
|
||||
|
||||
```c
|
||||
// 1. 在 enum 中添加新 token 类型
|
||||
@@ -678,7 +678,7 @@ else if (token == NewKeyword) {
|
||||
|
||||
### 8.2 添加新运算符
|
||||
|
||||
在 [next()](file:///Users/qingsong/micro_servers/libtry/try.c#L85) 中添加识别逻辑:
|
||||
在 [next()](try.c#L85) 中添加识别逻辑:
|
||||
|
||||
```c
|
||||
// 例如:+= 运算符
|
||||
@@ -690,7 +690,7 @@ else if (token == L'+') {
|
||||
}
|
||||
```
|
||||
|
||||
在 [statement()](file:///Users/qingsong/micro_servers/libtry/try.c#L466) 中添加执行逻辑。
|
||||
在 [statement()](try.c#L466) 中添加执行逻辑。
|
||||
|
||||
### 8.3 自定义输出
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# memdb — 内存数据库模板(实验)
|
||||
|
||||
基于 C++ 模板的进程内内存数据库(`include/memdb.hpp`),支持键值列、时间戳、索引与惰性删除。
|
||||
|
||||
> **状态:实验性,未完成**。仅含模板头与空 `main`,暂无实际接入方,仅供后续 DB 层设计参考。
|
||||
@@ -158,10 +158,10 @@ pymsg/
|
||||
|
||||
| 语言 | 文件 | 说明 |
|
||||
|------|------|------|
|
||||
| Python | [pymsg/__init__.py](file:///Users/qingsong/micro_servers/pymsg/pymsg/__init__.py) | 主实现 |
|
||||
| C++ | [gateway/inc/Msg.hpp](file:///Users/qingsong/micro_servers/gateway/inc/Msg.hpp) | gateway 使用 |
|
||||
| Go | [waf/internal/logclient/logclient.go](file:///Users/qingsong/micro_servers/waf/internal/logclient/logclient.go) | waf 使用 |
|
||||
| Python (黑盒) | [tests/blackbox/helpers.py](file:///Users/qingsong/micro_servers/tests/blackbox/helpers.py) | 纯 stdlib 测试实现 |
|
||||
| Python | [pymsg/__init__.py](pymsg/__init__.py) | 主实现 |
|
||||
| C++ | [gateway/inc/Msg.hpp](../libmsg/inc/us/Msg.hpp) | gateway 使用 |
|
||||
| Go | [waf/internal/logclient/logclient.go](../waf/internal/logclient/logclient.go) | waf 使用 |
|
||||
| Python (黑盒) | [tests/blackbox/helpers.py](../tests/blackbox/helpers.py) | 纯 stdlib 测试实现 |
|
||||
|
||||
### 3.3 代码索引
|
||||
|
||||
@@ -797,10 +797,10 @@ Modes:
|
||||
|
||||
| 语言 | 文件 | 类型 |
|
||||
|------|------|------|
|
||||
| Python | [pymsg/__init__.py](file:///Users/qingsong/micro_servers/pymsg/pymsg/__init__.py) | 主实现 |
|
||||
| Python | [tests/blackbox/helpers.py](file:///Users/qingsong/micro_servers/tests/blackbox/helpers.py) | 测试客户端 |
|
||||
| C++ | [gateway/inc/Msg.hpp](file:///Users/qingsong/micro_servers/gateway/inc/Msg.hpp) | gateway 客户端 |
|
||||
| Go | [waf/internal/logclient/logclient.go](file:///Users/qingsong/micro_servers/waf/internal/logclient/logclient.go) | waf 客户端 |
|
||||
| Python | [pymsg/__init__.py](pymsg/__init__.py) | 主实现 |
|
||||
| Python | [tests/blackbox/helpers.py](../tests/blackbox/helpers.py) | 测试客户端 |
|
||||
| C++ | [gateway/inc/Msg.hpp](../libmsg/inc/us/Msg.hpp) | gateway 客户端 |
|
||||
| Go | [waf/internal/logclient/logclient.go](../waf/internal/logclient/logclient.go) | waf 客户端 |
|
||||
|
||||
### D. 参考资源
|
||||
|
||||
|
||||
Reference in new issue
Block a user