diff --git a/dom/canvas/DrawTargetWebgl.cpp b/dom/canvas/DrawTargetWebgl.cpp index e1c7fcb4a2ea..56688ed23e65 100644 --- a/dom/canvas/DrawTargetWebgl.cpp +++ b/dom/canvas/DrawTargetWebgl.cpp @@ -413,8 +413,14 @@ void SharedContextWebgl::ClearCachesIfNecessary() { // not exceed the available texture limits and that shader creation succeeded. bool DrawTargetWebgl::Init(const IntSize& size, const SurfaceFormat format, const RefPtr& aSharedContext) { - MOZ_ASSERT(format == SurfaceFormat::B8G8R8A8 || - format == SurfaceFormat::B8G8R8X8); + switch (format) { + case SurfaceFormat::B8G8R8A8: + case SurfaceFormat::B8G8R8X8: + break; + default: + MOZ_ASSERT_UNREACHABLE("Unsupported format for DrawTargetWebgl."); + return false; + } mSize = size; mFormat = format; diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index 62a191f189bf..d119dd80bfe2 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -1797,8 +1797,11 @@ bool DrawTargetSkia::Init(const IntSize& aSize, SurfaceFormat aFormat) { // we need to have surfaces that have a stride aligned to 4 for interop with // cairo SkImageInfo info = MakeSkiaImageInfo(aSize, aFormat); + if (info.bytesPerPixel() != BytesPerPixel(aFormat)) { + return false; + } size_t stride = GetAlignedStride<4>(info.width(), info.bytesPerPixel()); - if (!stride) { + if (!stride || stride < info.minRowBytes64()) { return false; } SkSurfaceProps props(0, GetSkPixelGeometry()); @@ -1867,9 +1870,14 @@ bool DrawTargetSkia::Init(unsigned char* aData, const IntSize& aSize, MOZ_ASSERT((aFormat != SurfaceFormat::B8G8R8X8) || aUninitialized || VerifyRGBXFormat(aData, aSize, aStride, aFormat)); + SkImageInfo info = MakeSkiaImageInfo(aSize, aFormat); + if (info.bytesPerPixel() != BytesPerPixel(aFormat) || aStride <= 0 || + size_t(aStride) < info.minRowBytes64()) { + return false; + } + SkSurfaceProps props(0, GetSkPixelGeometry()); - mSurface = AsRefPtr(SkSurfaces::WrapPixels(MakeSkiaImageInfo(aSize, aFormat), - aData, aStride, &props)); + mSurface = AsRefPtr(SkSurfaces::WrapPixels(info, aData, aStride, &props)); if (!mSurface) { return false; } @@ -1894,6 +1902,13 @@ bool DrawTargetSkia::Init(RefPtr&& aSurface) { MOZ_ASSERT((format != SurfaceFormat::B8G8R8X8) || VerifyRGBXFormat(map->GetData(), size, map->GetStride(), format)); + SkImageInfo info = MakeSkiaImageInfo(size, format); + if (info.bytesPerPixel() != BytesPerPixel(format) || + size_t(map->GetStride()) < info.minRowBytes64()) { + delete map; + return false; + } + SkSurfaceProps props(0, GetSkPixelGeometry()); mSurface = AsRefPtr(SkSurfaces::WrapPixels( MakeSkiaImageInfo(size, format), map->GetData(), map->GetStride(), diff --git a/gfx/2d/HelpersSkia.h b/gfx/2d/HelpersSkia.h index 8febd014dba6..4921d6b4118a 100644 --- a/gfx/2d/HelpersSkia.h +++ b/gfx/2d/HelpersSkia.h @@ -41,7 +41,12 @@ static inline SkColorType GfxFormatToSkiaColorType(SurfaceFormat format) { return kRGBA_8888_SkColorType; default: MOZ_DIAGNOSTIC_CRASH("Unknown surface format"); - return kRGBA_8888_SkColorType; + switch (BytesPerPixel(format)) { + case 4: + return kRGBA_8888_SkColorType; + default: + return kAlpha_8_SkColorType; + } } } diff --git a/gfx/2d/RecordedEventImpl.h b/gfx/2d/RecordedEventImpl.h index 6e5d1cb4a639..19708fe9c491 100644 --- a/gfx/2d/RecordedEventImpl.h +++ b/gfx/2d/RecordedEventImpl.h @@ -3538,9 +3538,14 @@ inline bool RecordedSourceSurfaceCreation::PlayEvent( return false; } - RefPtr src = Factory::CreateWrappingDataSourceSurface( - mData, mSize.width * BytesPerPixel(mFormat), mSize, mFormat, - [](void* aClosure) { delete[] static_cast(aClosure); }, mData); + CheckedInt32 stride = CheckedInt32(mSize.width) * BytesPerPixel(mFormat); + RefPtr src; + if (!mSize.IsEmpty() && stride.isValid() && stride.value() > 0) { + src = Factory::CreateWrappingDataSourceSurface( + mData, stride.value(), mSize, mFormat, + [](void* aClosure) { delete[] static_cast(aClosure); }, + mData); + } if (src) { mDataOwned = false; } @@ -3580,18 +3585,23 @@ RecordedSourceSurfaceCreation::RecordedSourceSurfaceCreation(S& aStream) return; } - size_t size = 0; + CheckedInt size; if (mSize.width >= 0 && mSize.height >= 0) { - size = size_t(mSize.width) * size_t(mSize.height) * BytesPerPixel(mFormat); - mData = new (fallible) uint8_t[size]; + CheckedInt32 stride = CheckedInt32(mSize.width) * BytesPerPixel(mFormat); + if (stride.isValid() && stride.value() >= 0) { + size = CheckedInt(stride.value()) * size_t(mSize.height); + if (size.isValid()) { + mData = new (fallible) uint8_t[size.value()]; + } + } } if (!mData) { gfxCriticalNote << "RecordedSourceSurfaceCreation failed to allocate data of size " - << size; + << (size.isValid() ? size.value() : 0); aStream.SetIsBad(); } else { - aStream.read((char*)mData, size); + aStream.read((char*)mData, size.value()); } } diff --git a/gfx/2d/SourceSurfaceSkia.cpp b/gfx/2d/SourceSurfaceSkia.cpp index 322c0225478e..f740df4e8e79 100644 --- a/gfx/2d/SourceSurfaceSkia.cpp +++ b/gfx/2d/SourceSurfaceSkia.cpp @@ -131,12 +131,18 @@ bool SourceSurfaceSkia::InitFromImage(const sk_sp& aImage, aFormat != SurfaceFormat::UNKNOWN ? aFormat : SkiaColorTypeToGfxFormat(pixmap.colorType(), pixmap.alphaType()); + if (pixmap.info().bytesPerPixel() != BytesPerPixel(mFormat)) { + return false; + } mStride = pixmap.rowBytes(); } else if (aFormat != SurfaceFormat::UNKNOWN) { mFormat = aFormat; - SkImageInfo info = MakeSkiaImageInfo(mSize, mFormat); + const SkImageInfo& info = aImage->imageInfo(); + if (info.bytesPerPixel() != BytesPerPixel(mFormat)) { + return false; + } mStride = GetAlignedStride<4>(info.width(), info.bytesPerPixel()); - if (!mStride) { + if (mStride <= 0 || size_t(mStride) < info.minRowBytes64()) { return false; } } else {