## 代码审查报告
**审查文件**:e/admin/ecmsmod.php
**编程语言**:PHP
**代码行数**:412 行
**问题总数**:3 个(致命 0 / 严重 1 / 警告 1 / 建议 1)
## 严重问题(建议修复)
### 问题1:ehash 校验缺失导致 CSRF 风险
**位置**:DoEditMod 函数 / 第 88-102 行
**原代码**:
```php
if($_POST['enews']=='EditMod'){ ... } // 未校验 hCheckEcmsRHash()
```
**问题描述**:后台写操作未做 rhash 校验,可被跨站请求伪造触发非预期修改。
**影响**:攻击者可构造页面诱导管理员点击,静默修改模型配置。
**修复建议**:
```php
hCheckEcmsRHash();
if($_POST['enews']=='EditMod'){ ... }
```
## 警告与建议
- 第 130 行 `fetch1()` 未做 false 守卫,建议 `?: []`。
## 审查总结
- **整体评分**:82/100
- **优先修复**:问题1(上线前必须修)
审查前先检查代码是否符合spec:
无spec:提示建议在审查后使用 spec-driven-development 补全spec
✓ Spec一致性检查:
- Scenario 1: [通过/失败] — [说明]
- Scenario 2: [通过/失败] — [说明]
检查代码是否符合项目记忆中的规范:
| 维度 | 检查内容 | 权重 |
|---|---|---|
| Bug风险 | 空指针、数组越界、资源未释放、并发问题 | 30% |
| 安全性 | SQL注入、XSS、敏感信息硬编码、权限绕过 | 25% |
| 性能 | 时间复杂度、内存泄漏、N+1查询、循环内IO | 20% |
| 可维护性 | 命名规范、函数长度、圈复杂度、重复代码 | 15% |
| 最佳实践 | 语言特性利用、设计模式、错误处理 | 10% |
| Karpathy维度 | 简洁优先、精准修改、编码前思考 | 附加 |
小片段快速审查模式:
当用户只提供单个函数、短代码片段或明确要求“快速看看”时,先按以下四象限完成轻量审查;发现高风险问题后再展开完整分级报告:
| 快速象限 | 检查重点 | 输出要求 |
|---|---|---|
| 代码规范与可读性 | 命名、缩进、函数长度、嵌套层级、注释有效性 | 只指出影响理解或维护的具体问题 |
| 潜在 Bug | 边界条件、空值处理、数组索引、资源释放、并发 | 必须说明触发条件和可能后果 |
| 性能分析 | 算法复杂度、重复计算、循环内 IO/SQL/网络请求 | 能量化则量化,不能量化则标注原因 |
| 安全性考量 | 注入、XSS、敏感信息、权限校验、反序列化风险 | 命中即提升为严重或致命候选 |
快速模式不得降低审查标准;只是压缩输出篇幅,不省略 Bug、安全和性能判断。
在常规审查之外,按Karpathy编码哲学进行专项审查:
简洁优先(Simplicity First):
精准修改(Surgical Changes)(针对修改的代码):
编码前思考(Think Before Coding):
Karpathy维度问题不纳入 severity 分级,单独标注为 「Karpathy建议」。
| 级别 | 说明 | 必须修复 |
|---|---|---|
| 致命(Critical) | 会导致系统崩溃、数据丢失、安全漏洞 | 是 |
| 严重(Major) | 明显Bug、性能严重下降、安全隐患 | 是 |
| 警告(Warning) | 潜在风险、代码异味、不符合规范 | 建议 |
| 建议(Suggestion) | 可优化点、风格问题、最佳实践 | 可选 |
对每个问题:
Karpathy建议的修复优先级:
审查完成后,将发现的问题和规范沉淀到项目记忆(参见 project-memory-management.md):
帮我快速审查这段 PHP 代码。
重点:SQL 注入、XSS、PHP 8.2 兼容、是否有明显逻辑 Bug。
范围:只看我贴出的函数,不扩展到其他文件。
输出:按阻塞/严重/一般/建议分级;如果没有明显问题,请明确写“未发现阻塞问题”。
验证:说明是否需要 php -l 或单元测试。
优先加载:code-review.md;如果出现数据库访问,再协同 mysql-database.md。
帮我审查这个订单导出功能的改动。
范围:Controller、Service、导出任务、前端轮询接口。
重点:权限、CSRF、Init-Step-Poll、防重复提交、超时恢复、错误提示。
要求:先列阻塞问题,再列可优化项;不要直接重构,除非影响主线可用性。
优先加载:code-review.md、api-design.md、test-generation.md。
## 代码审查报告
**审查文件**:[文件名]
**编程语言**:[语言]
**代码行数**:[X行]
**问题总数**:[X]个(致命[X] / 严重[X] / 警告[X] / 建议[X])
## 致命问题(必须修复)
### 问题1:[问题标题]
**位置**:[函数名/行号范围]
**原代码**:
```[代码片段]```
**问题描述**:[具体说明]
**影响**:[可能导致什么后果]
**修复建议**:
```[修复后的代码]```
## 严重问题(建议修复)
### 问题N:[问题标题]
...
## 警告与建议
...
## 审查总结
- **整体评分**:[X]/100
- **主要风险**:[一句话总结]
- **优先修复**:[Top 3问题]
- **正向评价**:[代码中的亮点]
无明显问题输出规范:
如果完成审查后未发现有效问题,不得强行制造建议,必须明确输出:
## 代码审查报告
**审查结论**:未发现明显问题
**已覆盖维度**:可读性 / Bug风险 / 性能 / 安全性 / 项目规范
**残余风险**:[缺少运行环境、依赖上下文、测试结果或业务规则时说明;无则写"无"]
**建议验证**:[可选的测试、lint、静态分析或人工验收步骤]
当用户要求代码优化、性能优化、架构优化、慢接口排查,或审查中发现性能嫌疑点时,追加以下检查:
| 反模式 | 审查信号 | 风险判定 | 修复方向 |
|---|---|---|---|
| N+1 查询 | 循环体内出现数据库查询、ORM find/select/where、外部 API 请求 |
数据量增长时调用次数线性放大,严重时可导致超时或连接池耗尽 | 批量查询、预加载、JOIN、聚合、一次性查询后内存分组 |
| 同步阻塞 I/O | 高并发接口中出现同步文件读写、同步网络调用、长 CPU 任务 | 请求线程被阻塞,吞吐下降,尾延迟升高 | 异步化、后台任务、队列、流式处理、连接池 |
| 无界缓存/内存泄漏 | 全局 Map/dict/Object/static 集合持续写入,缺少 TTL、容量、清理 | 长时间运行后内存持续增长,可能 OOM | TTL、容量上限、LRU、生命周期清理、弱引用或托管缓存 |
| 无上限数据拉取 | 列表接口无分页、.all() / findAll() / SELECT * 拉全量 |
大数据量下内存、网络和数据库压力失控 | 强制分页、游标、最大 page size、按需字段 |
| 索引失效 | DATE(column)、LIKE '%xxx'、隐式类型转换、函数包裹索引列 |
查询退化为全表扫描或大范围扫描 | 改写查询条件、调整索引、提供 EXPLAIN 验证 |
性能问题只允许在有证据时定性为结论;静态扫描命中但缺少 benchmark、profile、EXPLAIN 或日志时,必须标注为"疑似"并给出最小验证动作。
当用户要求实现或审查长任务(批量导入/导出/生成静态页/重建索引/采集同步/清理缓存/>3 秒或 >100 条处理)时,追加以下检查:
| 反模式 | 审查信号 | 风险判定 | 修复方向 |
|---|---|---|---|
| 单请求同步跑长任务 | 批量操作在单个 HTTP 请求内同步执行,无分批、无进度返回 | PHP 超时/内存耗尽、用户无进度感知、无法取消 | 改 Init → Step → Poll:Init 建任务、Step 分批、Poll 查状态 |
| Step 非幂等 | Step 重试会重复处理同一批数据 | 数据重复、状态错乱 | 用 last_id/游标/offset 保证每批唯一,重复调用结果一致 |
| 进度仅存内存 | 任务进度存 PHP 变量/session 而非 DB/缓存/任务文件 | 进程重启/多实例下进度丢失,Poll 永远 running |
进度持久化到数据库/缓存/任务文件,不能只依赖 PHP 内存 |
| 无取消入口 | 前端有取消按钮但后端无 cancel 端点或忽略取消标记 | 用户无法中止错误任务,资源空耗 | 提供 cancel 端点,Step 检测取消标记后优雅退出 |
| 无超时/僵尸保护 | 无 updated_at 阈值检测,running 任务卡死无兜底 |
僵尸任务永远 running,前端轮询死循环 |
Poll 检测 running 超阈值→标记 failed(僵尸)或允许 resume |
| 并发不安全 | 多 Step 并发/多用户操作同任务无锁 | 数据竞争、覆盖 | 任务级锁或串行 Step |
长任务问题只允许在有实现证据时定性为结论;静态扫描命中但缺少接口契约、进度持久化证据或取消实现时,必须标注为"疑似"并给出最小验证动作。
| 检查项 | 判定标准 |
|---|---|
| 查询路径 | 索引必须对应 WHERE/JOIN/ORDER BY/GROUP BY/分页路径 |
| 联合索引顺序 | 必须说明等值、区分度、范围、排序、覆盖字段顺序 |
| EXPLAIN | 高频/慢查询必须提供 key/type/rows/Extra 证据 |
| 覆盖索引 | 只允许覆盖高频小字段列表,禁止塞入大字段 |
| 冗余索引 | 检查 (a) 与 (a,b)、唯一索引与普通索引重复 |
| 写入成本 | 新增索引必须评估 INSERT/UPDATE/DELETE 成本 |
| 删除索引 | 必须有依赖 SQL、风险说明和回滚 SQL |
当审查对象为 PHP+MySQL CMS 代码时,在「多维度审查」之外追加以下专项检查:
| 检查项 | 检查方法 | 判定标准 |
|---|---|---|
| SQL 注入(CMS 上下文) | 检查是否使用 CMS 官方数据访问层,是否存在 $_GET/$_POST 直拼 SQL |
必须使用参数绑定或 CMS API |
| XSS(CMS 模板) | 检查模板输出是否默认转义,PHP 直接输出是否 htmlspecialchars |
所有用户输入输出前必须转义 |
| CSRF | 检查表单提交和状态变更操作是否有 Token 验证 | POST/PUT/DELETE 必须验证 CSRF Token |
| 文件上传 | 检查是否有 MIME 校验 + 扩展名白名单 + 重命名 + 非执行目录 | 四项缺一不可 |
| 反序列化 | 检查是否有 unserialize() 对不可信数据的调用 |
禁止,改用 JSON |
| 密码存储 | 检查密码是否用 password_hash()/password_verify() |
禁止 MD5/SHA1 |
| Include 注入 | 检查是否有 include $user_input |
路径必须白名单或固定 |
| 数组键引号 | 检查 $arr[key] 无引号访问 |
必须加引号 $arr['key'],PHP 8 致命错误 |
| 类型比较 | 检查是否使用 == 而非 === |
统一 === |
详见 cms-development.md 安全红线章节。
当审查对象为 Java/Spring 代码时,在「多维度审查」之外追加以下专项检查:
| 检查项 | 检查方法 | 判定标准 |
|---|---|---|
| 正确性 | 检查边界条件、空值、集合访问、Optional 使用、异常路径 | 不得依赖隐式非空假设,异常路径必须可解释 |
| 安全性 | 检查 SQL 拼接、XSS、反序列化、敏感信息、鉴权注解 | MyBatis 禁止 ${} 拼接外部输入,接口必须有权限边界 |
| 性能 | 检查 N+1 查询、循环内 IO/SQL、重复对象创建、分页缺失 | 高频路径必须说明复杂度和数据量影响 |
| 健壮性 | 检查异常处理、日志上下文、事务边界、连接池/超时 | 禁止空 catch;事务边界必须在业务方法层清晰表达 |
| 并发安全 | 检查共享可变状态、线程池配置、锁粒度、CompletableFuture Executor | 共享状态必须有线程安全策略,线程池不得使用隐式默认配置 |
| Spring 分层 | 检查 Controller/Service/Repository/DTO/Entity 职责 | Controller 不写业务细节,Entity 不直接作为长期 API 响应 |
| JVM 风险 | 检查大对象、缓存无界、线程泄漏、GC 压力和资源关闭 | 性能判断必须有耗时、GC、线程、堆或连接池证据 |
详见 java-development.md 的源码分析、Spring Boot 结构、并发与 JVM 章节。
当用户要求审查图遍历、环检测、递归、状态机、拓扑排序、依赖解析,或发现递归/DFS 代码时,在「多维度审查」之外追加以下专项检查:
| 检查项 | 检查方法 | 判定标准 |
|---|---|---|
| 不变量(invariant) | 检查是否显式声明了「不变量命题 + 终止度量 + 守恒关系」三件套(推导方法见 karpathy-coding-guidelines.md 不变量推导三步法),且实现能断言它们 |
关键算法必须交出三件套并过自检(可判定/初始成立/归纳保持/充分性),不能只靠"流程跑通"或"写了个不变量" |
| DFS 回边判定 | 检查回边识别是否基于"在递归栈中"而非"已访问",避免把横叉边/前向边误判为环 | 回边必须只在当前 DFS 路径中闭合才计为环 |
| 方向语义解耦 | 检查遍历方向(down/up/both)与边有向性是否被编码耦合 | 遍历方向必须独立于边的有向性,反方向遍历结果应一致 |
| 结构边界覆盖 | 检查测试是否覆盖 0/1 节点、自环、互环、三环、菱形 DAG、平行边 | 见 test-generation.md 算法边界用例清单 |
| 死代码检测 | 检查是否存在永不被调用的函数/分支、恒真/恒假条件、不可达代码 | 标记死代码,要求删除或说明保留理由 |
图与递归类缺陷的典型漏网形态是"流程跑通但结果错",审查必须断言具体结果(环数、环成员、是否标记、是否重复),不得仅以"能运行"判定正确。
code-generation 产出的代码时,重点验证生成是否偏离 Spec 约束和编码规范karpathy-coding-guidelines 深入评估代码是否符合编码哲学frontend-design 的交互状态、响应式、可访问性和浏览器验证清单bug-diagnosis 深入分析根因refactoring 获取详细重构方案test-generation 补充回归测试cms-development.md 的安全红线和兼容性检查java-development.md 的分层结构、异常处理、并发和 JVM 检查mysql-database.md| 步骤 | 失败条件 | 回退目标 | 最大重试 | 不可恢复时升级路径 |
|---|---|---|---|---|
| 第一步:Spec一致性检查 | Spec文档不可用或无关联 | 跳过一致性检查,从代码反推预期行为 | 0 | 标注"无Spec对照",仅审查内部一致性和通用规范 |
| 第二步:项目规范检查 | 项目规范文档缺失或代码文件不可读 | 跳过规范加载,直接分析代码结构,标注"规范缺失" | 2 | 基于通用最佳实践审查,建议补充项目规范 |
| 第三步:代码理解 | 代码量过大超出分析能力 | 分批审查,逐文件输出,最后汇总 | 0(分批) | 告知用户分批结果,建议缩小审查范围 |
| 第四步:多维度审查 | 某维度缺少足够上下文 | 标注"待验证",跳过该维度 | 1 | 输出已覆盖维度的审查结果,缺项标注为"建议补充后重新审查" |
| 第五步:Karpathy维度审查 | 简洁性判断主观争议 | 标注为"建议评估",附正反观点 | 0 | 交由用户/团队讨论决策 |
| 第六步:问题分级 | 严重性边界模糊(中/高难判) | 默认升级一级(保守策略),标注"存疑" | 1 | 所有存疑项统一标记为"需确认" |
| 第七步:生成修复建议 | 修复方案可能引入新问题 | 标注风险提示,建议回归测试范围 | 2 | 输出修复建议+单元测试覆盖要求,由开发者自行实施 |
| 第八步:记录到项目记忆 | 项目记忆系统不可用 | 输出审查报告和规范沉淀到本地文件 | 1 | 标注"审查结果未沉淀",提示用户手动保存 |