搜索/在底层系统补丁中优先找真正的缺陷,而不是挑风格毛病

在底层系统补丁中优先找真正的缺陷,而不是挑风格毛病

审查驱动、网络库等底层系统代码的补丁时使用。它追踪内存、锁和错误路径,检查整数宽度、并发、密码学和 API 变更,只报告能修正的问题,风格意见只在非常确定时才提出。

要使用这个AI规则
## 可能的缺陷即使不太确定也报告,风格问题只在很确定时报告 将正确性缺陷视为价值最高的发现。对于置信度达到50%或以上、可能存在的正确性缺陷,应当报告;证据不完整时,则应说明不确定性。可能存在的释放后使用、资源泄漏、竞争或越界问题,即使需要进一步确认,也值得提出。 对风格、格式和流程方面的发现采用不同门槛: - 只有置信度超过80%时才报告。 - 省略最终判断为正确、可接受或无害的任何内容。 - 绝不能在同一条发现中先提出疑虑,随后又否定该疑虑。 - 在可行的情况下,每条评论尽量只用一个可执行的句子。 根据每个补丁自身的行为进行审查。不要从单独的差异中推断补丁序列顺序、跨补丁编译依赖关系或贡献者的处境。审查一个补丁序列时,应省略没有问题的补丁,而不是将其概括为“没有问题”。 ## 追踪内存分配和错误路径,查找泄漏和误用 对于每次分配、打开的句柄、获取的锁或部分初始化的对象,追踪其后的所有分支。检查提前返回和清理标签,确认释放成对、顺序正确且错误码得到保留。 优先检查: - 释放后访问、重复释放、空指针解引用,以及可到达的未初始化读取。 - 内存、描述符、套接字、锁或部分构造成员的泄漏。 - 对确实可能失败的操作缺少失败检查。 - 错误的返回值、被丢弃的错误状态、反转的条件和边界偏差一位。 - 某个值在首次读取前就被无条件覆盖。 - 在嵌套循环中重复使用同一个循环计数器。 - 累加计数器时把样本赋给计数器,而不是加到计数器上。 区分递增计数器、仪表值和初始赋值。如果受支持的平台已明确说明,某个调用在参数有效时不会失败,就不要仅仅因为函数返回整数而将未检查的返回值标记为问题。 ## 检查整数宽度和数据包大小 审查算术运算时应关注操作数的位宽,而不能只关注目标值的位宽: - 当结果需要更宽的类型时,在乘法前至少扩宽一个操作数。 - 向宽位掩码中移位之前,使用与目标值同宽的字面量或操作数。 - 对用于指针运算或宽结果的移位,先扩宽较窄的无符号值。 - 如果结果的完整范围能由较窄类型容纳,且不涉及更宽的上下文,就不要改动这种移位。 - 对由来宾、数据包、设备或API输入控制的每一条链式遍历或索引遍历设置上限。 批量释放数据包或描述符对象时,应遵守所有权规则。如果数组元素可能来自不同来源,那么假定只使用一个分配器或内存池的批量原语并不安全;除非高速路径契约能够证明所有权统一,否则应使用能够识别内存池的释放路径。 将协议载荷大小与完整帧大小区分开。帧封装开销应根据设备能力推导,而不是采用通用常量;完成设置后,应读取当前的权威配置,而不是过时的请求字段。 当一个帧无法放入单个接收缓冲区时,实现必须启用受支持的多段路径,或者拒绝该配置。在初始配置、队列设置和运行时大小变更期间都要重新检查这一点,并根据已配置的模式和实际大小要求共同选择接收函数。 ## 检查共享数据是否使用原子操作或锁,而不是 volatile 不要把`volatile`当作线程间同步。共享可变状态需要原子操作或合适的锁;`volatile`只约束编译器访问,既不提供原子性,也不提供内存顺序。 选择能够保证正确性的最弱顺序: - 对不发布相关数据的独立统计值和标志使用宽松顺序。 - 对发布与消费关系使用释放存储和获取加载。 - 对既消费状态又发布状态的读取-修改-写入操作使用获取-释放顺序。 - 只有当彼此独立的原子变量需要统一的全局顺序时,才使用顺序一致性。 优先在原子操作本身指定顺序,而不是使用独立的内存栅栏。只有必须为一大组非原子访问排序时,内存栅栏才合适。 对于硬件寄存器和其他真正面向设备的访问,可以使用`volatile`。对于放置在进程间共享内存中的互斥量、条件变量、屏障或读写锁,应要求按进程共享方式初始化;对于进程私有内存则不要提出这一要求。当等待行为符合具体用途时,优先使用专为共享内存设计的同步原语。 ## 只在补丁处理密钥或机密时检查密码学问题 只有当补丁处理密钥、一次性随机数、认证材料或安全协议代码时,才应用密码学检查。 - 使用恒定时间等值比较原语,比较受攻击者影响的认证标签、摘要、MAC或完整性值。 - 替换普通字节比较时,应保留原有的等值语义。 - 密钥、扩展密钥表、会话秘密和类似材料应在释放前,通过无法被优化掉的操作擦除。 - 使用密码学安全的随机源生成密钥、初始化向量和一次性随机数。 不要把算法标识符、长度、能力或查找键的普通比较标记为问题。如果重用属于运行时性质,而静态补丁差异无法证实,就不要断言一次性随机数发生了重用。 ## 保持库的 API 简单,并为不兼容的 ABI 变更加版本 将可复用的库设计为类似编译器的服务:创建句柄、提供输入、接收结构化输出,并让调用方决定后续操作。避免使用单例状态和迫使调用方成为库后端的回调表。 对于公开回调和数据模型: - 优先使用一个回调参数,而不是庞大的操作表。 - 超过五个回调应视为需要重新设计的警告,超过二十个则应视为API设计错误。 - 记录回调的所有权、生命周期、返回值和失败行为。 - 对可能失败的操作,不要使用无返回值回调。 - 相比不断扩大的枚举与共用体组合,优先使用可扩展的带标签记录。 任何以头文件形式安装的内容,无论其标签如何,都属于公开API。应明确缓冲区的所有权和生命周期,尤其是内部静态存储区的情况。 新代码绝不能引入已弃用的接口。弃用一个接口时,必须确保代码树内不再有使用者,同时提供发布文档、迁移路径和编译器可见的注解。将公开、实验性和内部注解准确放在工具链预期的位置,从源码定义导出符号,并对不兼容的稳定签名变更使用ABI版本控制。绝不能要求手工编辑生成的符号映射。 ## 把机械式风格交给工具,审查工具发现不了的问题 让格式化工具、语义补丁工具和仓库验证脚本处理机械式替换。对于这些工具无法理解的情况,再使用人工或AI审查。 检查项目在缩进、行尾、包含文件分组、花括号、函数布局、标识符和命名空间前缀方面的既定规则。对外部可见的库或驱动程序符号要求使用唯一前缀,以避免静态链接冲突。使用包容性术语。 对于真假状态,优先使用真正的布尔类型;但错误码或多状态值应保留整数,并避免在既有代码中进行无关的类型改动。除非运行时注册或能力探测会修改编译期函数分派表,否则应将其保持为常量。 让分配和复制原语与数据路径相匹配: - 一般控制数据使用普通堆分配。 - DMA、队列或跨进程数据使用设备可见、感知NUMA并完成零初始化的分配方式。 - 只有当高速路径能够获益且满足相应契约时,才使用优化的批量复制。 注释应解释约束和意图,而不是复述代码。 ## 每次改代码时,一起更新测试和文档 每个提交都应当能够独立构建,但只查看补丁的审查者绝不能推测补丁序列的顺序。使用项目支持的编译器、目标、选项和构建脚本进行验证。 为新行为和公开API添加有针对性的测试。使用仓库的功能测试断言和测试套件运行器,准确记录环境要求,并为面向设备的新API提供至少一个实现。 以原子方式同时更新代码和文档: - 记录公开API和重要的用户可见变更。 - 使功能矩阵和操作文档与实现保持一致。 - 只针对公开API、新驱动程序或重大行为变更更新当前版本的发布说明。 - 不要要求仅涉及测试或内部实现的变更提供发布说明。 - 在结构化文档中,如果每个条目都是术语并附有充实说明,应优先使用定义列表;对于简短条目和操作步骤,则保留简单列表。 应用仓库采用的构建语言格式化工具和排序规则。使用指定的格式化工具和行长策略验证Python。 ## 只在目标为稳定版时应用稳定分支规则 只有当目标分支或版本被明确标识为稳定版时,才使用严格的稳定版发布规则。此时只能接受缺陷修复:不能添加新功能、公开API、ABI变更、符号、配置选项或无关的重构。 要求向后移植引用原始修复,并遵循项目的稳定版通知惯例。围绕一项小修复进行大规模清理会增加向后移植的风险,因此应视为警告信号。 如果没有指定版本,应假定目标为主开发分支;在该分支上,新功能和API可能是有效的。绝不能仅仅因为仓库也维护稳定分支,就应用只针对稳定版的禁止事项。 ## 写出具体修法,提交前把发现再检查两遍 将已确认的内存安全、同步、边界、清理、密码学、ABI和编译缺陷分类为错误。对于缺少测试或文档、API形态不合适、添加已弃用内容、误用分配方式以及高置信度的可维护性问题,使用警告。 不要报告: - 已由验证工具负责的生成映射缺失、版权细节或提交格式问题。 - 正确使用硬件`volatile`、进程私有锁、多段接收或当前测试宏的情况。 - 没有错误证据、只含糊要求验证某项内容的请求。 - 没有问题的补丁、推测性的跨补丁失败,或没有纠正行动的观察。 对于每个真实问题,先陈述问题;仅在影响并不明显时解释影响;并给出具体修复方案或代码方向。 提交前分别进行两轮检查: 1. 正确性检查:恢复那些未经证明就被排除、但合理怀疑涉及正确性的发现,并确认已经追踪资源路径、生命周期、边界和错误传播。 2. 误报检查:移除分析本身已经判断为可接受、正确或无害的所有风格或流程项目。 经过这些检查后,发现列表为空也是有效结果。不要为了填满列表而编造评论。