Newsgroup: it.comp.programmare.win32
Titolo: Serializzazione di collezioni. Bug in MFC?

Salve a tutti!
Uso VC++6.0
da qualche parte ho:
CList<CTest, CTest&> myList;
...
myList.Serialize(ar);
...
internamente MFC chiama:
CList::Serialize che č fatta cosě:
if (ar.IsStoring())
....
else
 {
  DWORD nNewCount = ar.ReadCount();
  while (nNewCount--)
  {
   TYPE newData;
   SerializeElements<TYPE>(ar, &newData, 1);
   AddTail(newData);
  }
 }
Supponiamo che il file sia rotto e che la ar.ReadCount() ritorni un numero
assurdo (es. 200000000)
siccome la SerializeElements fornita da MFC č fatta cosě:
template<class TYPE>
void AFXAPI SerializeElements(CArchive& ar, TYPE* pElements, int nCount)
{
 ASSERT(nCount == 0 ||
  AfxIsValidAddress(pElements, nCount * sizeof(TYPE)));
 // default is bit-wise read/write
 if (ar.IsStoring())
  ar.Write((void*)pElements, nCount * sizeof(TYPE));
 else
  ar.Read((void*)pElements, nCount * sizeof(TYPE));
}
e siccome la CArchive::Read NON tira eccezioni se finisce il file
la conseguenza č che il programma alloca un quantitativo enorme di memoria e
di fatto si pianta il PC!!!!
Per ora ho risolto sovrascrivendo la SerializeElements per il mio tipo in
questo modo:
template <> void AFXAPI SerializeElements <CTest> ( CArchive& ar, CTest*
pElements, int nCount )
{
 ASSERT(nCount == 0 ||
  AfxIsValidAddress(pElements, nCount * sizeof(*pElements)));
 // default is bit-wise read/write
 if (ar.IsStoring())
  ar.Write((void*)pElements, nCount * sizeof(*pElements));
 else
 {
  UINT n = ar.Read((void*)pElements, nCount * sizeof(*pElements));
  if(n != nCount * sizeof(*pElements))
   AfxThrowArchiveException(CArchiveException::endOfFile);
 }
}
Facendo cosě, una volta finito il file si ferma tutto senza allocare GB!
Secondo voi č un bug della MFC?
E' lecito correggere la SerializeElements standard (nel file afxtempl.h)?
Grazie
b.b.

 E' lecito correggere la SerializeElements standard (nel file afxtempl.h)?
E' assolutamente ILLEGALE modificare gli include standard... :( 
-- 
Luc


Piuttosto ti generi una classe che erediti da CList e ridefinisca la 
funzione SerializeElements.
LP

 funzione SerializeElements.
Certo, OK,
in realtà la SerializeElements è una helper globale, che (come da post
originale) ho già provveduto a ridefinire in modo corretto.
Il punto è che QUALSIASI programma che serializza collezioni MFC passa per
la SerializeElements standard che (secondo me) è bacata!!
Sono d'accordo che una possibile soluzione sia derivare una CList2 ( ma poi
andrebbe fatta anche CMap2, CArray2.........) e ridefinire il comportamento
della serialize che è virtuale (ricopiando di fatto le implementazioni MFC).
Poi in tutti i programmi occorre sostituire CList con CList2 ecc...
Mi sembrava più semplice "correggere" la SerializeElements definita in
afxtempl.h e via....
Ciao
b.b.

 afxtempl.h
Sicuramente è più semplice, ma sicuramente denota anche che la programmazione 
non è il tuo forte... 
-- 
Luc

non è il tuo forte...
Forse non mi sono spiegato bene.
provo a riassumere:
1 - c'è un bug molto serio in MFC 6.0 (almeno a mio avviso).
mi piacerebbe tra l'altro avere il vs. parere
Se non  ti è chiaro il bug è riassumibile così:
1.1 la CArchive.Read NON tira eccezioni se leggi oltre eof (diciamo pure by
design, tanto è vero che ritorna il 
n.ro
 di bytes letti, in linea con le
varie read di basso livello)
1.2 preso atto di ciò, chi usa Read DEVE controllare che cacchio ha letto!
1.3 la SerializeElements della MFC 6.0 (file afxtempl.h linea 89) usa la
suddetta Read e NON controlla il valore di ritorno
1.4 tale SerializeElemens viene chiamata da QUALSIASI programma che
serializza collezioni MFC e non fornisce una implementazione del template
per il proprio tipo.
2 - non sono al corrente se Microsoft abbia intenzione di rilasciare
ulteriori SP per VS6. Comunque ho già segnalato il BUG e ho anche verificato
nelle MFC7 dove nonostatnte il codice sia leggermente cambiato, il bug
persiste!
3 - a questo punto ho decine di progetti che potenzialmente hanno un
problema.
In un caso specifico il problema si è concretizzato, e in quel particolare
progetto ho indagato e risolto fornendo l'implementazione corretta della
SerializeElements per i miei tipi (che fortunatamente erano solo 2!!!) che
serializzo attraverso collezioni.
Devo decidere cosa fare dei restanti progetti:
3.1 - me ne frego, tanto la possibilità che si verifichino problemi è bassa
3.2 - Indago per settimane alla ricerca di tutti i tipi che serializzo (e
comunque non escludo che qualche pezzo di MFC venga serializzato in modo
errato, BTW ho già controllato le CString che sono OK in quanto non usano
Read ma l'operatore >>)
3.3 - Ipotizzo che MS no rilascerà ulteriori SP, correggo afxtempl.h sui PC
del mio gruppo di sviluppo, attacco warning ovunque e ricompilo tutto il
malloppo. Pianto il file in questione in readonly e se non basta invento un
trucco che controlla se per caso viene modificato (installazione di
patch....)
Sarei interessato a sapere che cosa ne pensate.
Ciao
b.b.
P.S.
non vorrei avvaire un flame, ma mi potresti spiegare cortesemente perchè


 
Se ti trovassi in un ambiente Open Source, (sempre che anche lì la 
licenza lo permetta) potresti scrivere tu la patch e sottoporla 
all'attenzione del gruppo di sviluppo. Con M$ non so.
Ripeto, per te risulta più semplice scriverti una classe che ridefinisce 
(come hai già fatto), mettendola in una libreria e utilizzarla anche 
negli altri progetti al posto di quella bacata. (era questo che 
intendevo nel mio post)
La questione diventa quindi: "Come fare a sottoporre a M$ questo baco in 
modo che (si spera) qualcuno lo corregga e rialsci l'ennesima pezza?"
LP
PS: Questo modo, piuttosto che una tua correzione della suddetta classe, 
è preferibile anche per il fatto che se sposti il sorgente su un altro 
computer o reinstalli VS, il tuo programma continuerebbe a compilare 
senza problemi. L'alternativa sarebbe di ricordarsi di patchare TUTTE le 
distribuzioni di VS dove vuoi compilare il tuo programma.


Ho provato su microsoft.public.vc.mfc ma fanno orecchie da mercante
P.S.
Non ho ancora avuto da nessuno risposte riguardo la questione principale:
Ma secondo voi è un BUG?
Nessuno di voi serializza collezioni MFC?
Non siete preoccupati?
Se qualcuno è interessato posso postare un programmino di 50 righe che
dimostra il problema!
Grazie
b.b.

 
LP

 >non è il tuo forte...
Evidentemente si riferiva al fatto che intendevi modificare direttamente
le librerie, una cosa molto poco elegante, ma il suo tono è indubbiamente
biasimevole...
Devo confessare che quando inizialmente ho letto il titolo del topic ho
pensato anche io che tu fossi uno dei soliti niubboni che non sanno usare
MFC, ma leggendo attentamente ho visto che non è affatto il tuo caso :-)
In effetti la questione che proponi è interessante, ma non sono affatto
d'accordo nel definire "bug" il problema che hai trovato: io piuttosto la
definirei "vulnerabilità", una vulnerabilità che a seconda delle
situazioni può anche portare a degli exploit di tipo DoS, ma secondo me
non è un "bug"; per evitare queste vulnerabilità in situazioni specifiche
dove vengono serializzati dati potenzialmente e/o volontariamente
danneggiati, un ipotetico programmatore potrebbe semplicemente inventare
un formato tale da evitare la vulnerabilità; ad esempio, il file
serializzato potrebbe contenere la data dell'ultima scrittura, e il
programma prima di aprire il file potrebbe controllare se la data scritta
nel file corrisponde effettivamente a quella riportata dal sistema
operativo.
Altrimenti sai quante potrebbero essere le mille altre cosette e cosettine
che potrebbero implicare vulnerabilità del programma? Quello che voglio
dire è che secondo me troppi altri controlli dovrebbe fare MFC prima di
prenedere dati dall'esterno (e già ne fa tanti), ma in tal modo potrebbe
soffrirne la velocità del programma, anche perché questi controlli
verrebbero fatti anche in situazioni in cui non sarebbero realmente
necessari.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 necessari.
Be' oddio, sempre che si possa parlare di problemi di velocità coi
processori d'oggi, che overcloccati sfondano i 6 gigahertz :-)


...
Resto dell'idea che la lettura oltre eof che non genera eccezioni sia un
bug...
... e che l'errore sia il mancato controllo del ritorno della ar.Read().
In ogni caso ho segnalato il problema:
http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx?feedbackid=11f1cf88-2255-4d39-866f-d265b12a85a3
Ciao
b.b.