
Heap corruption in WhatsApp's media picker
Corrupção de heap no seletor de mídia do WhatsApp afetando o WhatsApp para Android antes da versão 2.19.291
Um arquivo GIF é dividido em segmentos, marcados por um byte específico:
De acordo com o código-fonte, renderFrame chama DDGifSlurp para analisar um GIF, e getBitmap para exibir o GIF. Um buffer rasterBits é alocado pela função, e seu tamanho é calculado multiplicando a largura pela altura da imagem que está sendo processada no momento. Talvez para economizar espaço de memória e tempo, o mesmo buffer rasterBits será usado para todos os quadros/imagens no GIF. Portanto, é necessário que o buffer seja capaz de conter a maior imagem descrita no arquivo. Assim, o buffer é realocado conforme necessário se outra seção de imagem dentro do mesmo GIF descrever uma imagem maior (exigir mais espaço).
DDGifSlurp analisa o arquivo GIF em um loop, processando cada imagem/quadro no arquivo, e termina quando o registro de terminação é encontrado. Quando DGifGetImageDesc retorna GIF_ERROR (a), isso resulta em terminação antecipada (no caso do switch), fazendo com que o código que realoca o buffer rasterBits seja ignorado. Um trecho de DDGifSlurp é mostrado abaixo:
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);
}
Uma imagem GIF que possui o seguinte formato causará um travamento: