CVE-2024-0051 AI-generated analysis
platform/frameworks/av, libstagefright software OMX MPEG4/H.263 decoder (media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp)
Adds an end-of-list check to the outQueue search loop in SoftMPEG4::onQueueFilled. If the current output header is not found, the decoder now returns instead of walking past the end of the output buffer list.
Root cause
In SoftMPEG4::onQueueFilled, after a frame is decoded, the code searches outQueue (List<BufferInfo *>) for the BufferInfo whose mHeader equals outHeader, using `while ((*it)->mHeader != outHeader) ++it;`. The loop had no `it != outQueue.end()` guard. If outHeader was not in outQueue, the iterator moved past the end and was dereferenced. The code then used the resulting pointer as a BufferInfo: it wrote `outInfo->mOwnedByUs = false` and called `outQueue.erase(it)`. The commit message calls this an out of bounds read and write.
How the fix works
- media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp:SoftMPEG4::onQueueFilled: the loop condition becomes `it != outQueue.end() && (*it)->mHeader != outHeader`, so the iterator is never dereferenced at end().
- Same function: `if (it == outQueue.end()) return;` is added after the loop. When the header is not found, the function now returns early. It no longer dereferences `*it`, writes mOwnedByUs, erases from outQueue or calls notifyFillBufferDone.
Completeness
- The fix covers the one unguarded search loop in SoftMPEG4::onQueueFilled. It is a defensive check. It does not change the upstream condition that leaves outHeader missing from outQueue, and the material does not show that condition.
- On the not-found path, the function returns after the input buffer has already been consumed (inQueue.erase / notifyEmptyBufferDone). By then, the outHeader fields (nTimeStamp, nFlags, nOffset, nFilledLen) have also been written. The fix does not undo these side effects or signal an error.
- Per index search, the other SoftOMX decoders shown (SoftFlacDecoder, SoftMP3, SoftVorbis, SoftVPX) take `*outQueue.begin()` directly instead of searching the list. The same loop pattern does not appear elsewhere in the material.
Behavior changes
- When the current output header is not in outQueue, onQueueFilled now returns silently: no notifyFillBufferDone for that frame, no error event, and mNumSamplesOutput is not incremented.
- No change in behavior when the header is present in outQueue.
Per major
- Android 14: same fix: commit 3bedd18fd3f4 in android-security-14.0.0_r6 (Change-Id Ic230d10048193a785f185dc6a7de6f455f9318c1). At android-security-14.0.0_r29, 3/4 lines of the patched region are present.
- Android 15: not affected (not listed by the bulletin). At android-security-15.0.0_r17, 3/4 lines of the patched region are present, so the fixed code is in 15.
- Android 16: not affected / code absent: media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp does not exist at android-security-16.0.0_r8.
- Android 17: not affected / code absent: the patched file does not exist at android-security-17.0.0_r1.
Unknowns
- How outHeader is chosen earlier in onQueueFilled, and the exact condition under which it is missing from outQueue (the start of the function is not in the material).
- Why only 3 of 4 patched-region lines are reported present at the 14 and 15 tags.
- Whether SoftMPEG4.cpp was removed in Android 16 as part of a broader removal of OMX software codecs or for another reason (the material only shows the file is absent).
- Details of the POC, and the concrete memory impact beyond the 'out of bounds read and write' stated in the commit message.