
Heap-Korruption im Media-Picker von WhatsApp
Heap corruption im Medienauswahldialog von WhatsApp, der WhatsApp für Android vor Version 2.19.291 betrifft
Eine GIF-Datei ist in Segmente unterteilt, die durch ein bestimmtes Byte gekennzeichnet sind:
Laut Quellcode ruft renderFrame DDGifSlurp auf, um ein GIF zu parsen, und getBitmap, um das GIF anzuzeigen. Ein rasterBits-Puffer wird von der Funktion allokiert, und seine Größe wird durch Multiplikation der Breite mit der Höhe des gerade verarbeiteten Bildes berechnet. Um möglicherweise Speicherplatz und Zeit zu sparen, wird derselbe rasterBits-Puffer für alle Frames/Bilder im GIF verwendet. Daher muss der Puffer in der Lage sein, das größte in der Datei beschriebene Bild aufzunehmen. Folglich wird der Puffer entsprechend neu allokiert, wenn ein anderer Bildabschnitt innerhalb desselben GIF ein größeres Bild beschreibt (mehr Platz benötigt).
DDGifSlurp parst die GIF-Datei in einer Schleife, verarbeitet jedes Bild/Frame in der Datei und endet, wenn der Terminate-Eintrag gefunden wird. Wenn DGifGetImageDesc GIF_ERROR zurückgibt (a), führt dies zu einem vorzeitigen Abbruch (im switch-case), sodass der Code zur Neuallokation des rasterBits-Puffers übersprungen wird. Ein Ausschnitt von DDGifSlurp ist unten gezeigt:
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);
}
Ein GIF-Bild mit dem folgenden Format führt zu einem Absturz: