2017-08-10 86 views
1

今天,我发现下面的编译和打印42:从流中读取char * - 另一个缓冲区溢出失败?

#include <iostream> 
#include <sstream> 

int main() 
{ 
    std::stringstream s; 
    s << 42; 
    char c[8]; 
    s >> c; 
    std::cout << c; 
} 

但是,这是一个潜在的缓冲区溢出攻击,对不对?如果我们从用户提供的数据流中读取数据,我们无法轻易知道数据的大小,因此无法分配足够的存储空间。 std::gets被删除,也许这应该也是?

+0

也许与https://stackoverflow.com/questions/3203452/how-to-read-entire-stream-into-a-stdstring相关? – lz96

+0

这显示了正确的方法来做到这一点,我的问题是更多关于为什么c + +可以轻松地拍摄自己的脚。 – Lyberta

+0

@ M.M'fgets'有一个size参数,这个不是。 – Lyberta

回答

1

那么,你可以通过书面防止缓冲区溢出在这种情况下:

s >> setw(sizeof c) >> c; 

所以我觉得它更像是的fgets的情况下,可以用来拍摄自己的脚,但也可以正确使用,正确使用它是一个完美可行的选择。

我希望仍然存在使用这种超负荷的operator>>,它是不是真的可行弃用它,够活代码如:

void func(char *buf, size_t buf_len) 
{ 
    std::cin >> setw(buf_len) >> buf; 
} 

但对于编写新的代码我的建议是避免使用阵列完全(C风格的数组,就是这样)。而应使用std::stringstd::array或其他此类容器,这些容器很难导致缓冲区溢出。

+0

我不明白如何使用'std :: array'在这里更改任何东西 –

+0

@MooingDuck我希望''std :: istream'和'std :: array'会导致'operator >>'重载。 ..如果不是那么应该有:) –

+0

不幸的是,没有C++容器有这样的重载,除了'std :: string'和'std :: wstring' –