
Corruzione dell'heap nel selettore multimediale di WhatsApp
Corruzione dell'heap nel selettore multimediale di WhatsApp che colpisce WhatsApp per Android precedente alla versione 2.19.291
Un file GIF è diviso in segmenti, contrassegnati da un byte specifico:
Secondo il codice sorgente, renderFrame chiama DDGifSlurp per analizzare un GIF e getBitmap per visualizzare il GIF. Un buffer rasterBits viene allocato dalla funzione e la sua dimensione viene calcolata moltiplicando la larghezza per l'altezza dell'immagine che sta attualmente elaborando. Forse per risparmiare spazio in memoria e tempo, lo stesso buffer rasterBits verrà utilizzato per tutti i fotogrammi/immagini nel GIF. Pertanto, è necessario che il buffer sia in grado di contenere l'immagine più grande descritta nel file. Di conseguenza, il buffer viene riallocato di conseguenza se un'altra sezione immagine all'interno dello stesso GIF descrive un'immagine più grande (richiede più spazio).
DDGifSlurp analizza il file GIF in un ciclo, elaborando ogni immagine/fotogramma nel file e termina quando viene incontrato il record di terminazione. Quando DGifGetImageDesc restituisce GIF_ERROR (a), si verifica una terminazione anticipata (nel caso switch), causando il salto del codice che rialloca il buffer rasterBits. Un frammento di DDGifSlurp è mostrato di seguito:
void DDGifSlurp(GifInfo *info, bool decode, bool exitAfterFrame) {
...
do {
...
switch (RecordType) {
case IMAGE_DESC_RECORD_TYPE:
if (DGifGetImageDesc(gifFilePtr, isInitialPass) == GIF_ERROR) { <-- [a]
break;
}
...
if (decode) {
...
const uint_fast32_t newRasterSize = gifFilePtr->Image.Width * gifFilePtr->Image.Height;
if (newRasterSize > info->rasterSize || widthOverflow > 0 || heightOverflow > 0) {
void *tmpRasterBits = reallocarray(info->rasterBits, newRasterSize, sizeof(GifPixelType));
...
}
}while (RecordType != TERMINATE_RECORD_TYPE);
}
Un'immagine GIF che ha il seguente formato causerà un crash: