容量决定可写入的范围

缓冲区为数据提供一定范围的存储。把超过该范围的数据写进去,并不会合法地自动扩容;写入可能碰到其他对象,也可能触发异常或硬件故障,具体结果取决于语言、工具与运行环境。

读取越界通常另称缓冲区越界读取,两者都属于边界错误,却不应混为同一个写入操作。C语言中,即使某个地址看似仍可访问,越出相应数组的下标或不合法指针运算仍可能已经违反语言规则。

参考:[1] [2]

检查必须覆盖实际访问

边界检查需要与真正使用的索引和长度一致。例如只检查索引小于数组长度,没有排除负值,在带符号整数参与计算时仍可能得到数组之前的位置。检查写在代码里,并不代表它已经覆盖所有不合法输入。

SEI CERT还指出,多维数组中看似落在同一大片存储内的位置,也不能因此忽略各层数组的边界。正确性依赖具体对象与访问表达式,不能只拿整块内存的起止地址做粗略判断。

参考:[1]

检测工具要结合接口约束

AddressSanitizer可以在经过插桩的执行中报告多类越界访问,并提供相关调用位置。容器的逻辑大小与底层已分配容量不同,某些容器越界检查还需要库与检测器合作,不能只凭分配空间大小判断元素已经存在。

更可靠的预防还要让接口明确容量与有效范围,并确保错误路径不继续执行非法访问。动态检测有助于发现已经执行到的缺陷,而不能替代输入约束、对象边界和未覆盖路径的检查。

参考:[2] [1]