Guard against overflow in blur code.

This fuzz creates a blur that has w = 1 and h = 2^31 - epsilon.
And a filter sigma of 360. This causes the intermediate
buffer size > 2^31. This causes the multiply in the following
code SkMaskBlurFilter.cpp:1023:

  tmpStart + tmpW * tmpH

to overflow. Because tmpW = source height, which is near 2^31,
and tmpH is about 3*360.

Cause the blur to fail if the intermediate buffer is > INT_MAX.

Bug: oss-fuzz:49061
Change-Id: I4f9f6bbe76cd71da1ac86562771ca393852452c4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/558305
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2022-07-13 10:52:52 -04:00 committed by SkCQ
parent 2fd7b18043
commit b70a030066

View File

@ -11,6 +11,8 @@
#include "include/private/SkTo.h"
#include "src/core/SkSafeMath.h"
#include <climits>
/** returns the product if it is positive and fits in 31 bits. Otherwise this
returns 0.
*/
@ -57,27 +59,29 @@ SkMask SkMask::PrepareDestination(int radiusX, int radiusY, const SkMask& src) {
SkSafeMath safe;
SkMask dst;
dst.fImage = nullptr;
dst.fFormat = SkMask::kA8_Format;
// dstW = srcW + 2 * radiusX;
size_t dstW = safe.add(src.fBounds.width(), safe.add(radiusX, radiusX));
// dstH = srcH + 2 * radiusY;
size_t dstH = safe.add(src.fBounds.height(), safe.add(radiusY, radiusY));
if (!SkTFitsIn<int>(dstW) || !SkTFitsIn<int>(dstH)) {
dst.fBounds.setEmpty();
dst.fRowBytes = 0;
} else {
dst.fBounds.setWH(SkTo<int>(dstW), SkTo<int>(dstH));
dst.fBounds.offset(src.fBounds.x(), src.fBounds.y());
dst.fBounds.offset(-radiusX, -radiusY);
dst.fRowBytes = SkTo<uint32_t>(dstW);
}
dst.fImage = nullptr;
dst.fFormat = SkMask::kA8_Format;
size_t toAlloc = safe.mul(dstW, dstH);
if (safe && src.fImage != nullptr) {
// We can only deal with masks that fit in INT_MAX and sides that fit in int.
if (!SkTFitsIn<int>(dstW) || !SkTFitsIn<int>(dstH) || toAlloc > INT_MAX || !safe) {
dst.fBounds.setEmpty();
dst.fRowBytes = 0;
return dst;
}
dst.fBounds.setWH(SkTo<int>(dstW), SkTo<int>(dstH));
dst.fBounds.offset(src.fBounds.x(), src.fBounds.y());
dst.fBounds.offset(-radiusX, -radiusY);
dst.fRowBytes = SkTo<uint32_t>(dstW);
if (src.fImage != nullptr) {
dst.fImage = SkMask::AllocImage(toAlloc);
}