像往常一样,您需要在解压缩时注意。
您可以使用固定/有限容量的缓冲区(例如使用 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千字节的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";
}
打印在Coliru上实时运行
max10k: 10240 bytes
max100k: 20480 bytes
抛出异常
当然,如果超出限制,您可以选择抛出异常:
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));
if (decompressed.size() + is.gcount() >= limit)
throw std::runtime_error("unzip limit exceeded");
decompressed.insert(decompressed.end(), buf, buf + is.gcount());
}
return decompressed;
}
std::thread
中运行此程序,检查共享解压缩的大小,如果超过限制,则终止线程。参见https://dev59.com/vmct5IYBdhLWcg3wSbfY。 - schorsch_76