CVE-2024-49749 AI-generated analysis
platform/external/giflib, GIF decoder (dgif_lib.c, DGifSlurp)
Replaces a broken (effectively dead) overflow check in DGifSlurp with a correct one that rejects non-positive or overflowing ImageDesc.Width * ImageDesc.Height before RasterBits is allocated.
Root cause
In dgif_lib.c DGifSlurp, the guard before computing ImageSize was written as `Width < 0 && Height < 0 && Width > (INT_MAX / Height)`. Because it required both dimensions to be negative, it never rejected the real problem case: large positive Width and Height whose product overflows. ImageSize = Width * Height could then wrap, and the wrapped value is passed to reallocarray(NULL, ImageSize, sizeof(GifPixelType)), producing a RasterBits buffer smaller than the image dimensions imply. The old check also did not reject zero dimensions.
How the fix works
- dgif_lib.c:DGifSlurp: the condition is changed to `Width <= 0 || Height <= 0 || Width > (INT_MAX / Height)`, returning GIF_ERROR. This rejects non-positive dimensions (which also rules out dividing by Height == 0) and rejects any pair whose product would exceed INT_MAX, so the subsequent `ImageSize = Width * Height` cannot overflow.
- The existing `ImageSize > (SIZE_MAX / sizeof(GifPixelType))` check and the reallocarray call are unchanged. The new check runs before them and is the one that actually prevents the multiplication from wrapping.
Completeness
- Covers the single multiplication in DGifSlurp that sizes sp->RasterBits. The guard is now correct for all int values of Width and Height.
- Single-commit fix: no other functions in dgif_lib.c are changed. The material does not show whether other callers that compute Width*Height from ImageDesc (outside DGifSlurp, e.g. consumers using DGifGetLine directly) have equivalent checks.
- The code context at android-security-14.0.0_r29 shows the fixed condition in place, matching the diff.
Behavior changes
- GIF images whose image descriptor has Width == 0 or Height == 0 are now rejected by DGifSlurp with GIF_ERROR. Previously they were allowed to proceed with a zero-sized allocation.
- Images where Width * Height would exceed INT_MAX are now rejected with GIF_ERROR instead of being allocated with a wrapped size.
- Callers such as GIFMovie (frameworks/base/libs/hwui/jni/GIFMovie.cpp) treat a DGifSlurp failure as a failed decode and close the file, per index search.
Per major
- Android 14: same fix: commit 3281e14f6b9b in android-security-14.0.0_r16 (cherry-pick, Change-Id Ieef04e789acf783eda2dff2cd9284ed204f1d117). The fixed condition is present at android-security-14.0.0_r29 (4/6 lines of the patched region match).
- Android 15: same fix: commit b3aea8d187b1 in android-security-15.0.0_r4, identical diff. At android-security-15.0.0_r17, 4/6 lines of the patched region are present.
- Android 16: not affected (not listed by the bulletin). At android-security-16.0.0_r8, 4/6 lines of the patched region are present.
- Android 17: not affected (not listed by the bulletin). At android-security-17.0.0_r1, 4/6 lines of the patched region are present.
Unknowns
- The material does not show the downstream write that the undersized RasterBits buffer leads to. The context stops at the start of the interlaced loop.
- Whether Android 12/12L/13 received the same commit. The bulletin lists them as affected, but no commit material is provided for them.
- Whether other Width*Height computations elsewhere in giflib or its consumers carry an equivalent guard.