CVE-2024-43768 AI-generated analysis
platform/external/skia, PDF backend (src/pdf/SkDeflate.cpp, zlib allocator callback skia_alloc_func)
Adds an integer-overflow bounds check to Skia's zlib allocator callback skia_alloc_func in src/pdf/SkDeflate.cpp so that nullptr is returned when items * size would not fit in size_t, instead of passing a wrapped-around size to sk_calloc_throw.
Root cause
skia_alloc_func<T>(void*, T items, T size), the zlib allocator callback in src/pdf/SkDeflate.cpp, computed SkToSizeT(items) * SkToSizeT(size) and passed the product straight to sk_calloc_throw. Nothing checked that size fits in size_t or that items * size fits in size_t, so an overflowing product could wrap and request a smaller allocation than requested.
How the fix works
- src/pdf/SkDeflate.cpp:skia_alloc_func: first checks SkTFitsIn<size_t>(size) and returns nullptr if size does not fit in size_t (relevant when zlib's T is wider than size_t).
- src/pdf/SkDeflate.cpp:skia_alloc_func: computes maxItems = SIZE_MAX / size and returns nullptr if maxItems < items, i.e. if items * size would overflow size_t. Only then does it call sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size)).
- Adds #include "include/private/base/SkTFitsIn.h" for SkTFitsIn; the commit message notes the only cherry-pick conflict was in the header includes.
Completeness
- Covers the single multiplication in skia_alloc_func, the only allocation site in the diff; skia_free_func is unchanged.
- The new code divides SIZE_MAX by size without first checking size != 0; the material does not show whether zlib can call the allocator with size 0, so this is noted only as a code observation.
- The check does not separately verify that items fits in size_t; it relies on the comparison maxItems < items (performed in the wider of the two types) to reject oversize items before SkToSizeT(items) is evaluated.
- No other zlib allocator callbacks within skia are shown in the material.
Behavior changes
- Allocation requests from zlib whose items*size would overflow size_t (or whose size does not fit in size_t) now receive nullptr from skia_alloc_func instead of a wrapped-around, too-small allocation.
- For non-overflowing requests behavior is unchanged (sk_calloc_throw of the exact product).
Per major
- Android 14: same fix: b5543cb8c6b9 in android-security-14.0.0_r15 (reviewed on skia-review 888996, cherry-picked from googleplex commit 4ac6d5834d4d...), with a conflict only in the header includes of src/pdf/SkDeflate.cpp; at android-security-14.0.0_r29 all 8/8 patched lines are present.
- Android 15: not affected per the bulletin; the patched region (8/8 lines) is present at android-security-15.0.0_r17.
- Android 16: not affected per the bulletin; the patched region (8/8 lines) is present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin; the patched region (8/8 lines) is present at android-security-17.0.0_r1.
Unknowns
- How the overflowing items/size values are reached from untrusted input (which PDF generation API or content) is not shown.
- How zlib and SkDeflateWStream handle a nullptr return from the allocator, and how an undersized buffer would have been used before the fix, are not shown.
- Whether zlib can ever call the allocator with size == 0 (which would make SIZE_MAX / size a division by zero) is not shown.
- Whether SkTFitsIn.h lives at include/private/base/SkTFitsIn.h in older Skia snapshots is not shown; backports may need to check the include path.
- The bulletin lists Android 12, 12L and 13 as affected, but the material only provides the Android 14 commit; the commits for 12/12L/13 are not shown.