Bug 163762: IntSize::area() should used checked arithmetic
authorddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 22 Oct 2016 06:38:36 +0000 (06:38 +0000)
committerddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 22 Oct 2016 06:38:36 +0000 (06:38 +0000)
<https://webkit.org/b/163762>

Reviewed by Darin Adler.

Source/WebCore:

No new tests since no change in nominal behavior.

* platform/graphics/IntSize.h:
(WebCore::IntSize::area): Change to return a
Checked<unsigned, T> value. Use WTF:: namespace to avoid
including another header.

* platform/graphics/IntRect.h:
(WebCore::IntRect::area): Ditto.

The remaining changes are to use the Checked<unsigned> return
value of IntSize::area() and IntRect::area() correctly in
context, in addition to items noted below.

* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::isTopLevelFullPagePlugin):
Declare contentWidth and contentHeight as float values to
prevent overflow when computing the area, and to make the
inequality comparison in the return statement uses the same type
for both sides.
* html/ImageData.cpp:
(WebCore::ImageData::ImageData):
* html/MediaElementSession.cpp:
(WebCore::isElementRectMostlyInMainFrame):
* platform/graphics/ImageBackingStore.h:
(WebCore::ImageBackingStore::setSize): Restructure logic to
compute area only once.
(WebCore::ImageBackingStore::clear):
* platform/graphics/ImageFrame.h:
(WebCore::ImageFrame::frameBytes):
* platform/graphics/ImageSource.cpp:
(WebCore::ImageSource::maximumSubsamplingLevel):
* platform/graphics/ca/LayerPool.cpp:
(WebCore::LayerPool::backingStoreBytesForSize):
* platform/graphics/cg/ImageDecoderCG.cpp:
(WebCore::ImageDecoder::frameBytesAtIndex):
* platform/graphics/filters/FEGaussianBlur.cpp:
(WebCore::FEGaussianBlur::platformApplySoftware):
* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::asUnmultipliedImage):
(WebCore::FilterEffect::asPremultipliedImage):
(WebCore::FilterEffect::copyUnmultipliedImage):
(WebCore::FilterEffect::copyPremultipliedImage):
(WebCore::FilterEffect::createUnmultipliedImageResult):
(WebCore::FilterEffect::createPremultipliedImageResult):
* platform/graphics/win/ImageBufferDataDirect2D.cpp:
(WebCore::ImageBufferData::getData): Update overflow check,
rename local variable to numBytes, and compute numBytes once.
* platform/graphics/win/ImageDecoderDirect2D.cpp:
(WebCore::ImageDecoder::frameBytesAtIndex):
* platform/image-decoders/ImageDecoder.cpp:
(WebCore::ImageDecoder::frameBytesAtIndex):
* platform/ios/LegacyTileLayerPool.mm:
(WebCore::LegacyTileLayerPool::bytesBackingLayerWithPixelSize):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::requiresCompositingForCanvas):
* rendering/shapes/Shape.cpp:
(WebCore::Shape::createRasterShape):

Source/WebKit2:

* Shared/ShareableBitmap.cpp:
(WebKit::ShareableBitmap::create): Add overflow check and return
nullptr on overflow.
(WebKit::ShareableBitmap::createShareable): Ditto.
(WebKit::ShareableBitmap::create): Change debug assert for
adequate buffer size check into release check.
* Shared/ShareableBitmap.h:
(WebKit::ShareableBitmap::numBytesForSize): Change to return a
Checked<unsigned, RecordOverflow> value.
(WebKit::ShareableBitmap::sizeInBytes):
* Shared/cairo/ShareableBitmapCairo.cpp:
(WebKit::ShareableBitmap::numBytesForSize): Ditto.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _takeViewSnapshot]): Call unsafeGet().

Tools:

* TestWebKitAPI/Tests/WebCore/IntRect.cpp:
(TestWebKitAPI::TEST): Call unsafeGet().
* TestWebKitAPI/Tests/WebCore/IntSize.cpp:
(TestWebKitAPI::TEST): Ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207708 268f45cc-cd09-0410-ab3c-d52691b4dbfc

27 files changed:
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLPlugInImageElement.cpp
Source/WebCore/html/ImageData.cpp
Source/WebCore/html/MediaElementSession.cpp
Source/WebCore/platform/graphics/ImageBackingStore.h
Source/WebCore/platform/graphics/ImageFrame.h
Source/WebCore/platform/graphics/ImageSource.cpp
Source/WebCore/platform/graphics/IntRect.h
Source/WebCore/platform/graphics/IntSize.h
Source/WebCore/platform/graphics/ca/LayerPool.cpp
Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp
Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
Source/WebCore/platform/graphics/filters/FilterEffect.cpp
Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.cpp
Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp
Source/WebCore/platform/image-decoders/ImageDecoder.cpp
Source/WebCore/platform/ios/LegacyTileLayerPool.mm
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/shapes/Shape.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/ShareableBitmap.cpp
Source/WebKit2/Shared/ShareableBitmap.h
Source/WebKit2/Shared/cairo/ShareableBitmapCairo.cpp
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp
Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp

index cc7351a..6da67ec 100644 (file)
@@ -1,3 +1,69 @@
+2016-10-21  David Kilzer  <ddkilzer@apple.com>
+
+        Bug 163762: IntSize::area() should used checked arithmetic
+        <https://webkit.org/b/163762>
+
+        Reviewed by Darin Adler.
+
+        No new tests since no change in nominal behavior.
+
+        * platform/graphics/IntSize.h:
+        (WebCore::IntSize::area): Change to return a
+        Checked<unsigned, T> value. Use WTF:: namespace to avoid
+        including another header.
+
+        * platform/graphics/IntRect.h:
+        (WebCore::IntRect::area): Ditto.
+
+        The remaining changes are to use the Checked<unsigned> return
+        value of IntSize::area() and IntRect::area() correctly in
+        context, in addition to items noted below.
+
+        * html/HTMLPlugInImageElement.cpp:
+        (WebCore::HTMLPlugInImageElement::isTopLevelFullPagePlugin):
+        Declare contentWidth and contentHeight as float values to
+        prevent overflow when computing the area, and to make the
+        inequality comparison in the return statement uses the same type
+        for both sides.
+        * html/ImageData.cpp:
+        (WebCore::ImageData::ImageData):
+        * html/MediaElementSession.cpp:
+        (WebCore::isElementRectMostlyInMainFrame):
+        * platform/graphics/ImageBackingStore.h:
+        (WebCore::ImageBackingStore::setSize): Restructure logic to
+        compute area only once.
+        (WebCore::ImageBackingStore::clear):
+        * platform/graphics/ImageFrame.h:
+        (WebCore::ImageFrame::frameBytes):
+        * platform/graphics/ImageSource.cpp:
+        (WebCore::ImageSource::maximumSubsamplingLevel):
+        * platform/graphics/ca/LayerPool.cpp:
+        (WebCore::LayerPool::backingStoreBytesForSize):
+        * platform/graphics/cg/ImageDecoderCG.cpp:
+        (WebCore::ImageDecoder::frameBytesAtIndex):
+        * platform/graphics/filters/FEGaussianBlur.cpp:
+        (WebCore::FEGaussianBlur::platformApplySoftware):
+        * platform/graphics/filters/FilterEffect.cpp:
+        (WebCore::FilterEffect::asUnmultipliedImage):
+        (WebCore::FilterEffect::asPremultipliedImage):
+        (WebCore::FilterEffect::copyUnmultipliedImage):
+        (WebCore::FilterEffect::copyPremultipliedImage):
+        (WebCore::FilterEffect::createUnmultipliedImageResult):
+        (WebCore::FilterEffect::createPremultipliedImageResult):
+        * platform/graphics/win/ImageBufferDataDirect2D.cpp:
+        (WebCore::ImageBufferData::getData): Update overflow check,
+        rename local variable to numBytes, and compute numBytes once.
+        * platform/graphics/win/ImageDecoderDirect2D.cpp:
+        (WebCore::ImageDecoder::frameBytesAtIndex):
+        * platform/image-decoders/ImageDecoder.cpp:
+        (WebCore::ImageDecoder::frameBytesAtIndex):
+        * platform/ios/LegacyTileLayerPool.mm:
+        (WebCore::LegacyTileLayerPool::bytesBackingLayerWithPixelSize):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::requiresCompositingForCanvas):
+        * rendering/shapes/Shape.cpp:
+        (WebCore::Shape::createRasterShape):
+
 2016-10-21  Gavin Barraclough  <barraclough@apple.com>
 
         WebPageProxy should not need PageActivityState
