
Corrupción de heap en el selector de medios de WhatsApp
Corrupción de montón en el selector de medios de WhatsApp que afecta a WhatsApp para Android antes de la versión 2.19.291
Un archivo GIF está dividido en segmentos, marcados por un byte específico:
Según el código fuente, renderFrame llama a DDGifSlurp para analizar un GIF y a getBitmap para mostrar el GIF. La función asigna un búfer rasterBits, cuyo tamaño se calcula multiplicando el ancho por la altura de la imagen que está procesando en ese momento. Quizá para ahorrar espacio de memoria y tiempo, el mismo búfer rasterBits se utilizará para todos los fotogramas/imágenes del GIF. Por lo tanto, se requiere que el búfer sea capaz de contener la imagen más grande descrita en el archivo. Así, el búfer se reasigna en consecuencia si otra sección de imagen dentro del mismo GIF describe una imagen más grande (requiere más espacio).
DDGifSlurp analiza el archivo GIF en un bucle, procesando cada imagen/fotograma del archivo, y termina cuando se encuentra el registro de terminación. Cuando DGifGetImageDesc devuelve GIF_ERROR (a), se produce una terminación anticipada (en el caso del switch), lo que hace que se omita el código que reasigna el búfer rasterBits. A continuación se muestra un fragmento de DDGifSlurp:
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);
}
Una imagen GIF con el siguiente formato provocará un fallo: