lo que está sucediendo es que estoy leyendo paquetes de cifrado, y encuentro un paquete dañado que devuelve un número aleatorio muy grande para la longitud.función vector.resize corrompe la memoria cuando el tamaño es demasiado grande
size_t nLengthRemaining = packet.nLength - (packet.m_pSource->GetPosition() - packet.nDataOffset);
seckey.SecretValues.m_data.resize(nLengthRemaining);
En este código m_data es un std::vector<unsigned char>
. nLengthRemaining es demasiado grande debido a un paquete de datos dañado, por lo tanto, se lanza la función de cambio de tamaño. El problema no es que los cambios de tamaño (manejamos las excepciones), sino que el cambio de tamaño ya ha dañado la memoria y esto lleva a más excepciones más adelante.
Lo que quiero hacer es saber si la longitud es demasiado grande antes de llamar al cambio de tamaño, entonces solo llame el tamaño si está bien. He intentado poner este código antes de la llamada a cambiar el tamaño:
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);
Este código está utilizando la función miembro std :: vector max_size para probar si el nLengthRemaining es mayor. Sin embargo, eso no debe ser confiable, porque nLengthRemaining es aún menor que nMaxSize, pero al parecer sigue siendo lo suficientemente grande como para causar que el tamaño tenga un problema (nMaxSize fue 4xxxxxxxxx y nLengthRemaining es 3xxxxxxxxx).
Además, no he determinado qué es el tamaño de excepción que arroja. No es std :: length_error y no es std :: bad_alloc. La excepción que está lanzando realmente no es demasiado importante para mí, pero tengo curiosidad por saberlo.
Por cierto, para que lo sepa, este código funciona correctamente en casos normales. Este caso de un paquete de datos dañado es el único lugar donde se vuelve loco. ¡Por favor ayuda! Gracias.
ACTUALIZACIÓN:
@ Michael. Por ahora solo voy a ignorar el paquete si es más grande que 5 MB. Discutiré con otros miembros del equipo sobre la posible validación de los paquetes (puede que ya esté allí y no lo sé). Estoy empezando a pensar que realmente es un error en nuestra versión de STL, la excepción que arroja ni siquiera es una excepción estándar, lo que me sorprendió. Trataré de averiguar de mi supervisor qué versión de STL estamos ejecutando también (¿cómo verificaría?).
OTRA ACTUALIZACIÓN: Solo demuestro que es un error en la versión de STL que estoy usando en mi máquina de desarrollo Visual Studio 6. Escribí esta aplicación de ejemplo:
// VectorMaxSize.cpp: define el punto de entrada para la aplicación de la consola. //
#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;
}
En mi máquina dev VS6 que tiene el mismo comportamiento que tiene el proyecto de cifrado, que provoca todo tipo de estragos. Cuando lo construya y lo ejecute en mi máquina Visual Studio 2008, resize arrojará una excepción std :: bad_alloc y el vector no se corromperá, ¡tal como lo habríamos esperado! Es hora de jugar fútbol EA EA NCAA, jeje!
¿En qué plataforma estás? – sbi
Tengo curiosidad de qué versión de compilador/stl está utilizando. Las implementaciones a las que tengo acceso no dañarán el objeto vector si falla la asignación. – jmucchiello
@cchampion: "En mi máquina de desarrollo VS6 ..." Si hubiera dicho esto antes, no habríamos perdido tanto tiempo en esto. ¡Eso es más de 10 años de tecnología! Por supuesto, tiene errores. Ver mi respuesta – sbi