不正确的空终止 c/c++

  • 本文关键字:c++ 终止 不正确 c++
  • 更新时间 :
  • 英文 :


我最近正在尝试在现有的c ++源代码(与C混合)上使用静态代码分析器。当我尝试这样的事情时,我发现发生了很多错误

char* buff= new char[length];
size_t readbytes = fread(buff,length,1, file)

我在buff上得到不正确的空指针终止。我试过这样的事情——

if((readbytes=fread(buff,length,1,file))<length){ /*dont do anything*/}
else {/*rest of the code*/}

这不起作用。 还试图与strlen(buff) == length核实 - 也没有用。

我在memcpy上遇到的类似高风险问题,当我的目的地是char[constant size]型时,memmove

会我在这里缺少什么来让它写入,从而无法避免空终止风险?

假设fread应该首先添加一个终止 null 是错误的。或者终止 null 不存在于缓冲区的中间。您应该分配 +1 字节并手动添加终止 null,以确保它存在于缓冲区中的某个位置:

char * buff{new ichar[length + 1]};
size_t readbytes{fread(buff, length, 1, file)};
if(readbytes <= length)
{
buff = readbytes[readbytes] = '';
}
else
{
abort(); // fread return value is unexpected
}
assert(strlen(buff) <= readbytes);

我在这里缺少什么来让它写入,以便避免空终止风险?

您对fread如何工作的理解是不正确的。

fread()不 null 终止输入缓冲区。不仅如此,如果从中读取的文件包含二进制数据,则缓冲区可能包含任意数量的(可以是零,可以是非零)空字符。

如果确定文件仅包含文本内容,则可以执行以下操作:

  1. 确保读取的字符数比缓冲区可以容纳的字符数少一个。
  2. 使用空字符终止缓冲区。
  3. 此外,您需要交换两个中间参数。请参阅fread文档,了解中间两个参数的含义。

size_t readbytes = fread(buff, 1, length - 1, file);
buff[readbytes] = '';

从 https://en.cppreference.com/w/c/io/fread:

buffer- 指向存储
读取对象的数组的指针大小- 每个对象的大小(以字节
为单位)计数- 要读取的对象的数量- 要读取
的流

假设输入文件有一行,内容为:

abcdef

缓冲区定义为:

char buff[20];

如果您使用

size_t n = fread(buff, 20, 1, file);

然后,n将为 0。您请求读取 1 个大小为 20 的对象,文件中只有 7 个字符(我也包含一个换行符)。

如果您使用

size_t n = fread(buff, 1, 20, file);

那么,n将是7。您请求读取 20 个大小为 1 的对象,但该函数只能读取 7 个大小为 1 的对象。

现在,您可以决定是否

size_t readbytes = fread(buff, length - 1, 1, file);

size_t readbytes = fread(buff, 1, length - 1, file);

适合您的用例。

您可以使用字符串和文件流来完全避免此问题。当您使用C++时,您不妨使用它提供的所有这些不错的流函数来避免此类问题。

#include <iostream>
#include <fstream>
const char* filePath = "yourFile.txt";
int main() {
std::string line = "";
std::ifstream inFile (filePath, std::ifstream::in);
if (inFile.good()) {
std::getline(inFile, line, 'n');
}
inFile.close();
// more checks here (inFile.fail() || inFile.bad()) + cleanup
/* Do what you want with line */
return 0;
}

最新更新