This is an automated email from the git hooks/post-receive script.
pierov pushed a commit to branch tor-browser-91.10.0esr-11.0-1 in repository tor-browser.
commit 7967e9aebf8532e5d149feba418fde16bf2dd5f6 Author: Lee Salzman lsalzman@mozilla.com AuthorDate: Tue May 10 05:26:44 2022 +0000
Bug 1767365 - Clip image data transfers. r=aosmond, a=RyanVM
Differential Revision: https://phabricator.services.mozilla.com/D145674 --- dom/canvas/CanvasRenderingContext2D.cpp | 28 +++++++++++++++++----------- gfx/2d/BaseRect.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index b80b371d2867e..1098cb8d811e2 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -5044,6 +5044,16 @@ already_AddRefed<ImageData> CanvasRenderingContext2D::GetImageData( return MakeAndAddRef<ImageData>(w, h, *array); }
+static IntRect ClipImageDataTransfer(IntRect& aSrc, const IntPoint& aDestOffset, + const IntSize& aDestBounds) { + IntRect dest = aSrc; + dest.SafeMoveBy(aDestOffset); + dest = IntRect(IntPoint(0, 0), aDestBounds).SafeIntersect(dest); + + aSrc = aSrc.SafeIntersect(dest - aDestOffset); + return aSrc + aDestOffset; +} + nsresult CanvasRenderingContext2D::GetImageDataArray( JSContext* aCx, int32_t aX, int32_t aY, uint32_t aWidth, uint32_t aHeight, nsIPrincipal& aSubjectPrincipal, JSObject** aRetval) { @@ -5073,9 +5083,9 @@ nsresult CanvasRenderingContext2D::GetImageDataArray( return NS_OK; }
- IntRect srcRect(0, 0, mWidth, mHeight); - IntRect destRect(aX, aY, aWidth, aHeight); - IntRect srcReadRect = srcRect.Intersect(destRect); + IntRect dstWriteRect(0, 0, aWidth, aHeight); + IntRect srcReadRect = ClipImageDataTransfer(dstWriteRect, IntPoint(aX, aY), + IntSize(mWidth, mHeight)); if (srcReadRect.IsEmpty()) { *aRetval = darray; return NS_OK; @@ -5100,9 +5110,6 @@ nsresult CanvasRenderingContext2D::GetImageDataArray( return NS_ERROR_OUT_OF_MEMORY; }
- IntRect dstWriteRect = srcReadRect; - dstWriteRect.MoveBy(-aX, -aY); - // Check for site-specific permission. This check is not needed if the // canvas was created with a docshell (that is only done for special // internal uses). @@ -5253,10 +5260,10 @@ void CanvasRenderingContext2D::PutImageData_explicit( dirtyRect = imageDataRect; }
- dirtyRect.MoveBy(IntPoint(aX, aY)); - dirtyRect = IntRect(0, 0, mWidth, mHeight).Intersect(dirtyRect); - - if (dirtyRect.Width() <= 0 || dirtyRect.Height() <= 0) { + IntRect srcRect = dirtyRect; + dirtyRect = ClipImageDataTransfer(srcRect, IntPoint(aX, aY), + IntSize(mWidth, mHeight)); + if (dirtyRect.IsEmpty()) { return; }
@@ -5311,7 +5318,6 @@ void CanvasRenderingContext2D::PutImageData_explicit( dstFormat = sourceSurface->GetFormat(); }
- IntRect srcRect = dirtyRect - IntPoint(aX, aY); uint8_t* srcData = arr.Data() + srcRect.y * (width * 4) + srcRect.x * 4;
PremultiplyData( diff --git a/gfx/2d/BaseRect.h b/gfx/2d/BaseRect.h index 8d0a3f1db1c72..b72d6c1d5548b 100644 --- a/gfx/2d/BaseRect.h +++ b/gfx/2d/BaseRect.h @@ -313,6 +313,39 @@ struct BaseRect { height = aSize.height; }
+ // Variant of MoveBy that ensures that even after translation by a point that + // the rectangle coordinates will still fit within numeric limits. The origin + // and size will be clipped within numeric limits to ensure this. + void SafeMoveByX(T aDx) { + T x2 = XMost(); + if (aDx >= T(0)) { + T limit = std::numeric_limits<T>::max(); + x = limit - aDx < x ? limit : x + aDx; + width = (limit - aDx < x2 ? limit : x2 + aDx) - x; + } else { + T limit = std::numeric_limits<T>::min(); + x = limit - aDx > x ? limit : x + aDx; + width = (limit - aDx > x2 ? limit : x2 + aDx) - x; + } + } + void SafeMoveByY(T aDy) { + T y2 = YMost(); + if (aDy >= T(0)) { + T limit = std::numeric_limits<T>::max(); + y = limit - aDy < y ? limit : y + aDy; + height = (limit - aDy < y2 ? limit : y2 + aDy) - y; + } else { + T limit = std::numeric_limits<T>::min(); + y = limit - aDy > y ? limit : y + aDy; + height = (limit - aDy > y2 ? limit : y2 + aDy) - y; + } + } + void SafeMoveBy(T aDx, T aDy) { + SafeMoveByX(aDx); + SafeMoveByY(aDy); + } + void SafeMoveBy(const Point& aPoint) { SafeMoveBy(aPoint.x, aPoint.y); } + void Inflate(T aD) { Inflate(aD, aD); } void Inflate(T aDx, T aDy) { x -= aDx;