
WhatsAppのメディアピッカーにおけるヒープ破損
Android版WhatsAppのバージョン2.19.291以前に影響するWhatsAppのメディアピッカーにおけるヒープ破損
GIFファイルは、特定のバイトで区切られたセグメントに分割されます。
ソースコードによると、renderFrameはDDGifSlurpを呼び出してGIFを解析し、getBitmapを呼び出してGIFを表示します。関数によってrasterBitsバッファが割り当てられ、そのサイズは現在処理中の画像の幅と高さを掛け合わせて計算されます。おそらくメモリと時間を節約するため、同じrasterBitsバッファがGIF内のすべてのフレーム/画像に使用されます。したがって、バッファはファイル内で最も大きな画像を格納できる必要があります。そのため、同じGIF内の別の画像セクションがより大きな画像(より多くのスペースを必要とする)を記述している場合、バッファはそれに応じて再割り当てされます。
DDGifSlurpはループ内でGIFファイルを解析し、ファイル内の各画像/フレームを処理し、終了レコードに遭遇すると終了します。DGifGetImageDescがGIF_ERRORを返すと (a)、早期終了 (switch case内で) となり、rasterBitsバッファを再割り当てするコードがスキップされます。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);
}
以下の形式を持つGIF画像はクラッシュを引き起こします: