将图像写入目录失败

时间:2009-09-02 23:53:27

标签: c++ optimization directory overflow buffer

4 个答案:

答案 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个字符并且程序不会崩溃(至少在那时:)。