发生的情况是我正在读取加密数据包,并且遇到一个损坏的数据包,该数据包返回一个非常大的长度随机数。
size_t nLengthRemaining = packet.nLength - (packet.m_pSource->GetPosition() - packet.nDataOffset);
seckey.SecretValues.m_data.resize(nLengthRemaining);
在此代码中,m_data 是std::vector<unsigned char>
。由于数据包损坏,nLengthRemaining 太大,因此调整大小函数会抛出异常。问题不在于调整大小抛出(我们处理异常),而是调整大小已经损坏了内存,这会导致以后出现更多异常。
我想要做的是在调用 resize 之前知道长度是否太大,然后仅在可以的情况下调用 resize。我尝试将此代码放在调用调整大小之前:
std::vector<unsigned char>::size_type nMaxSize = seckey.SecretValues.m_data.max_size();
if(seckey.SecretValues.m_data.size() + nLengthRemaining >= nMaxSize) {
throw IHPGP::PgpException("corrupted packet: length too big.");
}
seckey.SecretValues.m_data.resize(nLengthRemaining);
此代码使用 std::vector max_size 成员函数来测试 nLengthRemaining 是否更大。但这一定不可靠,因为 nLengthRemaining 仍然小于 nMaxSize,但显然仍然大到足以导致调整大小出现问题(nMaxSize 为 4xxxxxxxxx,nLengthRemaining 为 3xxxxxxxxx)。
另外,我还没有确定 resize 抛出了什么异常。它不是 std::length_error 也不是 std::bad_alloc。它抛出的异常对我来说确实不太重要,但我很想知道。
顺便说一句,只是让你知道,这段代码在正常情况下确实可以正常工作。这种数据包损坏的情况是唯一让人疯狂的地方。请帮忙!谢谢。
UPDATE:
@迈克尔。现在,如果数据包大于 5 MB,我将忽略该数据包。我将与其他团队成员讨论验证数据包的可能性(它可能已经存在,但我只是不知道)。我开始认为这确实是我们版本的 STL 中的一个错误,它抛出的异常甚至不是 std::exception,这让我感到惊讶。我会尝试从我的主管那里了解我们也在运行什么版本的 STL(我将如何检查?)。
另一个更新:
我只是证明这是我在 Visual Studio 6 开发机器上使用的 STL 版本中的一个错误。我写了这个示例应用程序:
// VectorMaxSize.cpp :定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <math.h>
#include <typeinfo>
typedef std::vector<unsigned char> vector_unsigned_char;
void fill(vector_unsigned_char& v) {
for (int i=0; i<100; i++) v.push_back(i);
}
void oput(vector_unsigned_char& v) {
std::cout << "size: " << v.size() << std::endl;
std::cout << "capacity: " << v.capacity() << std::endl;
std::cout << "max_size: " << v.max_size() << std::endl << std::endl;
}
void main(int argc, char* argv[]) {
{
vector_unsigned_char v;
fill(v);
try{
v.resize(static_cast<size_t>(3555555555));
}catch(std::bad_alloc&) {
std::cout << "caught bad alloc exception" << std::endl;
}catch(const std::exception& x) {
std::cerr << typeid(x).name() << std::endl;
}catch(...) {
std::cerr << "unknown exception" << std::endl;
}
oput(v);
v.reserve(500);
oput(v);
v.resize(500);
oput(v);
}
std::cout << "done" << std::endl;
}
在我的 VS6 开发机器上,它与加密项目具有相同的行为,它会造成各种破坏。当我在 Visual Studio 2008 机器上构建并运行它时,调整大小将引发 std::bad_alloc 异常,并且向量不会被损坏,正如我们所期望的那样!是时候来看看 EA Sport NCAA 橄榄球了嘿嘿!