zephyrrtos.cnZephyr 生态 · 中国驱动软件系统
标准 · 代码评审 · 40 条

代码评审规则标准

这不是一份「最佳实践散文」,而是评审引擎真正执行的规则目录:40 条规则, 每条都写清判定依据(为什么算问题)、修复建议(怎么改)、置信度(certain = 文本级可判 / heuristic = 跨函数推断,一律降级「待人工确认」) 与等级。本页可搜索、可按域 / 等级 / 置信度筛选;数据源只有一份—— 评审引擎的 review/rules.py,页面由它导出生成,不手抄。

通道 M(机器可查)36 条 · 通道 C(上游合规)4 条 · 默认等级 MAJOR 15 / MINOR 25 · 确定性 21 / 启发式 19 · 40 条附「为什么容易误报」

等级契约与命名

规则 IDR-<域>-<序号>,域 ∈ CX / DRV / DT / KCF / KRN / MEM / PY / SEC / UP(KRN 内核并发 / DRV 驱动 / DT 设备树 / KCF Kconfig / MEM 内存 / SEC 安全 / UP 上游合规 / PY 脚本 / CX 复杂度)
等级策略(不可协商)
  • 机器规则最高 MAJOR;BLOCK 只能由评审人确认后给出
  • 置信度 heuristic 的规则一律降级 INFO「待人工确认」
  • 无 file:line + 代码片段证据的结论直接丢弃
  • 风格偏好不得写 MAJOR
置信度certain = 同一语句/同一代码块内可判定,可报 MAJOR;heuristic = 跨函数/跨文件推断,一律降级 INFO「待人工确认」,不进 MAJOR/BLOCK
本版口径zephyrrtos.cn 代码评审规则标准 · v1.1.0 · 数据源 api-server/scripts/review/rules.py (RULES) + review/false_positives.py · 生成于
机器只负责「能核对的部分」:报告里每条结论都必须带 文件:行 + 代码片段 + 判据 + 建议; 拿不出证据的结论由引擎直接丢弃。BLOCK 结论只能由评审人确认后给出。

查询 40 条规则

输入 ID / 关键字(标题、依据、建议都能搜),或按域、等级、置信度、通道筛选;筛选即隐藏/显示下面已渲染的条目,不需要联网。每条规则下面的「为什么容易误报」点开即读——它写的是这条规则在什么情况下会误伤、评审人该拿什么去确认,属于人写的编辑说明,不参与引擎判定。

共 40 条(无筛选)

R-CX-001 MAJOR certain 通道 M CX · 复杂度与结构

圈复杂度超阈

判定依据:圈复杂度越高,独立路径越多,测试覆盖与人工评审越不可能做到充分。上游 6105 个函数的实测分布:p50=2、p90=9、p99=22、max=50。

修复建议:按职责拆分函数(提取子函数 / 用表驱动替代长 switch / 早返回消除嵌套);配合 ztest 覆盖分支。

参考:McCabe 圈复杂度;标定数据见 review/calibrate.py · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:表驱动 / 状态机 switch、寄存器位运算展开、宏生成代码会把圈复杂度算高;阈值 30 对 switch 型代码偏严。

人工怎么确认:看结构分析里的热点表与整文件分布,确认高 CC 是否来自 switch/宏展开而非业务分支。

R-CX-002 MINOR certain 通道 M CX · 复杂度与结构

函数过长

判定依据:超长函数通常同时是国内核复杂度与栈占用的来源;上游实测 p90=41、p99=94、max=245 SLOC。

修复建议:按「初始化 / 传输 / 收尾」拆分;把寄存器操作抽成小函数;错误处理统一收口(允许 goto cleanup)。

参考:标定数据见 review/calibrate.py · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:probe / 寄存器初始化 / dump 这类「读表写表」函数天然长,宏展开也计入行数。

人工怎么确认:看函数主体是否以寄存器读写为主;若拆分只会制造碎片,可在提交说明里写清理由。

R-CX-003 MINOR certain 通道 M CX · 复杂度与结构

控制流嵌套过深

判定依据:嵌套越深越容易在评审里漏掉某个分支的失败路径;上游实测 p99=4、max=9。

修复建议:用早返回/早继续(`if (!ok) return -EINVAL;`)把分支拍平;把内层循环体抽成函数。

参考:标定数据见 review/calibrate.py · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:多层 for + 位校验、嵌套 #if 展开会虚增嵌套深度。

人工怎么确认:确认嵌套是否来自预处理分支;预处理导致的嵌套不算控制流复杂度。

R-CX-004 MINOR certain 通道 M CX · 复杂度与结构

参数过多

判定依据:参数过多通常是「一个结构体该被抽出来」的信号,也容易在调用处顺序写错;上游实测 p99=6、max=10。

修复建议:把强相关参数聚成 config/request 结构体;公共 API 用 `struct x_config *`。

参考:标定数据见 review/calibrate.py · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:内核 API 本身签名参数多(k_timer_init 等)会连带被判;真正风险是「同类参数相邻易写错序」。

人工怎么确认:关注是否多于 5 个且同类型相邻(如两个指针/两个超时),这才是易错点。

R-CX-005 MINOR heuristic 通道 M CX · 复杂度与结构

密集使用 goto

判定依据:Zephyr 允许用 goto 做统一清理(上游约 3.2% 的函数含 goto),但单个函数里大量 goto 会让控制流难以追踪。

修复建议:保留「错误退出统一走 cleanup」的用法;把跳转目标过多的函数按阶段拆分。

参考:Zephyr coding style:goto 仅用于清理路径 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:Zephyr 官方惯用 goto 做统一 cleanup(上游约 3.2% 函数含 goto),单入口多出口是合法模式。

人工怎么确认:只数「跳转目标」数量;cleanup 型 goto 不算密集使用。

R-CX-006 MINOR heuristic 通道 M CX · 复杂度与结构

文件内复杂度集中

判定依据:一个文件里多个高复杂度函数,通常说明该模块缺少分层:改动一处就要重新理解整片逻辑。

修复建议:按功能拆文件(如 probe / io / pm 分文件),或把公共逻辑下沉到 driver 公共层。

参考:标定数据见 review/calibrate.py · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:单一主题的大文件(完整驱动 + 寄存器表)会天然集中,生成代码也会。

人工怎么确认:看是否能按 probe / io / pm 拆;纯寄存器表或生成代码不构成问题。

R-DRV-001 MAJOR certain 通道 M DRV · 驱动模型 / device API

硬编码外设基地址

判定依据:硬编码 0x4xxxxxxx 这类外设基地址绕过了 Devicetree,同一驱动无法跨 SoC 复用,且与 DTS 不一致时表现为静默读写错寄存器。

修复建议:从 DT 取:`DEVICE_DT_GET`/`DT_REG_ADDR(DT_NODELABEL(x))`,或在 binding 里声明 reg;地址只出现在 board DTS 中。

参考:zephyr-rtos skill references/50-review.md P1 第 1 条 · 适用 profile:app / driver / subsys / kernel / board / test

为什么容易误报 · 评审人怎么确认

误报场景:位掩码常量(0x4xxxxxxx 也像地址)、测试夹具、注释里的历史地址会被误伤。

人工怎么确认:确认是 MMIO 访问而不是位域/掩码;地址只应出现在 board DTS。

R-DRV-002 MAJOR certain 通道 M DRV · 驱动模型 / device API

device_is_ready() 的结果被丢弃

判定依据:设备未就绪时继续调用 API,会踩空驱动 data 指针或返回不可预期的错误码,是 Zephyr 上最常见的启动期崩溃原因。

修复建议:`if (!device_is_ready(dev)) { LOG_ERR("%s not ready", dev->name); return -ENODEV; }`

参考:zephyr-rtos skill references/50-review.md P0 第 4 条 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:`(void)device_is_ready(dev)` 显式忽略(调用方已有前置校验),或仅用于打日志。

人工怎么确认:看是否有前置断言/上游已校验;确需忽略时写注释说明「已校验」。

R-DRV-003 MINOR heuristic 通道 M DRV · 驱动模型 / device API

声明了 DT_DRV_COMPAT 但没有 DEVICE_DT_INST_DEFINE

判定依据:典型漏配:compatible 声明了但实例没有被实例化注册,表现为 `device_is_ready` 永远失败。

修复建议:补 `DEVICE_DT_INST_DEFINE(...)` + `DT_INST_FOREACH_STATUS_OKAY(...)`,或确认该文件只是公共头。

参考:driver_model.md 驱动开发模板 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:公共头文件、多实例文件(DT_DRV_COMPAT 在 .c、DEFINE 在另一处或宏展开里)会漏看。

人工怎么确认:全文件搜 `DEVICE_DT_INST_DEFINE` 与 `DT_INST_FOREACH_STATUS_OKAY`,含 include 链。

R-DRV-004 MINOR heuristic 通道 M DRV · 驱动模型 / device API

GPIO 引脚号使用魔法数字

判定依据:把引脚号写进代码使同一套逻辑无法换板;引脚属于板级事实,应在 DTS 里。

修复建议:改用 `gpio_dt_spec`:`GPIO_DT_SPEC_GET(node, gpios)` + `gpio_pin_configure_dt(&spec, ...)`。

参考:zephyr-rtos skill references/50-review.md P1 第 1 条 · 适用 profile:app / driver / subsys

为什么容易误报 · 评审人怎么确认

误报场景:board.c / 板级初始化里写死引脚是合理的;samples、tests 里的固定引脚也属预期。

人工怎么确认:看文件位置:board 与 samples/tests 属预期,驱动核心代码才是真问题。

R-DT-001 MAJOR certain 通道 M DT · Devicetree 绑定一致性

DT_INST_PROP 使用了 binding 未声明的属性

判定依据:属性没在 binding(含 include 链)里声明时,`DT_INST_PROP` 会在编译期报 undefined 或取到默认 0,导致静默错误配置。

修复建议:在 `dts/bindings/**/<compatible>.yaml` 的 properties 中补声明(类型 + required + description),或改用已声明的属性名。

参考:dts/bindings 规范 + dt-schema · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:属性经 binding 的 include 链(`*-common.yaml`)声明,或用 vendor 前缀(`x-os,foo`)写在别处。

人工怎么确认:查 binding 的 include 链与 `properties`,不要只看单个 yaml。

R-DT-002 MINOR certain 通道 M DT · Devicetree 绑定一致性

使用了已弃用的 DT 宏

判定依据:旧宏在版本升级中被移除,跨版本编译会失败。

修复建议:`DT_LABEL` → `DEVICE_DT_GET` / `dev->name`;`DT_INST_*_BY_IDX` → `DT_INST_PROP_BY_IDX`;`DT_BUS_LABEL` → `DT_BUS`。

参考:migration-guide · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:旧宏仅用于跨版本 `#if` 隔离时是有意保留;宏名也可能来自上游镜像文件。

人工怎么确认:确认是否已有版本隔离;没有的话按建议替换。

R-KCF-001 MAJOR certain 通道 M KCF · Kconfig 符号规范

Kconfig 符号缺少类型声明

判定依据:没有 bool/tristate/int/hex/string 的 config 块在 Kconfig 解析阶段就不合法,`west build` 会直接报错或符号被当作 bool 处理。

修复建议:在 `config FOO` 下第一行补类型,如 `bool "Enable FOO driver"`。

参考:Zephyr Kconfig 约定 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:类型由被 `source` 的模板 Kconfig 给出,或 `menuconfig` 后面同一块声明。

人工怎么确认:看同文件与被 source 的文件是否已给类型。

R-KCF-002 MINOR certain 通道 M KCF · Kconfig 符号规范

Kconfig 符号缺少 help 说明

判定依据:上游要求每个新符号有 help;缺了不能合入,且用户看不出这个开关干什么。

修复建议:补 `help` 段:一句话讲清启用后果 + 依赖前提 + 默认值理由。

参考:Zephyr Kconfig 约定 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:有 `help` 但缩进/空行不合上游 style;`choice` 下的符号允许省略 help。

人工怎么确认:打开文件确认 help 段真实存在且非空。

R-KCF-003 MINOR heuristic 通道 M KCF · Kconfig 符号规范

Kconfig 符号没有 depends on / default / select

判定依据:没有可见性或默认值的符号会出现在所有配置里,容易被误开;没有依赖时可能被在不支持的平台上启用。

修复建议:至少给 `depends on <所属子系统或 SoC>`;可选的给安全默认值 `default n`。慎用 `select`(会造成隐式依赖链)。

参考:zephyr-rtos skill references/50-review.md P1 第 2 条 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:符号处在 `if FOO` 块内(已有隐含依赖)、或属于有意全局可见的调试开关、或上层已给 default。

人工怎么确认:看是否被 `if` 块包住或上层已约束;全局调试开关可接受。

R-KRN-001 MAJOR heuristic 通道 M KRN · 内核并发 / 中断 / 时间 / 栈

中断上下文中调用了阻塞 API

判定依据:ISR 里阻塞会拉高中断延迟、破坏实时性,严重时触发看门狗复位;k_sleep/k_mutex_lock/k_malloc 等在 ISR 里是未定义行为。

修复建议:改在中断里只做「记录 + 通知」:置标量/写 k_fifo/k_sem_give 唤醒线程,把耗时动作搬进线程;必须的原子操作只用 k_*_isr_ok 系列。

参考:Zephyr Kernel > Interrupts; zephyr-rtos skill references/50-review.md P0 第 1 条 · 适用 profile:app / driver / subsys / kernel

为什么容易误报 · 评审人怎么确认

误报场景:函数里有 `*_isr_ok` 安全变体、或该函数同时被线程调用(调用上下文不在本文件可见)。

人工怎么确认:确认调用路径能否从 ISR 到达;跨文件调用链必须人工跟。

R-KRN-002 MAJOR certain 通道 M KRN · 内核并发 / 中断 / 时间 / 栈

可失败 API 的返回值被丢弃

判定依据:整条语句只有一次调用、结果既没判断也没返回时,失败会被静默吞掉(典型:I2C NACK 后继续用旧数据、互斥锁超时后继续改共享态)。

修复建议:显式判断:`if (ret < 0) { LOG_ERR(...); return ret; }`;确实有意忽略的情况,用 `(void)call(...)` 表明这是决定而不是遗漏。

参考:zephyr-rtos skill references/50-review.md P0 第 4 条 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:显式 `(void)` 忽略、纯查询 API、或返回值已在宏/包装层校验。

人工怎么确认:看是否有 `(void)` 标注或包装层已判错。

R-KRN-003 MINOR heuristic 通道 M KRN · 内核并发 / 中断 / 时间 / 栈

文件级可写 static 变量被多个函数使用,未见同步原语

判定依据:跨线程/ISR 共享的可写全局状态若无 k_mutex/k_spinlock/atomic/irq_lock 保护,会出现撕裂读与竞态;volatile 只保证不被优化掉,不保证原子性。

修复建议:把共享态收进一个 data 结构 + 明确保护手段:线程间用 k_mutex,与 ISR 共享用 k_spinlock 或 atomic_*;纯计数用 atomic_inc。

参考:zephyr-rtos skill references/50-review.md P0 第 3 条 · 适用 profile:app / driver / subsys / kernel

为什么容易误报 · 评审人怎么确认

误报场景:变量只在 init 阶段单线程写、之后只读;或保护手段在另一文件(全局锁)。

人工怎么确认:看写点是否都在启动阶段、是否在别处被 k_mutex 保护。

R-KRN-004 MINOR heuristic 通道 M KRN · 内核并发 / 中断 / 时间 / 栈

未指定超时的阻塞等待

判定依据:K_FOREVER 等待一旦对端失效就是死锁;Zephyr 默认没有看门狗兜底。

修复建议:给出有依据的超时(如 K_MSEC(100))并处理 -EAGAIN;确需永久等待时在注释里说明触发条件与恢复路径。

参考:zephyr-rtos skill references/50-review.md P1 第 2 条 · 适用 profile:app / driver / subsys

为什么容易误报 · 评审人怎么确认

误报场景:设计上必须阻塞到底的等待(如等待链路建立),或由中断在别处唤醒。

人工怎么确认:确认是否有注释写明触发条件与恢复路径;有则可接受。

R-KRN-005 MAJOR heuristic 通道 M KRN · 内核并发 / 中断 / 时间 / 栈

中断上下文中使用了动态内存分配

判定依据:堆分配在 ISR 中不可用/耗时不可控,且碎片化会在长时间运行后暴露为随机失败。

修复建议:改用 k_mem_slab 或静态池;把需要分配的路径挪进线程。

参考:zephyr-rtos skill references/50-review.md P1 第 5 条 · 适用 profile:app / driver / subsys / kernel

为什么容易误报 · 评审人怎么确认

误报场景:包装函数内部改用 `k_mem_slab_alloc`(静态池)不算动态分配;函数也可能只被线程调用。

人工怎么确认:确认调用路径可达 ISR;slab / 静态池不触发本规则。

R-KRN-006 MINOR heuristic 通道 M KRN · 内核并发 / 中断 / 时间 / 栈

忙等循环内没有让出 CPU

判定依据:while(1)/for(;;) 里不让出会把同优先级及更低优先级线程饿死,在协作式调度下直接挂住系统。

修复建议:循环体内加 k_yield()/k_sleep();等待事件应使用 k_sem_take/k_poll 而不是轮询。

参考:zephyr-rtos skill references/50-review.md P1 第 3 条 · 适用 profile:app / driver / subsys

为什么容易误报 · 评审人怎么确认

误报场景:等待寄存器就绪的短自旋(微秒级)在单核上常被接受;`k_busy_wait()` 是合法 API。

人工怎么确认:看循环是否必然退出且时长 < 数百 µs;否则应改事件等待。

R-KRN-007 MINOR heuristic 通道 M KRN · 内核并发 / 中断 / 时间 / 栈

irq_lock() 与 irq_unlock() 数量不匹配

判定依据:忘记解锁会导致后续中断长期被屏蔽;多解锁会让中断状态错乱。函数内锁定次数与解锁次数不等是真问题。

修复建议:成对出现,且每条失败退出路径都要解锁;复杂路径改用 k_spinlock。

参考:zephyr-rtos skill references/50-review.md P0 第 3 条 · 适用 profile:app / driver / subsys / kernel

为什么容易误报 · 评审人怎么确认

误报场景:配对发生在 `#if` 分支或宏内部时,文件级计数会失真。

人工怎么确认:沿「同一条执行路径」数配对,而不是数全文件的出现次数。

R-MEM-001 MAJOR certain 通道 M MEM · 内存 / 缓冲区 / DMA

使用了不安全的字符串函数

判定依据:strcpy/sprintf/gets 没有长度约束,溢出直接踩坏相邻内存;Zephyr 的 checkpatch 会直接判 ERROR。

修复建议:`snprintf(buf, sizeof(buf), ...)`、`strncpy` 后手动补 `\0`,或 `memcpy` + 显式长度校验。

参考:checkpatch STRCPY/SPRINTF; references/50-review.md E 节 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:目标容量已知且足够大、或 strncpy 后手动补 `\0` 的惯用写法。

人工怎么确认:看是否有长度常量与手动补零;`sprintf` 到固定大缓冲仍有溢出风险,不建议放过。

R-MEM-002 MAJOR certain 通道 M MEM · 内存 / 缓冲区 / DMA

线程栈上的大缓冲区

判定依据:Zephyr 线程默认栈只有 1~4 KB,512 B 以上的局部数组极易溢出到相邻栈帧,表现为难复现的花屏/复位。

修复建议:改静态缓冲、`k_mem_slab` 或调用方传入 buffer;必须用局部大数组时显式调大该线程栈并写进注释。

参考:zephyr-rtos skill references/50-review.md P0 第 2 条 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:一次性初始化 / 工具类场景;线程栈已被显式调大(CONFIG_*_STACK_SIZE)。

人工怎么确认:看该线程栈大小配置与调用频率;栈够大且不递归可接受。

R-MEM-003 MINOR heuristic 通道 M MEM · 内存 / 缓冲区 / DMA

DMA 缓冲区未见对齐/缓存维护

判定依据:DMA 缓冲区未按 cache line 对齐(K_MEM_ALIGN/__aligned)或未做 cache clean/invalidate,会在带 D-cache 的核上出现数据不一致,且只在特定时序暴露。

修复建议:缓冲区用 `__aligned(32)` 或 `K_MEM_ALIGN`;非一致性平台在启动 DMA 前 clean、完成后 invalidate。

参考:zephyr-rtos skill references/50-review.md P1 第 5 条 · 适用 profile:driver / subsys / app

为什么容易误报 · 评审人怎么确认

误报场景:平台无 D-cache、或 DMA 为一致性的 SoC;缓冲区由驱动层/DT 保证对齐。

人工怎么确认:看 SoC 是否有 D-cache、DMA mask 是否已配;无 cache 的核不适用。

R-MEM-004 MINOR heuristic 通道 M MEM · 内存 / 缓冲区 / DMA

memcpy/memset 长度来自未校验的参数

判定依据:长度直接取自调用方/报文头而不与目标容量比较,是缓冲区溢出的标准入口。

修复建议:`len = MIN(len, sizeof(dst))`,或先校验 `if (len > sizeof(dst)) return -EINVAL;`。

参考:references/50-review.md A 节「边界/长度/溢出检查」 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:长度是编译期常量,或调用方已保证(同一文件可见)。

人工怎么确认:向上追一层调用方,确认长度已校验;追不到就按风险处理。

R-MEM-005 MINOR heuristic 通道 M MEM · 内存 / 缓冲区 / DMA

堆分配结果未判空

判定依据:k_malloc 在 Zephyr 上是可选 sys_heap 接口,内存紧张时返回 NULL;不判空直接写会导致在 0 地址附近崩溃,且现场极难定位。

修复建议:`buf = k_malloc(n); if (buf == NULL) { return -ENOMEM; }`;控制路径上尽量避免动态分配。

参考:references/50-review.md P1 第 5 条 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:堆未启用时符号不存在;或在非关键路径(一次性初始化)且失败即复位。

人工怎么确认:看堆配置与调用点是否在控制路径上。

R-PY-001 MAJOR certain 通道 M PY · Python 脚本

裸 except(吞掉所有异常)

判定依据:`except:` 会连 KeyboardInterrupt/SystemExit 一起吞掉,真实缺陷变成静默通过;测试脚本里最容易掩盖失败。

修复建议:捕获具体异常(`except (OSError, ValueError) as exc:`),并至少打印出原因;需要重抛就 `raise`。

参考:PEP 8 / Zephyr scripts 约定 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:`except:` 后立即 `raise`(仅做日志/清理)是合法模式。

人工怎么确认:看 except 体内是否 raise 或断言;测试脚本里广捕后断言也可接受。

R-PY-002 MAJOR certain 通道 M PY · Python 脚本

shell=True 或 os.system(命令注入面)

判定依据:参数里出现外部输入时,shell=True / os.system 会导致命令注入;即使当前是内部脚本,改一处调用就会变成攻击面。

修复建议:传列表参数(`subprocess.run([...], check=True)`);必须用 shell 时对每个变量做 `shlex.quote`。

参考:CWE-78;Zephyr scripts 惯例 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:命令串完全由代码常量构成、无外部输入(构建脚本的固定命令)。

人工怎么确认:追参数来源;固定命令改用列表形式即可消除告警。

R-PY-003 MAJOR certain 通道 M PY · Python 脚本

eval / exec

判定依据:把字符串当代码执行,等于把输入变成代码;解析配置应使用 json/yaml/literal_eval。

修复建议:改用 `ast.literal_eval`(仅字面量)或显式解析器;确需 eval 时限定 globals 并记录理由。

参考:CWE-95 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:开发工具里的 `eval` 用于构造闭包或 REPL,输入完全可信。

人工怎么确认:看输入来源与运行环境;生产路径上的 eval 一律要改。

R-PY-004 MINOR certain 通道 M PY · Python 脚本

可变默认参数

判定依据:`def f(x=[])` 的默认对象在定义时创建一次,多次调用会累积状态,表现为难复现的测试互相污染。

修复建议:默认值用 `None`,函数内 `if x is None: x = []`。

参考:Python 语言陷阱(mutable default argument) · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:默认值是 `None` 再在函数内分配(`def f(x=None)`)不触发本规则。

人工怎么确认:确认默认值不是字面量可变容器([] / {} / set())。

R-PY-005 MINOR heuristic 通道 M PY · Python 脚本

open() 未使用 with(句柄可能泄漏)

判定依据:异常路径上文件句柄不会关闭;长跑的 harness 里会累积句柄。

修复建议:改用 `with open(path, encoding='utf-8') as f:`;顺带显式指定 encoding,避免平台默认编码差异。

参考:PEP 343 / Zephyr scripts 惯例 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:句柄被返回给调用方(资源所有权转移),或 with 之外有明确 close 分支。

人工怎么确认:看是否 return 句柄或有 close;若在被调用方用 with 也成立。

R-PY-006 MINOR heuristic 通道 M PY · Python 脚本

硬编码绝对路径

判定依据:脚本在 CI 与本地环境路径不同,硬编码 /home/<user>/… 只在一台机器上能跑。

修复建议:用 `Path(__file__).resolve().parent` 相对定位,或从环境变量/参数取根目录。

参考:Zephyr scripts 可移植性约定 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:测试夹具/示例脚本的固定路径;`os.path.join(base, ...)` 拼接不是绝对路径。

人工怎么确认:看路径是否可配置(env / 参数);示例脚本可接受。

R-SEC-001 MAJOR certain 通道 M SEC · 安全与健壮性

疑似硬编码凭据

判定依据:口令/密钥/PSK 写死在源码里会随固件一起被读出,且无法轮换。

修复建议:走构建期注入(Kconfig + 私有不入库的 conf)、或设备安全存储;测试用值标注 TEST_ONLY 并确认不进产物。

参考:references/50-review.md E 节「敏感信息无硬编码」 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:测试夹具、文档示例、明显的占位符(注释里标注 not-a-secret)。

人工怎么确认:确认是否真实值且被使用;即便是测试值也建议改环境变量。

R-SEC-002 MINOR certain 通道 M SEC · 安全与健壮性

printk 被用作业务日志

判定依据:printk 没有等级、无法按模块过滤、不能延迟格式化,量产固件里会拖慢时序并占满串口。

修复建议:改用 `LOG_MODULE_REGISTER(...)` + `LOG_INF/WRN/ERR`;ISR 里避免默认的同步模式日志。

参考:zephyr-rtos skill references/50-review.md P1 第 3 条 · 适用 profile:app / driver / subsys / kernel

为什么容易误报 · 评审人怎么确认

误报场景:没有 LOG 子系统的早期 bring-up 代码、或调试分支里的临时 printk。

人工怎么确认:看是否落在最终运行路径、是否成体系(成体系才该用 LOG)。

R-SEC-003 MINOR heuristic 通道 M SEC · 安全与健壮性

日志里可能出现敏感值

判定依据:把口令/密钥/token 变量直接打进日志,日志常被转发、留存、附到工单里。

修复建议:日志只打长度或指纹(如首 4 字节 + 总长),不要打明文。

参考:references/50-review.md E 节 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:打印的是固定寄存器值/非敏感量、或日志级别为 DEBUG 且默认关闭。

人工怎么确认:看打印字段来源是否可能是凭据/密钥/令牌。

R-UP-001 MAJOR certain 通道 C UP · 上游合规(commit / DCO / 测试与文档)

commit 缺少 Signed-off-by

判定依据:Zephyr 采用 DCO,CI 对缺 Signed-off-by 的提交直接失败;这是 gate 级硬要求。

修复建议:`git commit -s`(或 rebase 时 `--signoff`)补上真实姓名与邮箱。

参考:Zephyr Contributing > DCO · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:merge / revert 提交、或本地 WIP 提交(正式合并前才补 trailer)。

人工怎么确认:看提交类型;正式提交前必须补 Signed-off-by。

R-UP-002 MINOR certain 通道 C UP · 上游合规(commit / DCO / 测试与文档)

commit 标题不合规范

判定依据:Zephyr 要求 `[subsystem:] 简短祈使句`,标题超过 72 字符会被 CI 判失败,且 release notes 生成会错乱。

修复建议:`drivers: gpio: nrfx: fix pin interrupt mask`(小写、祈使、无句号、≤72 字符)。

参考:Zephyr Commit Guidelines · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:`Revert "..."` 与 merge 标题天然长,上游 CI 对它们有单独口径。

人工怎么确认:看是否 revert/merge;正常提交压缩到 ≤72 字符。

R-UP-003 MINOR heuristic 通道 C UP · 上游合规(commit / DCO / 测试与文档)

改了驱动/子系统但没有同步测试

判定依据:上游要求可验证性;没有 tests/ 覆盖的驱动改动无法在 CI 的 twister 矩阵里被回归。

修复建议:在 `tests/drivers/<driver>/` 加 ztest(可用 native_sim 跑),或说明为何现有测试已覆盖。

参考:references/50-review.md P2「测试与文档」 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:纯注释/文档改动、或测试在拆分的另一个 PR 里。

人工怎么确认:看 diff 是否含行为变更;有行为变更却无测试才需追问。

R-UP-004 MINOR heuristic 通道 C UP · 上游合规(commit / DCO / 测试与文档)

改动了 binding/DT 但没有同步文档

判定依据:binding 变更不同步 `doc/` 会让用户按旧属性写 DTS,且 dt-schema 的文档生成会失败。

修复建议:同步更新 `doc/hardware/peripherals/<x>.rst` 或 binding 的 description。

参考:references/50-review.md P2「改 Kconfig/DT 要更新文档」 · 适用 profile:*

为什么容易误报 · 评审人怎么确认

误报场景:binding 只改 description/注释、或文档在独立 PR。

人工怎么确认:看是否改了属性语义/必填项;纯描述可放过。

怎么用这套标准

查一条规则的细节https://zephyrrtos.cn/agent/api/review_rules?action=explain&rule_id=R-KCF-002(工具 review_rules(action="explain", rule_id=…))
让评审引擎跑一遍贴代码 code_review(mode="snippet", …);或把 Gitea 链接的 host 换成 /agent/api/r/(commit / PR / 文件三种入口)
看规则怎么落地PR #1 的真实 AI 评审:40 条规则跑出 1 MINOR + 3 INFO,并把「机器判不了的 7 件事」列给评审人
导出 / 二次使用/files/zephyr-code-review-rules.json(全部规则与计数,供脚本或你自己的工具读取)
改规则在仓库 api-server/scripts/review/rules.py 改 → 重新导出 JSON → 重新生成本页(node scripts/build-rules-standard.mjs)→ 部署;本页不会手改
问智能体