index 118040e..4bcc8b4 100644 (file)
@@ -589,9 +589,9 @@ bool HTMLPlugInImageElement::isTopLevelFullPagePlugin(const RenderEmbeddedObject
     auto& style = renderer.style();
     IntSize visibleSize = frame.view()->visibleSize();
     LayoutRect contentRect = renderer.contentBoxRect();
-    int contentWidth = contentRect.width();
-    int contentHeight = contentRect.height();
-    return is100Percent(style.width()) && is100Percent(style.height()) && contentWidth * contentHeight > visibleSize.area() * sizingFullPageAreaRatioThreshold;
+    float contentWidth = contentRect.width();
+    float contentHeight = contentRect.height();
+    return is100Percent(style.width()) && is100Percent(style.height()) && contentWidth * contentHeight > visibleSize.area().unsafeGet() * sizingFullPageAreaRatioThreshold;
 }
     
 void HTMLPlugInImageElement::checkSnapshotStatus()
index 75b7ca3..04c361e 100644 (file)
@@ -113,7 +113,7 @@ RefPtr<ImageData> ImageData::create(Ref<Uint8ClampedArray>&& byteArray, unsigned
 
 ImageData::ImageData(const IntSize& size)
     : m_size(size)
-    , m_data(Uint8ClampedArray::createUninitialized(size.area() * 4))
+    , m_data(Uint8ClampedArray::createUninitialized((size.area() * 4).unsafeGet()))
 {
     ASSERT(m_data);
 }
@@ -123,7 +123,7 @@ ImageData::ImageData(const IntSize& size, Ref<Uint8ClampedArray>&& byteArray)
     , m_data(WTFMove(byteArray))
 {
     ASSERT(m_data);
-    ASSERT_WITH_SECURITY_IMPLICATION(!m_data || (size.area() * 4) <= m_data->length());
+    ASSERT_WITH_SECURITY_IMPLICATION(!m_data || (size.area() * 4).unsafeGet() <= m_data->length());
 }
 
 }
index c2a3ab5..26d7727 100644 (file)
@@ -675,10 +675,10 @@ static bool isElementRectMostlyInMainFrame(const HTMLMediaElement& element)
 
     IntRect mainFrameRectAdjustedForScrollPosition = IntRect(-mainFrameView->documentScrollPositionRelativeToViewOrigin(), mainFrameView->contentsSize());
     IntRect elementRectInMainFrame = element.clientRect();
-    unsigned int totalElementArea = elementRectInMainFrame.area();
+    unsigned totalElementArea = elementRectInMainFrame.area().unsafeGet();
     elementRectInMainFrame.intersect(mainFrameRectAdjustedForScrollPosition);
 
-    return elementRectInMainFrame.area() > totalElementArea / 2;
+    return elementRectInMainFrame.area().unsafeGet() > totalElementArea / 2;
 }
 
 static bool isElementLargeRelativeToMainFrame(const HTMLMediaElement& element)
