Title: [292757] trunk/Source
Revision
292757
Author
mmaxfi...@apple.com
Date
2022-04-11 20:00:18 -0700 (Mon, 11 Apr 2022)

Log Message

[WebGPU] Use checked arithmetic
https://bugs.webkit.org/show_bug.cgi?id=239058

Reviewed by Kimmo Kinnunen.

We have a bunch of places where overflow can occur.

Luckily, we can just detect overflow inside the validation functions, and not have
to do any inside the code that creates platform types (NSUInteger, etc.). This is
because if the validation code succeeds, then we are guaranteed that the cast to
NSUIntegers will succeed. This is because ranges in a resource are checked against
the size of the resource, and the size of the resource has been checked against
platform maximums, which are guaranteed to be smaller than the largest NSUInteger.

* WebGPU/BindGroup.mm:
(WebGPU::Device::createBindGroup):
* WebGPU/Buffer.mm:
(WebGPU::Buffer::validateGetMappedRange const):
(WebGPU::Buffer::getMappedRange):
(WebGPU::Buffer::validateMapAsync const):
(WebGPU::Buffer::mapAsync):
* WebGPU/CommandEncoder.mm:
(WebGPU::CommandEncoder::validateCopyBufferToBuffer):
(WebGPU::CommandEncoder::copyBufferToTexture):
(WebGPU::CommandEncoder::copyTextureToBuffer):
(WebGPU::CommandEncoder::copyTextureToTexture):
(WebGPU::CommandEncoder::validateClearBuffer):
(WebGPU::CommandEncoder::clearBuffer):
* WebGPU/Queue.mm:
(WebGPU::Queue::validateWriteBuffer const):
(WebGPU::Queue::writeTexture):
* WebGPU/Texture.h:
* WebGPU/Texture.mm:
(WebGPU::Texture::resolveTextureViewDescriptorDefaults const):
(WebGPU::Texture::validateCreateView const):
(WebGPU::Texture::createView):
(WebGPU::Texture::validateTextureCopyRange):
(WebGPU::Texture::validateLinearTextureData):

Modified Paths

Diff

Modified: trunk/Source/WTF/wtf/CheckedArithmetic.h (292756 => 292757)


--- trunk/Source/WTF/wtf/CheckedArithmetic.h	2022-04-12 01:58:28 UTC (rev 292756)
+++ trunk/Source/WTF/wtf/CheckedArithmetic.h	2022-04-12 03:00:18 UTC (rev 292757)
@@ -1000,6 +1000,12 @@
     return Checked<T, RecordOverflow>(value) + checkedSum<T>(args...);
 }
 
+template<typename T, typename U, typename V>
+Checked<T, RecordOverflow> checkedDifference(U left, V right)
+{
+    return Checked<T, RecordOverflow>(left) - Checked<T, RecordOverflow>(right);
+}
+
 // Sometimes, you just want to check if some math would overflow - the code to do the math is
 // already in place, and you want to guard it.
 
@@ -1010,7 +1016,7 @@
 
 template<typename T, typename U> bool differenceOverflows(U left, U right)
 {
-    return (Checked<T, RecordOverflow>(left) - Checked<T, RecordOverflow>(right)).hasOverflowed();
+    return checkedDifference<T>(left, right).hasOverflowed();
 }
 
 template<typename T, typename U>
@@ -1056,6 +1062,8 @@
 using WTF::CrashOnOverflow;
 using WTF::RecordOverflow;
 using WTF::checkedSum;
+using WTF::checkedDifference;
+using WTF::checkedProduct;
 using WTF::differenceOverflows;
 using WTF::isInBounds;
 using WTF::productOverflows;

Modified: trunk/Source/WebGPU/ChangeLog (292756 => 292757)


--- trunk/Source/WebGPU/ChangeLog	2022-04-12 01:58:28 UTC (rev 292756)
+++ trunk/Source/WebGPU/ChangeLog	2022-04-12 03:00:18 UTC (rev 292757)
@@ -1,5 +1,46 @@
 2022-04-11  Myles C. Maxfield  <mmaxfi...@apple.com>
 
