答案 0 :(得分:3)
目录名称有多长,以及您尝试将其存储的缓冲区有多长?你没有给我们太多的信息......如何显示一些代码?也许打电话给sprintf main()中的某个地方,以及涉及的任何变量的声明?
编辑:在给定输入目录的情况下,确定文件名需要是一个更大的数组 和你附加的文件名!快速修复:尝试将其声明为1500个字符而不是50个。更好的修复:因为您正在使用C ++,请查看std :: string和ostringstream类,它们将自行调整大小以防止缓冲区溢出。
回答你的后续问题:
结果路径中的“../”不应扩展为绝对路径。
基于“缓冲区溢出”消息和gdb回溯中的最后几行,我的预感sprintf()是一个幸运的猜测。我不熟悉glibc内部,但是__sprintf_chk()
和__vsprintf_chk()
可能是sprintf()的缓冲区溢出检查变体?
答案 1 :(得分:2)
我很久以前养成了到处使用snprintf的习惯。学会爱它。它可能仍然无法写出正确的文件,但至少它不会留下安全漏洞。
然后在您开始想知道为什么您的程序正在创建名为"this_is_a_long_file_na"
的文件之后,您可以返回并修复它以使用PATH_MAX
的缓冲区或动态大小的malloc缓冲区。如果缓冲区需要更大,snprintf将帮助您找到合适的大小。
或者您可以切换到C ++并使用std :: string。
答案 2 :(得分:1)
你使用sprintf打印到缓冲区'filename [50]'当然有50个长度。现在你打印的字符串是一个大小为1024的缓冲区,这对我来说是一个潜在的问题。当global.result_path超过50时会发生什么(实际上甚至更少,因为你也打印整数),你得到溢出。
尝试使用C ++ std :: string和std :: stringstream,即:
//Part 1:
std::stringstream ss;
ss << global.result_path << /* other data */;
train_samples[n].write_png(ss.str().c_str());
//Part 2:
class Global
{
std::string result_path;
...
}
使用上面的代码,您将永远不必担心溢出字符缓冲区或任何其他丑陋的东西。
答案 3 :(得分:1)
result_path太小了。
只需将result_path更改为1024.某些系统已定义宏MAX_PATH。 我还将sprintf更改为snprintf,其大小为sizeof(result_path)。
snprintf()函数就像sprintf()一样,只是给出了缓冲区的长度。这可以防止缓冲区溢出。
返回值是写入的字符数。如果由于buff_size限制而导致输出被截断,则返回值是如果有足够的空间可以写入最终字符串的字符数(不包括尾随的'\ 0')。
我怎么知道你对sprintf有问题是回溯。
即
(gdb) bt
#0 0x00007fbd29573fb5 in raise () from /lib/libc.so.6
#1 0x00007fbd29575bc3 in abort () from /lib/libc.so.6
#2 0x00007fbd295b3228 in ?? () from /lib/libc.so.6
#3 0x00007fbd296402c7 in __fortify_fail () from /lib/libc.so.6
#4 0x00007fbd2963e170 in __chk_fail () from /lib/libc.so.6
#5 0x00007fbd2963d519 in ?? () from /lib/libc.so.6
#6 0x00007fbd295b7426 in _IO_default_xsputn () from /lib/libc.so.6
#7 0x00007fbd29586fdb in vfprintf () from /lib/libc.so.6
#8 0x00007fbd2963d5b9 in __vsprintf_chk () from /lib/libc.so.6
#9 0x00007fbd2963d500 in __sprintf_chk () from /lib/libc.so.6
#10 0x0000000000408695 in main ()
即。 您的代码中有一个函数main。而__sprintf_chk就是它的地方。 你必须要打电话给sprintf。之后就死了。所以我的猜测是你传递了不好的论点。 sprintf死得很厉害的唯一方法就是缓冲区溢出。因此,您打印的字符串太小是一个很好的假设。使用snprintf和 它会更安全。然后,您可以打印以调试结果。如果你已经这样做了,你会立即看到缓冲区太小,因为result_path将被截断为50个字符并且程序不会崩溃(至少在那时:)。