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;