仅在打开编译器优化的情况下,某些地方的缓冲区溢出
Buffer overflow in certain places only with compiler optimizations turned on
所以我遇到了一个问题,某段代码给我这个错误 *** BUFFER OVERFLOW DETECTED ***
。这只有在我打开某些编译器优化选项后才开始发生(这不是我的程序,所以我必须使用这些)。我已经缩小到它是哪个选项。我还找到了一种方法来阻止缓冲区溢出,但是,我在程序的另一部分中有非常相似的代码, 不会 在我保持原样时给我同样的错误。这让我对我的修复感到非常困惑和非常不自信,因此我将不胜感激。
以下是 makefile
中的优化选项
CXXFLAGS+=-Os -O2 -fomit-frame-pointer
CXXFLAGS+=-fno-aggressive-loop-optimizations
我已将其缩小到开始导致错误的 -O2
标志。
仅当指定 -O2
标志时,此函数才会在 realpath()
缓冲区溢出时失败
static std::string getRealTargetPath (std::string baseTarget)
{
char nextTargetLink[MAXPATHLEN];
memset (nextTargetLink, 0, MAXPATHLEN);
if (realpath (baseTarget.c_str(), nextTargetLink) == NULL)
return "";
else
//etc...
}
如果我将 MAXPATHLEN
(大小 1024)更改为 PATH_MAX
(大小 4096),上面的函数将按预期运行。好,可以。但是下面的代码片段在使用 same std::string baseTarget
之后执行了大约 20 行。
char realLinkPath[MAXPATHLEN];
memset (realLinkPath, 0, MAXPATHLEN);
do
{
if (realpath (linkPath.c_str(), realLinkPath) != NULL)
if (strcmp(linkPath.c_str(), realLinkPath) != 0)
return true;
size_t eraseFrom = linkPath.rfind('/');
if (std::string::npos != eraseFrom)
linkPath.erase(eraseFrom);
} while ( !linkPath.empty() );
总而言之,即使这两个 realpath
函数使用相同的 const char* path
变量,如果缓冲区不是 PATH_MAX
长度,第一个将失败,但第二个不会,这一切只有在为编译指定了 -O2
标志时才会发生。
如有任何帮助,我们将不胜感激。
编辑:正如用户指出的那样,我也将其标记为 C
因为该程序很旧并且核心是用 C
编写的,我最好尽可能将其保留为 C没有使用 太多 许多 C++
功能
realpath
的手册页指定 resolved_path
的长度必须至少为 PATH_MAX。如果 realpath
的结果是一个长度超过 1024 字节的字符串,并且您的缓冲区不够大,那么您正在调用 undefined behavior。这意味着崩溃可能会(如第一种情况)或可能不会(如第二种情况)发生。
好吧,第二部分有不同的输入,所以碰巧工作得很好。 realpath()
是一个非常糟糕的函数,甚至 manpage 也指出(参见 BUGS)。
你能做的最好的事情就是重新编写代码,以便使用 null
指针调用 realpath 作为它的第二个参数,并注意你返回的分配缓冲区是 free()
d 正确
所以我遇到了一个问题,某段代码给我这个错误 *** BUFFER OVERFLOW DETECTED ***
。这只有在我打开某些编译器优化选项后才开始发生(这不是我的程序,所以我必须使用这些)。我已经缩小到它是哪个选项。我还找到了一种方法来阻止缓冲区溢出,但是,我在程序的另一部分中有非常相似的代码, 不会 在我保持原样时给我同样的错误。这让我对我的修复感到非常困惑和非常不自信,因此我将不胜感激。
以下是 makefile
CXXFLAGS+=-Os -O2 -fomit-frame-pointer
CXXFLAGS+=-fno-aggressive-loop-optimizations
我已将其缩小到开始导致错误的 -O2
标志。
仅当指定 -O2
标志时,此函数才会在 realpath()
缓冲区溢出时失败
static std::string getRealTargetPath (std::string baseTarget)
{
char nextTargetLink[MAXPATHLEN];
memset (nextTargetLink, 0, MAXPATHLEN);
if (realpath (baseTarget.c_str(), nextTargetLink) == NULL)
return "";
else
//etc...
}
如果我将 MAXPATHLEN
(大小 1024)更改为 PATH_MAX
(大小 4096),上面的函数将按预期运行。好,可以。但是下面的代码片段在使用 same std::string baseTarget
之后执行了大约 20 行。
char realLinkPath[MAXPATHLEN];
memset (realLinkPath, 0, MAXPATHLEN);
do
{
if (realpath (linkPath.c_str(), realLinkPath) != NULL)
if (strcmp(linkPath.c_str(), realLinkPath) != 0)
return true;
size_t eraseFrom = linkPath.rfind('/');
if (std::string::npos != eraseFrom)
linkPath.erase(eraseFrom);
} while ( !linkPath.empty() );
总而言之,即使这两个 realpath
函数使用相同的 const char* path
变量,如果缓冲区不是 PATH_MAX
长度,第一个将失败,但第二个不会,这一切只有在为编译指定了 -O2
标志时才会发生。
如有任何帮助,我们将不胜感激。
编辑:正如用户指出的那样,我也将其标记为 C
因为该程序很旧并且核心是用 C
编写的,我最好尽可能将其保留为 C没有使用 太多 许多 C++
功能
realpath
的手册页指定 resolved_path
的长度必须至少为 PATH_MAX。如果 realpath
的结果是一个长度超过 1024 字节的字符串,并且您的缓冲区不够大,那么您正在调用 undefined behavior。这意味着崩溃可能会(如第一种情况)或可能不会(如第二种情况)发生。
好吧,第二部分有不同的输入,所以碰巧工作得很好。 realpath()
是一个非常糟糕的函数,甚至 manpage 也指出(参见 BUGS)。
你能做的最好的事情就是重新编写代码,以便使用 null
指针调用 realpath 作为它的第二个参数,并注意你返回的分配缓冲区是 free()
d 正确