CVE-2024-0023 AI-generated analysis
platform/frameworks/av, media/codec2 sfplugin utils (Codec2BufferUtils, RGB to YUV conversion)
ConvertRGBToPlanarYUV in Codec2BufferUtils.cpp now bounds its conversion loops by the source view's crop rectangle (src.crop().width/height) instead of the view's full dimensions (src.width()/height()).
Root cause
Before the fix, ConvertRGBToPlanarYUV in media/codec2/sfplugin/utils/Codec2BufferUtils.cpp looped y over src.height() and x over src.width(), the full dimensions of the source C2GraphicView. Inside the loops it wrote dstY[x], dstU[x >> 1] and dstV[x >> 1] and advanced the source plane pointers by colInc. The only size check, dstStride * dstVStride * 3 / 2 > bufferSize, compares the destination against its own stride parameters, not against the loop extents. If the view's full dimensions exceed the crop region that the destination layout covers, the loops can process more rows and pixels than intended.
How the fix works
- media/codec2/sfplugin/utils/Codec2BufferUtils.cpp:ConvertRGBToPlanarYUV: the outer loop bound changes from src.height() to src.crop().height and the inner loop bound from src.width() to src.crop().width. The number of rows and pixels processed now follows the crop rectangle.
- Nothing else in the visible code changes: the bufferSize check, the plane pointer setup (pRed/pGreen/pBlue from src.data()), the colInc stepping and the color math are the same. The fix is a single commit that changes 2 lines.
Completeness
- The fix covers the conversion loop in ConvertRGBToPlanarYUV: the loop extents now come from the crop rectangle.
- The function still has no explicit check that src.crop().width <= dstStride or src.crop().height <= dstVStride. Correctness depends on how callers size the destination, and the material does not show that.
- The even-dimension CHECKs (lines 596-597) still test src.width() and src.height(), not the crop dimensions. An odd crop width or height is therefore not rejected, even though the chroma handling (x >> 1, y & 1) works in pairs of pixels and rows.
- The source plane pointers start at src.data()[PLANE_*] with no offset for crop().left/top. The material does not show whether data() already accounts for the crop origin.
Behavior changes
- RGB to YUV conversion now processes only the cropped region. When a view's full dimensions are larger than its crop, fewer rows and pixels are converted than before. The fix adds no new error codes or return paths.
Per major
- Android 14: Same fix. Resolved via bug_id in android-security-14.0.0_r4 (cherry-pick chain, Change-Id I42c71616c9d50f61c92f461f6a91f5addb1d724a). At android-security-14.0.0_r29 the loops use src.crop().height/width, as shown in the code context (5/7 lines of the patched region present).
- Android 15: Not affected per the bulletin. At android-security-15.0.0_r17, 5/7 lines of the patched region are present. The material does not say which lines match.
- Android 16: Not affected per the bulletin. At android-security-16.0.0_r8, 5/7 lines of the patched region are present.
- Android 17: Not affected per the bulletin. At android-security-17.0.0_r1, 5/7 lines of the patched region are present.
Unknowns
- The material does not show the callers of ConvertRGBToPlanarYUV or how they size the destination buffer relative to the crop.
- It does not show whether C2GraphicView::data() already includes the crop origin (left/top).
- It does not show the rest of the loop (the row pointer advancement after line 650).
- It does not show which process runs this code for a given trigger path.
- The PoC mentioned in the bug is not in the material, so the concrete triggering input is unknown.
- For 15/16/17, it is unknown which 5 of the 7 patched-region lines match.