strncmp 的这种用法是否包含越界读取?

Does this usage of strncmp contain an out of bounds read?

Fortify 表示这是越界读取:

if (strncmp("test string", "less than 32 char", 32) == 0)
{
...
}

表示函数从less than 32 char的边界外读取数据。

如果 strncmp 超过 32 个字符并且第二个字符串小于 32 个字符,是否真的有发现?

TL;DR - strncmp() 将继续比较 string 元素,直到任一字符串结束或 32元素(字符),以较少.

为准

A(ny) string 始终以 null 终止,并且在遇到 null 终止符时,不会执行进一步的比较。您的代码是安全的。

引用 C11,章节 §7.24.4.4(强调我的

int strncmp(const char *s1, const char *s2, size_t n);

The strncmp function compares not more than n characters (characters that follow a null character are not compared) from the array pointed to by s1 to the array pointed to by s2.

您的代码完全有效。

要么是您的编译器生成了错误的目标代码,要么是 fortify 报告了误报。

我怀疑是编译器生成了错误代码。这会造成太多问题,很快就会被发现并修复。

很可能是 fortify 报告了误报。

出于性能原因,标准字符串函数的实现通常会在自然对齐的寄存器宽度块中处理数据。这可能导致读取访问超过源数据对象的末尾,但对齐保证代码的行为与内存异常方面的原始实现完全一样。每个宽访问都包含在单个页面中,并且不会触及字节实现也不会触及的页面。

我会声称此类实现包含在 C 的假设规则中,也就是说,它们的行为与 "as if" 遵循抽象功能规范的行为相同。

这种优化实施的一个例子是OpenSolaris's strcmp() for SPARC v8。这是我十五年前写的代码,以及其他性能优化的字符串函数。

然而,各种内存检查工具会抱怨此类代码,因为它的使用会导致访问超出分配的数据对象的限制,即使越界读取访问在设计上是无害的。