bugprone-not-null-terminated-result¶
查找可能导致非空终止结果的函数调用。通常,字符串的正确长度为 strlen(src) + 1 或该表达式的等长,因为空终止符需要额外的空间。没有空终止符会导致在读取字符串时出现未定义行为。
以下及其相应的 wchar_t 基函数将被检查
memcpy, memcpy_s, memchr, memmove, memmove_s, strerror_s, strncmp, strxfrm
以下是一个现实世界的例子,程序员忘记增加传递的第三个参数,即 size_t length。这就是分配的内存长度不足以容纳空终止符的原因。
static char *stringCpy(const std::string &str) {
char *result = reinterpret_cast<char *>(malloc(str.size()));
memcpy(result, str.data(), str.size());
return result;
}
除了发出警告之外,修复还将重写所有必要的代码。它还尝试调整目标数组的容量
static char *stringCpy(const std::string &str) {
char *result = reinterpret_cast<char *>(malloc(str.size() + 1));
strcpy(result, str.data());
return result;
}
注意:它不能保证重写所有路径敏感的内存分配。
‘memcpy()’ 的转换规则¶
可以将 memcpy() 和 memcpy_s() 调用重写为以下四个函数: strcpy(), strncpy(), strcpy_s(), strncpy_s(),其中后两个是前两个的更安全版本。它分别重写了基于 wchar_t 的内存处理函数。
基于目标数组的重写¶
如果复制到目标数组不会溢出 [1],则新函数应该是旧的复制函数(以
cpy结尾),因为它比安全版本更高效。如果复制到目标数组可能溢出 [1],并且
WantToUseSafeFunctions设置为 true,并且可以获取目标数组的容量,则新函数可以是安全版本(以cpy_s结尾)。如果新函数可能是安全版本,并且分析的是 C++ 文件,并且目标数组是普通的
char/wchar_t,没有un/signed,则可以省略目标数组的长度。如果新函数可能是安全版本,并且目标数组是
un/signed,则需要将其强制转换为普通的char */wchar_t *。
- [1] 可能溢出
如果目标数组的容量未知。
如果给定长度等于目标数组的容量。
基于源字符串长度的重写¶
如果给定长度为
strlen(source)或该表达式的等长,则新函数应该是旧的复制函数(以cpy结尾),因为它比安全版本(以cpy_s结尾)更高效。否则,我们假设程序员希望复制 'N' 个字符,因此新函数是类似
ncpy的,它复制 'N' 个字符。
使用 ‘strlen()’ 或该表达式的等长的转换¶
它分别转换了基于 wchar_t 的内存和字符串处理函数(其中只有 strerror_s 没有基于 wchar_t 的别名)。
内存处理函数¶
memcpy 请访问 ‘memcpy()’ 的转换规则 部分。
memchr 通常有一个 C 样式的强制转换,需要将其删除,因为新函数 strchr 的返回类型是正确的。给定的长度将被删除。
memmove 如果有安全函数可用,新函数是 memmove_s,它有一个新的第二个参数,它是目标数组的长度,它被调整,并且源字符串的长度增加 1。如果安全函数不可用,则给定长度增加 1。
memmove_s 给定的长度增加 1。
字符串处理函数¶
strerror_s 给定的长度增加 1。
strncmp 如果第三个参数是第一个或第二个参数的 length + 1,则必须将其截断,不进行 + 1 操作。
strxfrm 给定的长度增加 1。
选项¶
- WantToUseSafeFunctions¶
值 true 指定目标环境被认为实现了以 ‘_s’ 为后缀的内存和字符串处理函数,这些函数比旧版本(例如 ‘memcpy_s()’)更安全。默认值为 true。