gpt4 book ai didi

c++ - 如何通过 boost::iostream 防止 zip 炸弹

转载 作者:太空狗 更新时间:2023-10-29 21:11:28 27 4
gpt4 key购买 nike

我写了一些这样的代码:

std::vector<char> unzip(std::vector<char> const& compressed)
{
std::vector<char> decompressed;

boost::iostreams::filtering_ostream os;

os.push(boost::iostreams::gzip_decompressor());
os.push(boost::iostreams::back_inserter(decompressed));

boost::iostreams::write(os, &compressed[0], compressed.size());
os.reset();
return decompressed;
}

如果compressed 是一个zip 炸弹,会发生什么?我认为内存会耗尽,进程会崩溃。

那么如何避免呢?解压前如何查看原始数据大小?

最佳答案

你会这样做,就像往常一样:解压缩时注意。

您可以使用具有固定/有限容量的缓冲区(例如使用 boost::iostreams::array_sink),或者您可以使用最大大小的保护来包装您的复制操作。

此外,在您的示例中,输入是内存缓冲区,因此使用设备比输入流更有意义。所以这里有一个简单的例子:

std::vector<char> unzip(size_t limit, std::vector<char> const& compressed) {
std::vector<char> decompressed;

boost::iostreams::filtering_istream is;

is.push(boost::iostreams::gzip_decompressor());
is.push(boost::iostreams::array_source(compressed.data(), compressed.size()));

while (is && (decompressed.size() < limit)) {
char buf[512];
is.read(buf, sizeof(buf));
decompressed.insert(decompressed.end(), buf, buf + is.gcount());
}
return decompressed;
}

当创建一个 60 字节的简单迷你炸弹时,它将扩展为 20 KB 的 NUL 字符:

int main() {
std::vector<char> const bomb = {
char(0x1f), char(0x8b), char(0x08), char(0x08), char(0xd1), char(0x6d), char(0x0e), char(0x5b), char(0x00), char(0x03), char(0x62), char(0x6f),
char(0x6d), char(0x62), char(0x00), char(0xed), char(0xc1), char(0x31), char(0x01), char(0x00), char(0x00), char(0x00), char(0xc2), char(0xa0),
char(0xf5), char(0x4f), char(0x6d), char(0x0a), char(0x3f), char(0xa0), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00),
char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00),
char(0x00), char(0x80), char(0xb7), char(0x01), char(0x60), char(0x83), char(0xbc), char(0xe6), char(0x00), char(0x50), char(0x00), char(0x00)
};

auto max10k = unzip(10*1024, bomb);
auto max100k = unzip(100*1024, bomb);

std::cout << "max10k: " << max10k.size() << " bytes\n";
std::cout << "max100k: " << max100k.size() << " bytes\n";
}

打印 Live On Coliru

max10k:  10240 bytes
max100k: 20480 bytes

throw

当然你可以选择在超过限制时抛出:

std::vector<char> unzip(size_t limit, std::vector<char> const& compressed) {
std::vector<char> decompressed;

boost::iostreams::filtering_istream is;

is.push(boost::iostreams::gzip_decompressor());
is.push(boost::iostreams::array_source(compressed.data(), compressed.size()));

while (is) {
char buf[512];
is.read(buf, sizeof(buf)); // can't detect EOF before attempting read on some streams

if (decompressed.size() + is.gcount() >= limit)
throw std::runtime_error("unzip limit exceeded");

decompressed.insert(decompressed.end(), buf, buf + is.gcount());
}
return decompressed;
}

关于c++ - 如何通过 boost::iostream 防止 zip 炸弹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50596089/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com