quello che succede è che sto leggendo pacchetti di crittografia e incontro un pacchetto corrotto che restituisce un numero casuale molto grande per la lunghezza.vector.resize funzione che danneggia la memoria quando la dimensione è troppo grande
size_t nLengthRemaining = packet.nLength - (packet.m_pSource->GetPosition() - packet.nDataOffset);
seckey.SecretValues.m_data.resize(nLengthRemaining);
In questo codice m_data è un std::vector<unsigned char>
. nLengthRemaining è troppo grande a causa di un pacchetto di dati danneggiato, pertanto la funzione di ridimensionamento viene generata. Il problema non risiede nel ridimensionamento (gestiamo le eccezioni), ma il ridimensionamento ha già danneggiato la memoria e questo porta a più eccezioni in seguito.
Quello che voglio fare è sapere se la lunghezza è troppo grande prima chiamo ridimensionamento, quindi chiamare ridimensionare se è ok. Ho provato a mettere questo codice prima della chiamata a ridimensionare:
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);
Questo codice utilizza la funzione di std :: vector membro max_size per verificare se il nLengthRemaining è più grande. Tuttavia, ciò non deve essere affidabile, poiché nLengthRemaining è ancora inferiore a nMaxSize, ma apparentemente abbastanza grande da causare il ridimensionamento di un problema (nMaxSize era 4xxxxxxxxx e nLengthRemaining è 3xxxxxxxxx).
Inoltre, non ho determinato quale ridimensionamento dell'eccezione viene lanciato. Non è uno std :: length_error e non è uno std :: bad_alloc. Quel che fa eccezione non è davvero troppo importante per me, ma sono curioso di sapere.
btw, solo così si sa, questo codice funziona correttamente in casi normali. Questo caso di un pacchetto di dati corrotto è l'unico posto dove impazzisce. Per favore aiuto! Grazie.
UPDATE:
@ Michael. Per ora ignorerò semplicemente il pacchetto se è più grande di 5 MB. Discuterò con altri membri del team sulla possibilità di convalidare i pacchetti (potrebbe già esserci e io non lo so). Sto iniziando a pensare che sia davvero un bug nella nostra versione di STL, l'eccezione che getta non è nemmeno un'eccezione std ::, che mi ha sorpreso. Cercherò di scoprire dal mio supervisore quale versione di STL stiamo eseguendo anche (come potrei controllare?).
UN ALTRO AGGIORNAMENTO: Ho appena provato che si tratta di un bug nella versione STL che sto utilizzando sul mio computer di sviluppo di Visual Studio 6. Ho scritto questa app di esempio:
// VectorMaxSize.cpp: definisce il punto di ingresso per l'applicazione della console. //
#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;
}
Sulla mia macchina dev VS6 ha lo stesso comportamento ha il progetto di crittografia, che provoca ogni sorta di caos. Quando lo costruisco ed eseguo sul mio computer di Visual Studio 2008, ridimensionamento genererà un'eccezione std :: bad_alloc e il vettore non sarà corrotto, proprio come ci saremmo aspettati! È tempo di giocare a EA Sport con il calcio NCAA!
Quale piattaforma sei? – sbi
Sono curioso di sapere quale versione del compilatore/stl stai usando. Le implementazioni a cui ho accesso non corromperanno l'oggetto vettoriale se l'allocazione fallisce. – jmucchiello
@cchampion: "Sulla mia macchina dev VS6 ..." Avevi detto prima, non avremmo perso così tanto tempo su questo. Questa è più di 10 anni di tecnologia! Certo, è buggy. Vedi la mia risposta. – sbi