+        [WebGPU] Use checked arithmetic
+        https://bugs.webkit.org/show_bug.cgi?id=239058
+
+        Reviewed by Kimmo Kinnunen.
+
+        We have a bunch of places where overflow can occur.
+
+        Luckily, we can just detect overflow inside the validation functions, and not have
+        to do any inside the code that creates platform types (NSUInteger, etc.). This is
+        because if the validation code succeeds, then we are guaranteed that the cast to
+        NSUIntegers will succeed. This is because ranges in a resource are checked against
+        the size of the resource, and the size of the resource has been checked against
+        platform maximums, which are guaranteed to be smaller than the largest NSUInteger.
+
+        * WebGPU/BindGroup.mm:
+        (WebGPU::Device::createBindGroup):
+        * WebGPU/Buffer.mm:
+        (WebGPU::Buffer::validateGetMappedRange const):
+        (WebGPU::Buffer::getMappedRange):
+        (WebGPU::Buffer::validateMapAsync const):
+        (WebGPU::Buffer::mapAsync):
+        * WebGPU/CommandEncoder.mm:
+        (WebGPU::CommandEncoder::validateCopyBufferToBuffer):
+        (WebGPU::CommandEncoder::copyBufferToTexture):
+        (WebGPU::CommandEncoder::copyTextureToBuffer):
+        (WebGPU::CommandEncoder::copyTextureToTexture):
+        (WebGPU::CommandEncoder::validateClearBuffer):
+        (WebGPU::CommandEncoder::clearBuffer):
+        * WebGPU/Queue.mm:
+        (WebGPU::Queue::validateWriteBuffer const):
+        (WebGPU::Queue::writeTexture):
+        * WebGPU/Texture.h:
+        * WebGPU/Texture.mm:
+        (WebGPU::Texture::resolveTextureViewDescriptorDefaults const):
+        (WebGPU::Texture::validateCreateView const):
+        (WebGPU::Texture::createView):
+        (WebGPU::Texture::validateTextureCopyRange):
+        (WebGPU::Texture::validateLinearTextureData):
+
+2022-04-11  Myles C. Maxfield  <mmaxfi...@apple.com>
+
         [WebGPU] WebGPU strings are UTF-8, not Latin-1
         https://bugs.webkit.org/show_bug.cgi?id=239057
 

Modified: trunk/Source/WebGPU/WebGPU/BindGroup.mm (292756 => 292757)


--- trunk/Source/WebGPU/WebGPU/BindGroup.mm	2022-04-12 01:58:28 UTC (rev 292756)
+++ trunk/Source/WebGPU/WebGPU/BindGroup.mm	2022-04-12 03:00:18 UTC (rev 292757)
@@ -55,6 +55,8 @@
     if (descriptor.nextInChain)
         return BindGroup::createInvalid(*this);
 
+    // FIXME: Validate this according to the spec.
+
     const BindGroupLayout& bindGroupLayout = WebGPU::fromAPI(descriptor.layout);
 
     // FIXME(PERFORMANCE): Don't allocate 3 new buffers for every bind group.
@@ -91,7 +93,6 @@
 
         if (bufferIsPresent) {
             id<MTLBuffer> buffer = WebGPU::fromAPI(entry.buffer).buffer();
-            // FIXME: Use checked casts.
             [vertexArgumentEncoder setBuffer:buffer offset:static_cast<NSUInteger>(entry.offset) atIndex:entry.binding];
             [fragmentArgumentEncoder setBuffer:buffer offset:static_cast<NSUInteger>(entry.offset) atIndex:entry.binding];
             [computeArgumentEncoder setBuffer:buffer offset:static_cast<NSUInteger>(entry.offset) atIndex:entry.binding];

Modified: trunk/Source/WebGPU/WebGPU/Buffer.mm (292756 => 292757)


--- trunk/Source/WebGPU/WebGPU/Buffer.mm	2022-04-12 01:58:28 UTC (rev 292756)
+++ trunk/Source/WebGPU/WebGPU/Buffer.mm	2022-04-12 03:00:18 UTC (rev 292757)
@@ -28,6 +28,7 @@
 
 #import "APIConversions.h"
 #import "Device.h"
+#import <wtf/CheckedArithmetic.h>
 #import <wtf/StdLibExtras.h>
 
 namespace WebGPU {
@@ -176,9 +177,8 @@
     if (offset < m_mappingRange.beginOffset)
         return false;
 
-    // FIXME: Used checked arithmetic.
-    auto endOffset = offset + rangeSize;
-    if (endOffset > m_mappingRange.endOffset)
+    auto endOffset = checkedSum<size_t>(offset, rangeSize);
+    if (endOffset.hasOverflowed() || endOffset.value() > m_mappingRange.endOffset)
         return false;
 
     if (m_mappedRanges.overlaps({ offset, endOffset }))
@@ -186,15 +186,22 @@
 
     return true;
 }
+
+static uint64_t computeRangeSize(uint64_t size, size_t offset)
+{
+    auto result = checkedDifference<uint64_t>(size, offset);
+    if (result.hasOverflowed())
+        return 0;
+    return result.value();
+}
   
 void* Buffer::getMappedRange(size_t offset, size_t size)
 {
     // https://gpuweb.github.io/gpuweb/#dom-gpubuffer-getmappedrange
 
-    // FIXME: Use checked arithmetic.
     auto rangeSize = size;
     if (size == WGPU_WHOLE_MAP_SIZE)
-        rangeSize = static_cast<size_t>(std::max(static_cast<uint64_t>(0), m_size - static_cast<uint64_t>(offset)));
+        rangeSize = computeRangeSize(m_size, offset);
 
     if (!validateGetMappedRange(offset, rangeSize)) {
         // FIXME: "throw an OperationError and stop."
@@ -220,8 +227,8 @@
     if (rangeSize % 4)
         return false;
 
-    // FIXME: Use checked arithmetic.
-    if (static_cast<uint64_t>(offset + rangeSize) > m_size)
+    auto end = checkedSum<uint64_t>(offset, rangeSize);
+    if (end.hasOverflowed() || end.value() > m_size)
         return false;
 
     if (m_state != State::Unmapped)
@@ -244,10 +251,9 @@
 {
     // https://gpuweb.github.io/gpuweb/#dom-gpubuffer-mapasync
 
-    // FIXME: Use checked arithmetic.
     auto rangeSize = size;
     if (size == WGPU_WHOLE_MAP_SIZE)
-        rangeSize = static_cast<size_t>(std::max(static_cast<uint64_t>(0), static_cast<uint64_t>(m_size - offset)));
+        rangeSize = computeRangeSize(m_size, offset);
 
     if (!validateMapAsync(mode, offset, rangeSize)) {
         m_device->generateAValidationError("Validation failure."_s);

Modified: trunk/Source/WebGPU/WebGPU/CommandEncoder.mm (292756 => 292757)


--- trunk/Source/WebGPU/WebGPU/CommandEncoder.mm	2022-04-12 01:58:28 UTC (rev 292756)
+++ trunk/Source/WebGPU/WebGPU/CommandEncoder.mm	2022-04-12 03:00:18 UTC (rev 292757)
@@ -35,6 +35,7 @@
 #import "QuerySet.h"
 #import "RenderPassEncoder.h"
 #import "Texture.h"
+#import <wtf/CheckedArithmetic.h>
 
 namespace WebGPU {
 
@@ -121,21 +122,20 @@
     if (destinationOffset % 4)
         return false;
 
-    // FIXME: "(sourceOffset + size) does not overflow a GPUSize64."
+    auto sourceEnd = checkedSum<uint64_t>(sourceOffset, size);
+    if (sourceEnd.hasOverflowed())
+        return false;
 
-    // FIXME: "(destinationOffset + size) does not overflow a GPUSize64."
+    auto destinationEnd = checkedSum<uint64_t>(destinationOffset, size);
+    if (destinationEnd.hasOverflowed())
+        return false;
 
-    // FIXME: "source.[[size]] is greater than or equal to (sourceOffset + size)."
-    // FIXME: Use checked arithmetic
-    if (source.size() < sourceOffset + size)
+    if (source.size() < sourceEnd.value())
         return false;
 
-    // FIXME: "destination.[[size]] is greater than or equal to (destinationOffset + size)."
-    // FIXME: Use checked arithmetic
-    if (destination.size() < destinationOffset + size)
+    if (destination.size() < destinationEnd.value())
         return false;
 
-    // FIXME: "source and destination are not the same GPUBuffer."
     if (&source == &destination)
         return false;
 
@@ -257,7 +257,6 @@
 
     NSUInteger sourceBytesPerRow = source.layout.bytesPerRow;
 
-    // FIXME: Use checked arithmetic
     NSUInteger sourceBytesPerImage = source.layout.rowsPerImage * source.layout.bytesPerRow;
 
     MTLBlitOption options = MTLBlitOptionNone;
@@ -289,7 +288,6 @@
         auto sourceSize = MTLSizeMake(widthForMetal, 1, 1);
         auto destinationOrigin = MTLOriginMake(destination.origin.x, 1, 1);
         for (uint32_t layer = 0; layer < copySize.depthOrArrayLayers; ++layer) {
-            // FIXME: Use checked arithmetic.
             auto sourceOffset = static_cast<NSUInteger>(source.layout.offset + layer * sourceBytesPerImage);
             NSUInteger destinationSlice = destination.origin.z + layer;
             [m_blitCommandEncoder
@@ -312,7 +310,6 @@
         auto sourceSize = MTLSizeMake(widthForMetal, heightForMetal, 1);
         auto destinationOrigin = MTLOriginMake(destination.origin.x, destination.origin.y, 1);
         for (uint32_t layer = 0; layer < copySize.depthOrArrayLayers; ++layer) {
-            // FIXME: Use checked arithmetic.
             auto sourceOffset = static_cast<NSUInteger>(source.layout.offset + layer * sourceBytesPerImage);
             NSUInteger destinationSlice = destination.origin.z + layer;
             [m_blitCommandEncoder
@@ -422,7 +419,6 @@
 
     NSUInteger destinationBytesPerRow = destination.layout.bytesPerRow;
 
-    // FIXME: Use checked arithmetic
     NSUInteger destinationBytesPerImage = destination.layout.rowsPerImage * destination.layout.bytesPerRow;
 
     MTLBlitOption options = MTLBlitOptionNone;
@@ -454,7 +450,6 @@
         auto sourceSize = MTLSizeMake(widthForMetal, 1, 1);
         auto sourceOrigin = MTLOriginMake(source.origin.x, 1, 1);
         for (uint32_t layer = 0; layer < copySize.depthOrArrayLayers; ++layer) {
-            // FIXME: Use checked arithmetic.
             auto destinationOffset = static_cast<NSUInteger>(destination.layout.offset + layer * destinationBytesPerImage);
             NSUInteger sourceSlice = source.origin.z + layer;
             [m_blitCommandEncoder
@@ -477,7 +472,6 @@
         auto sourceSize = MTLSizeMake(widthForMetal, heightForMetal, 1);
         auto sourceOrigin = MTLOriginMake(source.origin.x, source.origin.y, 1);
         for (uint32_t layer = 0; layer < copySize.depthOrArrayLayers; ++layer) {
-            // FIXME: Use checked arithmetic.
             auto destinationOffset = static_cast<NSUInteger>(destination.layout.offset + layer * destinationBytesPerImage);
             NSUInteger sourceSlice = source.origin.z + layer;
             [m_blitCommandEncoder
@@ -617,7 +611,6 @@
         auto sourceOrigin = MTLOriginMake(source.origin.x, 1, 1);
         auto destinationOrigin = MTLOriginMake(destination.origin.x, 1, 1);
         for (uint32_t layer = 0; layer < copySize.depthOrArrayLayers; ++layer) {
-            // FIXME: Use checked arithmetic.
             NSUInteger sourceSlice = source.origin.z + layer;
             NSUInteger destinationSlice = destination.origin.z + layer;
             [m_blitCommandEncoder
@@ -640,7 +633,6 @@
         auto sourceOrigin = MTLOriginMake(source.origin.x, source.origin.y, 1);
         auto destinationOrigin = MTLOriginMake(destination.origin.x, destination.origin.y, 1);
         for (uint32_t layer = 0; layer < copySize.depthOrArrayLayers; ++layer) {
-            // FIXME: Use checked arithmetic.
             NSUInteger sourceSlice = source.origin.z + layer;
             NSUInteger destinationSlice = destination.origin.z + layer;
             [m_blitCommandEncoder
@@ -692,8 +684,8 @@
     if (offset % 4)
         return false;
 
-    // FIXME: Use checked arithmetic.
-    if (buffer.size() < offset + size)
+    auto end = checkedSum<uint64_t>(offset, size);
+    if (end.hasOverflowed() || buffer.size() < end.value())
         return false;
 
     return true;
@@ -707,8 +699,12 @@
         return;
 
     if (size == WGPU_WHOLE_SIZE) {
-        // FIXME: Use checked arithmetic.
-        size = buffer.size() - offset;
+        auto localSize = checkedDifference<uint64_t>(buffer.size(), offset);
+        if (localSize.hasOverflowed()) {
+            m_device->generateAValidationError("CommandEncoder::clearBuffer(): offset > buffer.size"_s);
+            return;
+        }
+        size = localSize.value();
     }
 
     if (!validateClearBuffer(buffer, offset, size)) {

Modified: trunk/Source/WebGPU/WebGPU/Queue.mm (292756 => 292757)


--- trunk/Source/WebGPU/WebGPU/Queue.mm	2022-04-12 01:58:28 UTC (rev 292756)
+++ trunk/Source/WebGPU/WebGPU/Queue.mm	2022-04-12 03:00:18 UTC (rev 292757)
@@ -32,6 +32,7 @@
 #import "Device.h"
 #import "IsValidToUseWith.h"
 #import "Texture.h"
+#import <wtf/CheckedArithmetic.h>
 
 namespace WebGPU {
 
@@ -171,8 +172,8 @@
     if (bufferOffset % 4)
         return false;
 
-    // FIXME: Use checked arithmetic
-    if (bufferOffset + size > buffer.size())
+    auto end = checkedSum<uint64_t>(bufferOffset, size);
+    if (end.hasOverflowed() || end.value() > buffer.size())
         return false;
 
     return true;
@@ -283,7 +284,6 @@
 
     NSUInteger bytesPerRow = dataLayout.bytesPerRow;
 
-    // FIXME: Use checked arithmetic.
     NSUInteger bytesPerImage = dataLayout.bytesPerRow * dataLayout.rowsPerImage;
 
     MTLBlitOption options = MTLBlitOptionNone;
@@ -315,7 +315,6 @@
                 case WGPUTextureDimension_1D: {
                     auto region = MTLRegionMake1D(destination.origin.x, size.width);
                     for (uint32_t layer = 0; layer < size.depthOrArrayLayers; ++layer) {
-                        // FIXME: Use checked arithmetic.
                         auto sourceOffset = static_cast<NSUInteger>(dataLayout.offset + layer * bytesPerImage);
                         NSUInteger destinationSlice = destination.origin.z + layer;
                         [fromAPI(destination.texture).texture()
@@ -331,7 +330,6 @@
                 case WGPUTextureDimension_2D: {
                     auto region = MTLRegionMake2D(destination.origin.x, destination.origin.y, size.width, size.height);
                     for (uint32_t layer = 0; layer < size.depthOrArrayLayers; ++layer) {
-                        // FIXME: Use checked arithmetic.
                         auto sourceOffset = static_cast<NSUInteger>(dataLayout.offset + layer * bytesPerImage);
                         NSUInteger destinationSlice = destination.origin.z + layer;
                         [fromAPI(destination.texture).texture()
@@ -390,7 +388,6 @@
         auto sourceSize = MTLSizeMake(widthForMetal, 1, 1);
         auto destinationOrigin = MTLOriginMake(destination.origin.x, 1, 1);
         for (uint32_t layer = 0; layer < size.depthOrArrayLayers; ++layer) {
-            // FIXME: Use checked arithmetic.
             NSUInteger sourceOffset = layer * bytesPerImage;
             NSUInteger destinationSlice = destination.origin.z + layer;
             [m_blitCommandEncoder
@@ -413,7 +410,6 @@
         auto sourceSize = MTLSizeMake(widthForMetal, heightForMetal, 1);
         auto destinationOrigin = MTLOriginMake(destination.origin.x, destination.origin.y, 1);
         for (uint32_t layer = 0; layer < size.depthOrArrayLayers; ++layer) {
-            // FIXME: Use checked arithmetic.
             NSUInteger sourceOffset = layer * bytesPerImage;
             NSUInteger destinationSlice = destination.origin.z + layer;
             [m_blitCommandEncoder

Modified: trunk/Source/WebGPU/WebGPU/Texture.h (292756 => 292757)


--- trunk/Source/WebGPU/WebGPU/Texture.h	2022-04-12 01:58:28 UTC (rev 292756)
+++ trunk/Source/WebGPU/WebGPU/Texture.h	2022-04-12 03:00:18 UTC (rev 292757)
@@ -88,7 +88,7 @@
     Texture(id<MTLTexture>, const WGPUTextureDescriptor&, Vector<WGPUTextureFormat>&& viewFormats, Device&);
     Texture(Device&);
 
-    WGPUTextureViewDescriptor resolveTextureViewDescriptorDefaults(const WGPUTextureViewDescriptor&) const;
+    std::optional<WGPUTextureViewDescriptor> resolveTextureViewDescriptorDefaults(const WGPUTextureViewDescriptor&) const;
     uint32_t arrayLayerCount() const;
     bool validateCreateView(const WGPUTextureViewDescriptor&) const;
 

Modified: trunk/Source/WebGPU/WebGPU/Texture.mm (292756 => 292757)


--- trunk/Source/WebGPU/WebGPU/Texture.mm	2022-04-12 01:58:28 UTC (rev 292756)
+++ trunk/Source/WebGPU/WebGPU/Texture.mm	2022-04-12 03:00:18 UTC (rev 292757)
@@ -29,6 +29,7 @@
 #import "APIConversions.h"
 #import "Device.h"
 #import "TextureView.h"
+#import <wtf/CheckedArithmetic.h>
 #import <wtf/MathExtras.h>
 
 namespace WebGPU {
@@ -2068,7 +2069,7 @@
 
 Texture::~Texture() = default;
 
-WGPUTextureViewDescriptor Texture::resolveTextureViewDescriptorDefaults(const WGPUTextureViewDescriptor& descriptor) const
+std::optional<WGPUTextureViewDescriptor> Texture::resolveTextureViewDescriptorDefaults(const WGPUTextureViewDescriptor& descriptor) const
 {
     // https://gpuweb.github.io/gpuweb/#abstract-opdef-resolving-gputextureviewdescriptor-defaults
 
@@ -2078,8 +2079,10 @@
         resolved.format = m_descriptor.format;
 
     if (resolved.mipLevelCount == WGPU_MIP_LEVEL_COUNT_UNDEFINED) {
-        // FIXME: Use checked arithmetic.
-        resolved.mipLevelCount = m_descriptor.mipLevelCount - resolved.baseMipLevel;
+        auto mipLevelCount = checkedDifference<uint32_t>(m_descriptor.mipLevelCount, resolved.baseMipLevel);
+        if (mipLevelCount.hasOverflowed())
+            return std::nullopt;
+        resolved.mipLevelCount = mipLevelCount.value();
     }
 
     if (resolved.dimension == WGPUTextureViewDimension_Undefined) {
@@ -2112,10 +2115,13 @@
             resolved.arrayLayerCount = 6;
             break;
         case WGPUTextureViewDimension_2DArray:
-        case WGPUTextureViewDimension_CubeArray:
-            // FIXME: Use checked arithmetic
-            resolved.arrayLayerCount = m_descriptor.size.depthOrArrayLayers - resolved.baseArrayLayer;
+        case WGPUTextureViewDimension_CubeArray: {
+            auto arrayLayerCount = checkedDifference<uint32_t>(m_descriptor.size.depthOrArrayLayers, resolved.baseArrayLayer);
+            if (arrayLayerCount.hasOverflowed())
+                return std::nullopt;
+            resolved.arrayLayerCount = arrayLayerCount.value();
             break;
+        }
         case WGPUTextureViewDimension_Force32:
             ASSERT_NOT_REACHED();
             return resolved;
@@ -2166,18 +2172,17 @@
     if (!descriptor.mipLevelCount)
         return false;
 
-    // FIXME: Use checked arithmetic.
-    if (descriptor.baseMipLevel + descriptor.mipLevelCount > m_descriptor.mipLevelCount)
+    auto endMipLevel = checkedSum<uint32_t>(descriptor.baseMipLevel, descriptor.mipLevelCount);
+    if (endMipLevel.hasOverflowed() || endMipLevel.value() > m_descriptor.mipLevelCount)
         return false;
 
     if (!descriptor.arrayLayerCount)
         return false;
 
-    // FIXME: Use checked arithmetic.
-    if (descriptor.baseArrayLayer + descriptor.arrayLayerCount > arrayLayerCount())
+    auto endArrayLayer = checkedSum<uint32_t>(descriptor.baseArrayLayer, descriptor.arrayLayerCount);
+    if (endArrayLayer.hasOverflowed() || endArrayLayer.value() > arrayLayerCount())
         return false;
 
-    // "descriptor.format must be equal to either this.[[descriptor]].format or one of the formats in this.[[descriptor]].viewFormats."
     if (descriptor.format != m_descriptor.format && !m_viewFormats.contains(descriptor.format))
         return false;
 
@@ -2261,7 +2266,7 @@
 
     auto descriptor = resolveTextureViewDescriptorDefaults(inputDescriptor);
 
-    if (!validateCreateView(descriptor)) {
+    if (!descriptor || !validateCreateView(*descriptor)) {
         m_device->generateAValidationError("Validation failure."_s);
 
         // FIXME: "Return a new invalid GPUTextureView."
@@ -2269,16 +2274,16 @@
     }
 
     std::optional<MTLPixelFormat> pixelFormat;
-    if (isDepthOrStencilFormat(descriptor.format)) {
-        switch (descriptor.aspect) {
+    if (isDepthOrStencilFormat(descriptor->format)) {
+        switch (descriptor->aspect) {
         case WGPUTextureAspect_All:
-            pixelFormat = WebGPU::pixelFormat(descriptor.format);
+            pixelFormat = WebGPU::pixelFormat(descriptor->format);
             break;
         case WGPUTextureAspect_StencilOnly:
-            pixelFormat = stencilOnlyAspectMetalFormat(descriptor.format);
+            pixelFormat = stencilOnlyAspectMetalFormat(descriptor->format);
             break;
         case WGPUTextureAspect_DepthOnly:
-            pixelFormat = depthOnlyAspectMetalFormat(descriptor.format);
+            pixelFormat = depthOnlyAspectMetalFormat(descriptor->format);
             break;
         case WGPUTextureAspect_Force32:
             ASSERT_NOT_REACHED();
@@ -2290,12 +2295,12 @@
     ASSERT(*pixelFormat != MTLPixelFormatInvalid);
 
     MTLTextureType textureType;
-    switch (descriptor.dimension) {
+    switch (descriptor->dimension) {
     case WGPUTextureViewDimension_Undefined:
         ASSERT_NOT_REACHED();
         return TextureView::createInvalid(m_device);
     case WGPUTextureViewDimension_1D:
-        if (descriptor.arrayLayerCount == 1)
+        if (descriptor->arrayLayerCount == 1)
             textureType = MTLTextureType1D;
         else
             textureType = MTLTextureType1DArray;
@@ -2330,21 +2335,21 @@
         return TextureView::createInvalid(m_device);
     }
 
-    auto levels = NSMakeRange(descriptor.baseMipLevel, descriptor.mipLevelCount);
+    auto levels = NSMakeRange(descriptor->baseMipLevel, descriptor->mipLevelCount);
 
-    auto slices = NSMakeRange(descriptor.baseArrayLayer, descriptor.arrayLayerCount);
+    auto slices = NSMakeRange(descriptor->baseArrayLayer, descriptor->arrayLayerCount);
 
     id<MTLTexture> texture = [m_texture newTextureViewWithPixelFormat:*pixelFormat textureType:textureType levels:levels slices:slices];
     if (!texture)
         return TextureView::createInvalid(m_device);
 
-    texture.label = fromAPI(descriptor.label);
+    texture.label = fromAPI(descriptor->label);
 
     std::optional<WGPUExtent3D> renderExtent;
     if  (m_descriptor.usage & WGPUTextureUsage_RenderAttachment)
-        renderExtent = computeRenderExtent(m_descriptor.size, descriptor.baseMipLevel);
+        renderExtent = computeRenderExtent(m_descriptor.size, descriptor->baseMipLevel);
 
-    return TextureView::create(texture, descriptor, renderExtent, m_device);
+    return TextureView::create(texture, *descriptor, renderExtent, m_device);
 }
 
 void Texture::destroy()
@@ -2713,16 +2718,16 @@
 
     auto subresourceSize = imageCopyTextureSubresourceSize(imageCopyTexture);
 
-    // FIXME: Used checked arithmetic
-    if (imageCopyTexture.origin.x + copySize.width > subresourceSize.width)
+    auto endX = checkedSum<uint32_t>(imageCopyTexture.origin.x, copySize.width);
+    if (endX.hasOverflowed() || endX.value() > subresourceSize.width)
         return false;
 
-    // FIXME: Used checked arithmetic
-    if ((imageCopyTexture.origin.y + copySize.height) > subresourceSize.height)
+    auto endY = checkedSum<uint32_t>(imageCopyTexture.origin.y, copySize.height);
+    if (endY.hasOverflowed() || endY.value() > subresourceSize.height)
         return false;
 
-    // FIXME: Used checked arithmetic
-    if ((imageCopyTexture.origin.z + copySize.depthOrArrayLayers) > subresourceSize.depthOrArrayLayers)
+    auto endZ = checkedSum<uint32_t>(imageCopyTexture.origin.z, copySize.depthOrArrayLayers);
+    if (endZ.hasOverflowed() || endZ.value() > subresourceSize.depthOrArrayLayers)
         return false;
 
     if (copySize.width % blockWidth)
@@ -2746,8 +2751,9 @@
 
     auto heightInBlocks = copyExtent.height / blockHeight;
 
-    // FIXME: Use checked arithmetic.
-    auto bytesInLastRow = blockSize * widthInBlocks;
+    auto bytesInLastRow = checkedProduct<uint64_t>(blockSize, widthInBlocks);
+    if (bytesInLastRow.hasOverflowed())
+        return false;
 
     if (heightInBlocks > 1) {
         if (layout.bytesPerRow == WGPU_COPY_STRIDE_UNDEFINED)
@@ -2760,7 +2766,7 @@
     }
 
     if (layout.bytesPerRow != WGPU_COPY_STRIDE_UNDEFINED) {
-        if (layout.bytesPerRow < bytesInLastRow)
+        if (layout.bytesPerRow < bytesInLastRow.value())
             return false;
     }
 
@@ -2769,33 +2775,26 @@
             return false;
     }
 
-    uint64_t requiredBytesInCopy = 0;
+    auto requiredBytesInCopy = CheckedUint64(0);
 
     if (copyExtent.depthOrArrayLayers > 1) {
-        // FIXME: Use checked arithmetic.
-        auto bytesPerImage = layout.bytesPerRow * layout.rowsPerImage;
+        auto bytesPerImage = checkedProduct<uint64_t>(layout.bytesPerRow, layout.rowsPerImage);
 
-        // FIXME: Use checked arithmetic.
-        auto bytesBeforeLastImage = bytesPerImage * (copyExtent.depthOrArrayLayers - 1);
+        auto bytesBeforeLastImage = checkedProduct<uint64_t>(bytesPerImage, checkedDifference<uint64_t>(copyExtent.depthOrArrayLayers, 1));
 
-        // FIXME: Use checked arithmetic.
         requiredBytesInCopy += bytesBeforeLastImage;
     }
 
     if (copyExtent.depthOrArrayLayers > 0) {
-        if (heightInBlocks > 1) {
-            // FIXME: Use checked arithmetic.
-            requiredBytesInCopy += layout.bytesPerRow * (heightInBlocks - 1);
-        }
+        if (heightInBlocks > 1)
+            requiredBytesInCopy += checkedProduct<uint64_t>(layout.bytesPerRow, checkedDifference<uint64_t>(heightInBlocks, 1));
 
-        if (heightInBlocks > 0) {
-            // FIXME: Use checked arithmetic.
+        if (heightInBlocks > 0)
             requiredBytesInCopy += bytesInLastRow;
-        }
     }
 
-    // FIXME: Use checked arithmetic.
-    if (layout.offset + requiredBytesInCopy > byteSize)
+    auto end = checkedSum<uint64_t>(layout.offset, requiredBytesInCopy);
+    if (end.hasOverflowed() || end.value() > byteSize)
         return false;
 
     return true;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to