index c3ddd7d..99f6847 100644 (file)
@@ -51,10 +51,14 @@ public:
 
     bool setSize(const IntSize& size)
     {
-        if (size.isEmpty() || !m_pixels.tryReserveCapacity(size.area()))
+        if (size.isEmpty())
             return false;
 
-        m_pixels.resize(size.area());
+        unsigned area = size.area().unsafeGet();
+        if (!m_pixels.tryReserveCapacity(area))
+            return false;
+
+        m_pixels.resize(area);
         m_pixelsPtr = m_pixels.data();
         m_size = size;
         m_frameRect = IntRect(IntPoint(), m_size);
@@ -74,7 +78,7 @@ public:
 
     void clear()
     {
-        memset(m_pixelsPtr, 0, m_size.area() * sizeof(RGBA32));
+        memset(m_pixelsPtr, 0, (m_size.area() * sizeof(RGBA32)).unsafeGet());
     }
 
     void clearRect(const IntRect& rect)
index b21e7f9..e433ded 100644 (file)
@@ -109,7 +109,7 @@ public:
 
     IntSize size() const;
     IntSize sizeRespectingOrientation() const { return !m_orientation.usesWidthAsHeight() ? size() : size().transposedSize(); }
-    unsigned frameBytes() const { return hasNativeImage() ? size().area() * sizeof(RGBA32) : 0; }
+    unsigned frameBytes() const { return hasNativeImage() ? (size().area() * sizeof(RGBA32)).unsafeGet() : 0; }
     SubsamplingLevel subsamplingLevel() const { return m_subsamplingLevel; }
 
 #if !USE(CG)
index e835beb..909b8c1 100644 (file)
@@ -190,7 +190,7 @@ SubsamplingLevel ImageSource::maximumSubsamplingLevel()
     SubsamplingLevel level = SubsamplingLevel::First;
 
     for (; level < SubsamplingLevel::Last; ++level) {
-        if (frameSizeAtIndex(0, level).area() < maximumImageAreaBeforeSubsampling)
+        if (frameSizeAtIndex(0, level).area().unsafeGet() < maximumImageAreaBeforeSubsampling)
             break;
     }
 
index e463f79..d62de4c 100644 (file)
@@ -91,8 +91,9 @@ public:
     int maxY() const { return y() + height(); }
     int width() const { return m_size.width(); }
     int height() const { return m_size.height(); }
-    
-    unsigned area() const { return m_size.area(); }
+
+    template <typename T = WTF::CrashOnOverflow>
+    Checked<unsigned, T> area() const { return m_size.area<T>(); }
 
     void setX(int x) { m_location.setX(x); }
     void setY(int y) { m_location.setY(y); }
index 2db1aca..d39b650 100644 (file)
@@ -131,9 +131,10 @@ public:
 
     WEBCORE_EXPORT IntSize constrainedBetween(const IntSize& min, const IntSize& max) const;
 
-    unsigned area() const
+    template <typename T = WTF::CrashOnOverflow>
+    Checked<unsigned, T> area() const
     {
-        return abs(m_width) * abs(m_height);
+        return Checked<unsigned, T>(abs(m_width)) * abs(m_height);
     }
 
     size_t unclampedArea() const
index 344e964..0cf7f77 100644 (file)
@@ -56,7 +56,7 @@ HashSet<LayerPool*>& LayerPool::allLayerPools()
 
 unsigned LayerPool::backingStoreBytesForSize(const IntSize& size)
 {
-    return size.width() * size.height() * 4;
+    return (size.area() * 4).unsafeGet();
 }
 
 LayerPool::LayerList& LayerPool::listOfLayersWithSize(const IntSize& size, AccessType accessType)
index 785a8c0..70bde18 100644 (file)
@@ -336,7 +336,7 @@ bool ImageDecoder::frameHasAlphaAtIndex(size_t index) const
 unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
 {
     IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel);
-    return frameSize.area() * 4;
+    return (frameSize.area() * 4).unsafeGet();
 }
 
 NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode decodingMode) const
index e50ec66..fc39610 100644 (file)
@@ -539,7 +539,7 @@ void FEGaussianBlur::platformApplySoftware()
 
     IntSize paintSize = absolutePaintRect().size();
     paintSize.scale(filter().filterScale());
