CVE-2024-43097 AI-generated analysis
platform/external/skia, src/core/SkRegion.cpp (RunArray run storage used by SkRegion)
In Skia's SkRegion.cpp, RunArray::resizeToAtLeast now computes the 50% growth headroom with SkSafeMath::addInt and clamps the new element count to SK_MaxS32 on overflow, instead of letting `count += count >> 1` overflow a signed int before it is passed to realloc and stored as fCount.
Root cause
RunArray (src/core/SkRegion.cpp) is a grow-only buffer of SkRegionPriv::RunType. resizeToAtLeast(int count) added 50% headroom with `count += count >> 1` in plain int arithmetic. For a large enough requested count this addition overflows the signed int, so the value passed to fMalloc.realloc() and stored in fCount no longer reflects the requested size. operator[] checks bounds only with SkASSERT (debug builds), so release-build indexing relies on fCount being correct. The commit describes the issue as speculative, with no repro case.
How the fix works
- src/core/SkRegion.cpp:RunArray::resizeToAtLeast: `count += count >> 1` is replaced with an SkSafeMath instance; `newCount = safe.addInt(count, count >> 1)` does the addition with overflow tracking.
- If no overflow is reported (`safe` is true), the grown value is used. Otherwise count is clamped to SK_MaxS32, which is never smaller than the requested int count.
- The resulting count is used for fMalloc.realloc(count) and stored in fCount. The memcpy from the stack buffer still copies the old fCount elements.
Completeness
- resizeToAtLeast is the only RunArray method shown that reallocates fMalloc and updates fCount, and the headroom addition is its only arithmetic on count.
- The fix does not add runtime bounds checking to operator[] (still SkASSERT only) and does not validate the count requested by callers. A clamped request for SK_MaxS32 elements is left to fMalloc.realloc to handle (the class comment says RunArray uses sk_realloc_throw).
- Single-commit fix; only src/core/SkRegion.cpp changed.
Behavior changes
- When the 50% growth computation would overflow, the requested capacity becomes SK_MaxS32 elements instead of an overflowed value. Such a large request is left to the allocator, which per the class comment throws on failure.
- For sizes that do not overflow, the arithmetic result is unchanged.
Per major
- Android 14: same fix: commit 8d355fe1d079 in android-security-14.0.0_r15 (Bug 350118416). The patched resizeToAtLeast is visible in the code at android-security-14.0.0_r29; the line check reports 6/8 lines of the patched region present.
- Android 15: not affected per bulletin; 6/8 lines of the patched region present at android-security-15.0.0_r17.
- Android 16: not affected per bulletin; 6/8 lines of the patched region present at android-security-16.0.0_r8.
- Android 17: not affected per bulletin; 6/8 lines of the patched region present at android-security-17.0.0_r1.
Unknowns
- Which SkRegion operation sequence can push the run count high enough to overflow; the commit states there is no repro case.
- Whether AutoTMalloc::realloc takes a signed or unsigned count, i.e. what an overflowed value did on affected builds, and whether an out-of-bounds access actually followed.
- Why only 6/8 lines of the patched region match in the 14 to 17 tags.
- How the fix was applied to Android 12, 12L and 13 (listed as affected but no per-major data provided).