【发布时间】:2010-12-09 14:05:50
【问题描述】:
发生的事情是我正在读取加密数据包,我遇到了一个损坏的数据包,该数据包会返回一个非常大的随机数。
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之前知道长度是否太大,然后只有在没问题的情况下才调用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。它抛出了什么异常对我来说真的不太重要,但我很想知道。
顺便说一句,您知道,这段代码在正常情况下确实可以正常工作。这种数据包损坏的情况是唯一发疯的地方。请帮忙!谢谢。
更新:
@迈克尔。现在,如果数据包大于 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 机器上构建并运行它时,resize 将抛出一个 std::bad_alloc 异常并且向量不会被破坏,正如我们所预料的那样!是时候参加一些 EA Sport NCAA 足球了,呵呵!
【问题讨论】:
-
我很好奇您使用的是什么编译器/stl 版本。如果分配失败,我可以访问的实现不会破坏向量对象。
-
@cchampion:“在我的 VS6 开发机器上……”如果你早点这么说,我们就不会在这上面浪费这么多时间了。那是10多年前的技术!当然,它是越野车。看我的回答。
-
查看我最近的编辑 - 问题是 VC6 的
<xmemory>标头中的错误(但不是 Dunkumware VC 错误页面上讨论的错误)。