-    RefPtr<Uint8ClampedArray> tmpImageData = Uint8ClampedArray::createUninitialized(paintSize.width() * paintSize.height() * 4);
+    RefPtr<Uint8ClampedArray> tmpImageData = Uint8ClampedArray::createUninitialized((paintSize.area() * 4).unsafeGet());
     if (!tmpImageData) {
         WTFLogAlways("FEGaussianBlur::platformApplySoftware Unable to create buffer. Requested size was %d x %d\n", paintSize.width(), paintSize.height());
         return;
index 291edbd..2f742ca 100644 (file)
@@ -237,7 +237,7 @@ PassRefPtr<Uint8ClampedArray> FilterEffect::asUnmultipliedImage(const IntRect& r
     IntSize scaledSize(rect.size());
     ASSERT(!ImageBuffer::sizeNeedsClamping(scaledSize));
     scaledSize.scale(m_filter.filterScale());
-    auto imageData = Uint8ClampedArray::createUninitialized(scaledSize.width() * scaledSize.height() * 4);
+    auto imageData = Uint8ClampedArray::createUninitialized((scaledSize.area() * 4).unsafeGet());
     copyUnmultipliedImage(imageData.get(), rect);
     return WTFMove(imageData);
 }
@@ -247,7 +247,7 @@ PassRefPtr<Uint8ClampedArray> FilterEffect::asPremultipliedImage(const IntRect&
     IntSize scaledSize(rect.size());
     ASSERT(!ImageBuffer::sizeNeedsClamping(scaledSize));
     scaledSize.scale(m_filter.filterScale());
-    auto imageData = Uint8ClampedArray::createUninitialized(scaledSize.width() * scaledSize.height() * 4);
+    auto imageData = Uint8ClampedArray::createUninitialized((scaledSize.area() * 4).unsafeGet());
     copyPremultipliedImage(imageData.get(), rect);
     return WTFMove(imageData);
 }
@@ -316,14 +316,14 @@ void FilterEffect::copyUnmultipliedImage(Uint8ClampedArray* destination, const I
             IntSize inputSize(m_absolutePaintRect.size());
             ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
             inputSize.scale(m_filter.filterScale());
-            m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4);
+            m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized((inputSize.area() * 4).unsafeGet());
             if (!m_unmultipliedImageResult) {
                 WTFLogAlways("FilterEffect::copyUnmultipliedImage Unable to create buffer. Requested size was %d x %d\n", inputSize.width(), inputSize.height());
                 return;
             }
             unsigned char* sourceComponent = m_premultipliedImageResult->data();
             unsigned char* destinationComponent = m_unmultipliedImageResult->data();
-            unsigned char* end = sourceComponent + (inputSize.width() * inputSize.height() * 4);
+            unsigned char* end = sourceComponent + (inputSize.area() * 4).unsafeGet();
             while (sourceComponent < end) {
                 int alpha = sourceComponent[3];
                 if (alpha) {
@@ -356,14 +356,14 @@ void FilterEffect::copyPremultipliedImage(Uint8ClampedArray* destination, const
             IntSize inputSize(m_absolutePaintRect.size());
             ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
             inputSize.scale(m_filter.filterScale());
-            m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4);
+            m_premultipliedImageResult = Uint8ClampedArray::createUninitialized((inputSize.area() * 4).unsafeGet());
             if (!m_premultipliedImageResult) {
                 WTFLogAlways("FilterEffect::copyPremultipliedImage Unable to create buffer. Requested size was %d x %d\n", inputSize.width(), inputSize.height());
                 return;
             }
             unsigned char* sourceComponent = m_unmultipliedImageResult->data();
             unsigned char* destinationComponent = m_premultipliedImageResult->data();
-            unsigned char* end = sourceComponent + (inputSize.width() * inputSize.height() * 4);
+            unsigned char* end = sourceComponent + (inputSize.area() * 4).unsafeGet();
             while (sourceComponent < end) {
                 int alpha = sourceComponent[3];
                 destinationComponent[0] = static_cast<int>(sourceComponent[0]) * alpha / 255;
@@ -403,7 +403,7 @@ Uint8ClampedArray* FilterEffect::createUnmultipliedImageResult()
     IntSize resultSize(m_absolutePaintRect.size());
     ASSERT(!ImageBuffer::sizeNeedsClamping(resultSize));
     resultSize.scale(m_filter.filterScale());
-    m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(resultSize.width() * resultSize.height() * 4);
+    m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized((resultSize.area() * 4).unsafeGet());
     return m_unmultipliedImageResult.get();
 }
 
@@ -417,7 +417,7 @@ Uint8ClampedArray* FilterEffect::createPremultipliedImageResult()
     IntSize resultSize(m_absolutePaintRect.size());
     ASSERT(!ImageBuffer::sizeNeedsClamping(resultSize));
     resultSize.scale(m_filter.filterScale());
-    m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(resultSize.width() * resultSize.height() * 4);
+    m_premultipliedImageResult = Uint8ClampedArray::createUninitialized((resultSize.area() * 4).unsafeGet());
     return m_premultipliedImageResult.get();
 }
 
index b737252..6912e2b 100644 (file)
@@ -45,11 +45,11 @@ RefPtr<Uint8ClampedArray> ImageBufferData::getData(const IntRect& rect, const In
 {
     auto platformContext = context->platformContext();
 
-    Checked<unsigned, RecordOverflow> area = 4 * rect.area();
-    if (area.hasOverflowed())
+    auto numBytes = rect.area<RecordOverflow>() * 4;
+    if (numBytes.hasOverflowed())
         return nullptr;
 
-    auto result = Uint8ClampedArray::createUninitialized(area.unsafeGet());
+    auto result = Uint8ClampedArray::createUninitialized(numBytes.unsafeGet());
     unsigned char* resultData = result ? result->data() : nullptr;
     if (!resultData)
         return nullptr;
@@ -84,7 +84,7 @@ RefPtr<Uint8ClampedArray> ImageBufferData::getData(const IntRect& rect, const In
     if (!ok)
         return nullptr;
 
-    memcpy(result->data(), pixels, 4 * rect.area());
+    memcpy(result->data(), pixels, numBytes.unsafeGet());
 
     return result;
 }
index 995500b..b071d31 100644 (file)
@@ -172,7 +172,7 @@ unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsampl
         return 0;
 
     auto frameSize = frameSizeAtIndex(index, subsamplingLevel);
-    return frameSize.area() * 4;
+    return (frameSize.area() * 4).unsafeGet();
 }
 
 void ImageDecoder::setTargetContext(ID2D1RenderTarget* renderTarget)
index 436ed8d..babda89 100644 (file)
@@ -188,7 +188,7 @@ unsigned ImageDecoder::frameBytesAtIndex(size_t index) const
     if (m_frameBufferCache.size() <= index)
         return 0;
     // FIXME: Use the dimension of the requested frame.
-    return m_size.area() * sizeof(RGBA32);
+    return (m_size.area() * sizeof(RGBA32)).unsafeGet();
 }
 
 float ImageDecoder::frameDurationAtIndex(size_t index)
index 72dde89..e6a0d9f 100644 (file)
@@ -55,7 +55,7 @@ LegacyTileLayerPool* LegacyTileLayerPool::sharedPool()
 
 unsigned LegacyTileLayerPool::bytesBackingLayerWithPixelSize(const IntSize& size)
 {
-    return size.width() * size.height() * 4;
+    return (size.area() * 4).unsafeGet();
 }
 
 LegacyTileLayerPool::LayerList& LegacyTileLayerPool::listOfLayersWithSize(const IntSize& size, AccessType accessType)
index cee9cd2..b921d3e 100644 (file)
@@ -2544,7 +2544,7 @@ bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject&
         bool isCanvasLargeEnoughToForceCompositing = true;
 #else
         HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer.element());
-        bool isCanvasLargeEnoughToForceCompositing = canvas->size().area() >= canvasAreaThresholdRequiringCompositing;
+        bool isCanvasLargeEnoughToForceCompositing = canvas->size().area().unsafeGet() >= canvasAreaThresholdRequiringCompositing;
 #endif
         CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
         return compositingStrategy == CanvasAsLayerContents || (compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing);
index 4eb7f9c..6832d09 100644 (file)
@@ -196,7 +196,7 @@ std::unique_ptr<Shape> Shape::createRasterShape(Image* image, float threshold, c
         int minBufferY = std::max(0, marginRect.y() - imageRect.y());
         int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());
 
-        if (static_cast<unsigned>(imageRect.width() * imageRect.height() * 4) == pixelArrayLength) {
+        if ((imageRect.area() * 4).unsafeGet() == pixelArrayLength) {
             for (int y = minBufferY; y < maxBufferY; ++y) {
                 int startX = -1;
                 for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
index 2a00b0a..550af1a 100644 (file)
@@ -1,3 +1,25 @@
+2016-10-21  David Kilzer  <ddkilzer@apple.com>
+
+        Bug 163762: IntSize::area() should used checked arithmetic
+        <https://webkit.org/b/163762>
+
+        Reviewed by Darin Adler.
+
+        * Shared/ShareableBitmap.cpp:
+        (WebKit::ShareableBitmap::create): Add overflow check and return
+        nullptr on overflow.
+        (WebKit::ShareableBitmap::createShareable): Ditto.
+        (WebKit::ShareableBitmap::create): Change debug assert for
+        adequate buffer size check into release check.
+        * Shared/ShareableBitmap.h:
+        (WebKit::ShareableBitmap::numBytesForSize): Change to return a
+        Checked<unsigned, RecordOverflow> value.
+        (WebKit::ShareableBitmap::sizeInBytes):
+        * Shared/cairo/ShareableBitmapCairo.cpp:
+        (WebKit::ShareableBitmap::numBytesForSize): Ditto.
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _takeViewSnapshot]): Call unsafeGet().
+
 2016-10-21  Eric Carlson  <eric.carlson@apple.com>
 
         [MediaStream] Dynamically generate media capture sandbox extensions
index a43aa3b..8db0411 100644 (file)
@@ -66,10 +66,12 @@ void ShareableBitmap::Handle::clear()
 
 RefPtr<ShareableBitmap> ShareableBitmap::create(const IntSize& size, Flags flags)
 {
-    size_t numBytes = numBytesForSize(size);
-    
+    auto numBytes = numBytesForSize(size);
+    if (numBytes.hasOverflowed())
+        return nullptr;
+
     void* data = 0;
-    if (!tryFastMalloc(numBytes).getValue(data))
+    if (!tryFastMalloc(numBytes.unsafeGet()).getValue(data))
         return nullptr;
 
     return adoptRef(new ShareableBitmap(size, flags, data));
@@ -77,9 +79,11 @@ RefPtr<ShareableBitmap> ShareableBitmap::create(const IntSize& size, Flags flags
 
 RefPtr<ShareableBitmap> ShareableBitmap::createShareable(const IntSize& size, Flags flags)
 {
-    size_t numBytes = numBytesForSize(size);
+    auto numBytes = numBytesForSize(size);
+    if (numBytes.hasOverflowed())
+        return nullptr;
 
-    RefPtr<SharedMemory> sharedMemory = SharedMemory::allocate(numBytes);
+    RefPtr<SharedMemory> sharedMemory = SharedMemory::allocate(numBytes.unsafeGet());
     if (!sharedMemory)
         return nullptr;
 
@@ -90,9 +94,14 @@ RefPtr<ShareableBitmap> ShareableBitmap::create(const IntSize& size, Flags flags
 {
     ASSERT(sharedMemory);
 
-    size_t numBytes = numBytesForSize(size);
-    ASSERT_UNUSED(numBytes, sharedMemory->size() >= numBytes);
-    
+    auto numBytes = numBytesForSize(size);
+    if (numBytes.hasOverflowed())
+        return nullptr;
+    if (sharedMemory->size() < numBytes.unsafeGet()) {
+        ASSERT_NOT_REACHED();
+        return nullptr;
+    }
+
     return adoptRef(new ShareableBitmap(size, flags, sharedMemory));
 }
 
index fa0bb47..923aa1f 100644 (file)
@@ -125,9 +125,9 @@ private:
     ShareableBitmap(const WebCore::IntSize&, Flags, RefPtr<SharedMemory>);
 
 #if USE(CAIRO)
-    static size_t numBytesForSize(const WebCore::IntSize&);
+    static Checked<unsigned, RecordOverflow> numBytesForSize(const WebCore::IntSize&);
 #else
-    static size_t numBytesForSize(const WebCore::IntSize& size) { return size.width() * size.height() * 4; }
+    static Checked<unsigned, RecordOverflow> numBytesForSize(const WebCore::IntSize& size) { return size.area<RecordOverflow>() * 4; }
 #endif
 
 #if USE(CG)
@@ -141,7 +141,7 @@ private:
 #endif
 
     void* data() const;
-    size_t sizeInBytes() const { return numBytesForSize(m_size); }
+    size_t sizeInBytes() const { return numBytesForSize(m_size).unsafeGet(); }
 
     WebCore::IntSize m_size;
     Flags m_flags;
index 03e6841..31681e5 100644 (file)
@@ -40,9 +40,9 @@ namespace WebKit {
 
 static const cairo_format_t cairoFormat = CAIRO_FORMAT_ARGB32;
 
-size_t ShareableBitmap::numBytesForSize(const WebCore::IntSize& size)
+Checked<unsigned, RecordOverflow> ShareableBitmap::numBytesForSize(const WebCore::IntSize& size)
 {
-    return cairo_format_stride_for_width(cairoFormat, size.width()) * size.height();
+    return Checked<unsigned, RecordOverflow>(cairo_format_stride_for_width(cairoFormat, size.width())) * size.height();
 }
 
 static inline RefPtr<cairo_surface_t> createSurfaceFromData(void* data, const WebCore::IntSize& size)
index ebdbdd5..716902a 100644 (file)
@@ -1413,7 +1413,7 @@ static inline bool areEssentiallyEqualAsFloat(float a, float b)
 
     CARenderServerCaptureLayerWithTransform(MACH_PORT_NULL, self.layer.context.contextId, (uint64_t)self.layer, slotID, 0, 0, &transform);
     WebCore::IntSize imageSize = WebCore::expandedIntSize(WebCore::FloatSize(snapshotSize));
-    return WebKit::ViewSnapshot::create(slotID, imageSize, imageSize.width() * imageSize.height() * 4);
+    return WebKit::ViewSnapshot::create(slotID, imageSize, (imageSize.area() * 4).unsafeGet());
 #endif
 }
 
index 1ed39eb..a7065db 100644 (file)
@@ -1,3 +1,15 @@
+2016-10-21  David Kilzer  <ddkilzer@apple.com>
+
+        Bug 163762: IntSize::area() should used checked arithmetic
+        <https://webkit.org/b/163762>
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WebCore/IntRect.cpp:
+        (TestWebKitAPI::TEST): Call unsafeGet().
+        * TestWebKitAPI/Tests/WebCore/IntSize.cpp:
+        (TestWebKitAPI::TEST): Ditto.
+
 2016-10-21  James Craig  <jcraig@apple.com>
 
         Unreviewed: Added Aaron Chu <aaron_chu@apple.com> to contributors list.
index a290432..7392f06 100644 (file)
@@ -609,7 +609,7 @@ TEST(IntRect, AreaAndDistances)
 {
     WebCore::IntRect rect(10, 20, 100, 100);
 
-    EXPECT_EQ(10000U, rect.area());
+    EXPECT_EQ(10000U, rect.area().unsafeGet());
 }
 
 }
index f08e885..a55942f 100644 (file)
@@ -98,7 +98,7 @@ TEST(IntSize, DiagonalLengthAndArea)
     WebCore::IntSize test(1024, 768);
 
     EXPECT_EQ(1638400, test.diagonalLengthSquared());
-    EXPECT_EQ(786432U, test.area());
+    EXPECT_EQ(786432U, test.area().unsafeGet());
 }
 
 TEST(IntSize, Scale)