Reject fdAT chunks with data_length < 4 in APNG parser to prevent heap overflow#184301
Reject fdAT chunks with data_length < 4 in APNG parser to prevent heap overflow#184301mohammadmseet-hue wants to merge 4 commits into
Conversation
When converting fdAT chunks to IDAT chunks during APNG demuxing, DemuxNextImage() subtracts 4 from data_length to remove the fdAT sequence number. If an fdAT chunk has data_length < 4, this uint32_t subtraction underflows to ~4GB (0xFFFFFFFC for data_length=0). The underflowed value is then used as the length argument to memcpy, causing a heap buffer overflow. A crafted APNG image served from any HTTP server can trigger this when loaded by a Flutter application via Image.network() or similar APIs. The APNG parser is registered as a default image decoder and runs on all image data with a valid PNG signature + acTL chunk. This commit adds bounds checks in both the chunk_space calculation loop and the fdAT-to-IDAT conversion loop to reject fdAT chunks with insufficient data before the subtraction occurs. Related prior fixes in this file: - PR flutter#56928: frame offset bounds check - PR flutter#57025: integer wrapping fix for the bounds check Neither addressed the fdAT data_length underflow.
|
It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
There was a problem hiding this comment.
Code Review
This pull request introduces bounds checking for APNG fdAT chunks to prevent potential heap buffer overflows caused by uint32_t underflow. The reviewer pointed out that the validation check is redundantly implemented in two separate loops within the same function and suggested consolidating the logic by removing the unreachable second check.
| // Reject fdAT chunks with insufficient data to contain the | ||
| // 4-byte sequence number. Without this check, the subtraction | ||
| // underflows uint32_t and causes a heap buffer overflow. | ||
| if (c->get_data_length() < 4) { | ||
| return std::make_pair(std::nullopt, nullptr); | ||
| } |
There was a problem hiding this comment.
This entire block (comment and check) is redundant. An identical check is performed for all fdAT chunks within the same image_chunks collection earlier in this function at lines 477-479. Since that first check will cause an early return for any invalid chunk, this second check is unreachable for invalid data. To improve clarity and avoid redundancy, I suggest removing this block. You might consider moving this detailed comment to the first check at line 477 to retain the important context about the vulnerability.
This comment was marked as outdated.
This comment was marked as outdated.
Tests that malformed APNG images with fdAT chunks whose data_length is less than the required 4 bytes (for the sequence number) do not cause crashes. Without the bounds check, the uint32_t subtraction in DemuxNextImage() underflows and causes a heap buffer overflow. Three test cases: - fdAT with data_length=0 (underflows to 0xFFFFFFFC) - fdAT with data_length=2 (underflows to 0xFFFFFFFE) - fdAT with data_length=8 (valid, should be accepted)
Extend the data_length validation to cover two additional chunk types that use CastChunkData<T>() without size checks: - acTL (line 272): reject if data_length < sizeof(AnimationControlChunkData) Prevents heap OOB read of num_frames and num_plays fields. - fcTL (line 419): reject if data_length < sizeof(FrameControlChunkData) Prevents heap OOB read of width, height, offsets, delay, and blend/dispose operation fields. Same vulnerability class as the fdAT fix in the previous commit.
Add image_generator_apng_unittests.cc to ui_unittests sources so the fdAT/fcTL/acTL data_length validation tests are compiled and run.
|
@bdero @jason-simmons Could you review this when you get a chance? This PR fixes 3 heap buffer overflow vulnerabilities in the APNG parser (
Latest commit wires the unit tests into BUILD.gn (was missing before). All 3 tests + a positive validation test included. |
|
Thank you for your contribution! Sorry for the delay in reviewing. I've created a new PR containing your branch plus some additional changes: #186700 |
…ing malformed fdAT chunks (flutter#186700) An fdAT (frame data) chunk in an APNG should contain a sequence number followed by image data. The APNG decoder needs to reject invalid fdAT chunks that do not have the expected contents. Based on flutter#184301 and flutter#183180 Fixes flutter#183179 --------- Co-authored-by: 1seal <[email protected]> Co-authored-by: mohammadmseet-hue <[email protected]>
|
The #186700 version of this fix has been merged. |
Summary
The APNG parser in
image_generator_apng.cchas an integer underflow inDemuxNextImage()that leads to a heap buffer overflow when processing crafted APNG images with malformed fdAT chunks.The Bug
When converting fdAT chunks to IDAT chunks, the code subtracts 4 from
data_lengthto remove the 4-byte sequence number (line 519):If an fdAT chunk has
data_length < 4, thisuint32_tsubtraction underflows:The underflowed value is then passed to
memcpy(lines 525-527):The same issue exists in the
chunk_spacecalculation (line 477), wherechunk_space -= 4can produce an undersized allocation.Attack Vector
Any Flutter application that loads images from external sources is affected:
The APNG parser is registered as a default image decoder in
ImageGeneratorRegistryand processes all image data with a valid PNG signature +acTLchunk. The trigger flow:data_lengthis 0DemuxNextImage()on the malicious fdAT chunkmemcpywith ~4GB length → heap buffer overflowNo user interaction is required beyond the application loading the image.
The Fix
This commit adds
data_length < 4checks in both locations:Both checks return
std::make_pair(std::nullopt, nullptr)to gracefully fail the decode.PoC
A valid APNG with this structure triggers the vulnerability:
When loaded by a Flutter app, frame 1 decode triggers the heap overflow.
Related Prior Fixes
data_lengthunderflow — this is a distinct vulnerability in a different code path within the same function.Impact