CVE-2025-26416 AI-generated analysis
platform/external/skia, image codec (src/codec/SkBmpStandardCodec.cpp, BMP decoding)
In Skia's BMP decoder, SkBmpStandardCodec::initializeSwizzler now chooses the swizzler's destination format based on xformOnDecode() instead of colorXform(). The swizzler's output pixel format now matches the buffer that decodeRows actually writes into.
Root cause
SkBmpStandardCodec::initializeSwizzler used this->colorXform() to decide whether to set up the swizzler for the intermediate color-transform buffer (kXformSrcColorType, alpha forced to unpremul, kNo_ZeroInitialized). Per the commit message, the decoder only routes rows through the intermediate xform buffer when xformOnDecode() is true. onPrepareToDecode likewise calls resetXformBuffer only when xformOnDecode() is true. So when a color transform existed but xformOnDecode() was false, the swizzler was configured for kXformSrcColorType output while decodeRows wrote directly into the caller's destination buffer in its own color type. The added test shows the problematic case: an 8bpp indexed BMP decoded to kRGB_565_SkColorType with a linear sRGB color space. The test comments call this 'a < 32bpp buffer with a color transform' that 'should not crash'.
How the fix works
- src/codec/SkBmpStandardCodec.cpp:SkBmpStandardCodec::initializeSwizzler: the condition `if (this->colorXform())` becomes `if (this->xformOnDecode())`. swizzlerInfo now switches to kXformSrcColorType only when the decoder will actually use the intermediate xform buffer. In that case alpha is set to unpremul for premul destinations and fZeroInitialized to kNo_ZeroInitialized. Otherwise the swizzler is created with the caller's dstInfo.
- This aligns initializeSwizzler with SkBmpStandardCodec::onPrepareToDecode, which already gates resetXformBuffer(dstInfo.width()) on this->xformOnDecode().
- tests/CodecTest.cpp: adds DEF_TEST(Codec_bmp_indexed_colorxform) and the resource resources/images/bmp-size-32x32-8bpp.bmp. The test decodes the 8bpp BMP to kRGB_565_SkColorType with SkColorSpace::MakeSRGBLinear() via codec->getPixels(aps) and asserts kSuccess. It also adds an include of src/core/SkAutoPixmapStorage.h.
Completeness
- The fix covers the single swizzler-selection condition in SkBmpStandardCodec::initializeSwizzler. After the change, both the xform buffer allocation (onPrepareToDecode) and the swizzler output format are keyed on xformOnDecode().
- decodeRows itself is not changed. The fix relies on decodeRows already using xformOnDecode() to pick the destination, as stated in the commit message.
- Only SkBmpStandardCodec is touched. The material does not show the other BMP codec classes or other codecs that may use the same colorXform()/xformOnDecode() pattern, so their status cannot be judged.
- The regression test covers only one case: an 8bpp indexed BMP decoded to RGB_565 with a color space.
Behavior changes
- For BMP decodes where a color transform exists but is not applied on decode (xformOnDecode() false), the swizzler now writes the destination color type directly and respects the caller's fZeroInitialized option instead of forcing kNo_ZeroInitialized. No new error codes are introduced.
- Adds a new unit test, Codec_bmp_indexed_colorxform, and a new test resource.
Per major
- Android 14: same fix: platform/external/skia fc2ebb312c58 in android-security-14.0.0_r19 (cherry-pick of upstream skia-review 937497, Change-Id Iaf240852a9bcf0be02cda84f0e44576da8100dec). 8/8 lines of the patched region present at android-security-14.0.0_r29.
- Android 15: same fix: platform/external/skia a1c030a91f29 in android-security-15.0.0_r7. Same one-line change plus the same test and resource; only the CodecTest.cpp hunk location differs. 8/8 lines present at android-security-15.0.0_r17.
- Android 16: not affected (not listed by the bulletin). The patched region is present (8/8 lines) at android-security-16.0.0_r8.
- Android 17: not affected (not listed by the bulletin). The patched region is present (8/8 lines) at android-security-17.0.0_r1.
Unknowns
- The material does not include decodeRows or SkCodec::xformOnDecode(). The exact conditions under which xformOnDecode() is false while colorXform() is non-null are inferred from the commit message and the test, not shown directly.
- The material does not show the pixel size of kXformSrcColorType or the precise memory effect of the mismatch (for example whether it is an out-of-bounds write).
- The material does not show the other BMP codec classes in external/skia or other codecs, so whether they share the same colorXform()/xformOnDecode() mismatch is unknown.
- The bulletin lists Android 13 as affected, but the material includes no Android 13 fix commit.