如何防范未终止的字符串

时间:2014-02-15 22:00:25

标签: c

在C程序中,我有一个将消息写入日志文件的函数

LogResult writeLog(const char* format, ...)

该函数将其参数传递给'vfprintf()'作为'format'字符串和'va_list'。我突然意识到,如果有人传递未终止的字符串,我无法控制会发生什么,例如。

const char unterminatedString[5] = {'h', 'e', 'l', 'l', 'o'};
writeLog("Log message: %s", unterminatedString);

有没有办法防范这个?

4 个答案:

答案 0 :(得分:2)

还有许多其他方法(在你提到的那个方面)传递非法字符串。

一些例子:

char* unterminatedString;
writeLog("Log message: %s", unterminatedString);

char* unterminatedString = (char*)0xA5A5A5A5;
writeLog("Log message: %s", unterminatedString);

char unterminatedString[] = "abc";
unterminatedString[3] = 'd';
writeLog("Log message: %s", unterminatedString);

int x = -1;
char* unterminatedString = (char*)&x;
writeLog("Log message: %s", unterminatedString);

合法字符串必须从有效的内存地址开始,并以有效的内存地址结束(带0字符)。没有明确的方法断言,除了迭代字符串本身,直到达到0字符或执行内存访问冲突(这正是vfprintf函数的作用)。

答案 1 :(得分:2)

const char*不知道数组的长度,它只是一个地址。所以这不是简单的可能。

如果你想保持纯C,你可以传递字符串的长度int len作为额外的参数,并检查是否format[len]==0。 我不认为这有用,但在我看来更糟糕。

由于您使用C ++标记了此问题,因此您可以(并且应该)使用std::string

LogResult writeLog(const std::string& format, ...)

始终正确终止std::string,您可以使用std::string::c_str()访问其基础C风格字符串。

请注意,std::string可以存储\0 - 字符,因此使用C风格字符串的函数将停在第一个\0,而不是std::string的末尾}。

答案 2 :(得分:2)

我假设你的日志功能有自己的内部缓冲区,你知道它的大小。

然后,您可以使用指定缓冲区大小的vsprintf()函数。请参阅Possible buffer overflow vulnerability

答案 3 :(得分:1)

不,没有办法可以轻易做到。

可以做的是使用valgrind等工具查找此类错误。