Guard against some arithmetic overflows

Fixes locations that explicitly have TODOs about
checking for overflow. Also fixup other locations found while
searching the code for arithmetic operations.

Fixes: dawn:830
Change-Id: I4ef6b97a9cde14439e573a1da8d569ab985efc53
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/55605
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/RenderEncoderBase.cpp b/src/dawn_native/RenderEncoderBase.cpp
index 2081a91..c586aaa 100644
--- a/src/dawn_native/RenderEncoderBase.cpp
+++ b/src/dawn_native/RenderEncoderBase.cpp
@@ -127,7 +127,7 @@
                 }
 
                 if (indirectOffset >= indirectBuffer->GetSize() ||
-                    indirectOffset + kDrawIndirectSize > indirectBuffer->GetSize()) {
+                    kDrawIndirectSize > indirectBuffer->GetSize() - indirectOffset) {
                     return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
                 }
             }
@@ -165,7 +165,7 @@
                 }
 
                 if ((indirectOffset >= indirectBuffer->GetSize() ||
-                     indirectOffset + kDrawIndexedIndirectSize > indirectBuffer->GetSize())) {
+                     kDrawIndexedIndirectSize > indirectBuffer->GetSize() - indirectOffset)) {
                     return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
                 }
             }
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index 14a14a9..293e0a8 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -592,8 +592,10 @@
 
         // Compressed Textures will have paddings if their width or height is not a multiple of
         // 4 at non-zero mipmap levels.
-        if (mFormat.isCompressed) {
-            // TODO(crbug.com/dawn/830): check if there are any overflows.
+        if (mFormat.isCompressed && level != 0) {
+            // If |level| is non-zero, then each dimension of |extent| is at most half of
+            // the max texture dimension. Computations here which add the block width/height
+            // to the extent cannot overflow.
             const TexelBlockInfo& blockInfo = mFormat.GetAspectInfo(wgpu::TextureAspect::All).block;
             extent.width = (extent.width + blockInfo.width - 1) / blockInfo.width * blockInfo.width;
             extent.height =
@@ -607,10 +609,12 @@
                                                      const Origin3D& origin,
                                                      const Extent3D& extent) const {
         const Extent3D virtualSizeAtLevel = GetMipLevelVirtualSize(level);
-        uint32_t clampedCopyExtentWidth = (origin.x + extent.width > virtualSizeAtLevel.width)
+        ASSERT(origin.x <= virtualSizeAtLevel.width);
+        ASSERT(origin.y <= virtualSizeAtLevel.height);
+        uint32_t clampedCopyExtentWidth = (extent.width > virtualSizeAtLevel.width - origin.x)
                                               ? (virtualSizeAtLevel.width - origin.x)
                                               : extent.width;
-        uint32_t clampedCopyExtentHeight = (origin.y + extent.height > virtualSizeAtLevel.height)
+        uint32_t clampedCopyExtentHeight = (extent.height > virtualSizeAtLevel.height - origin.y)
                                                ? (virtualSizeAtLevel.height - origin.y)
                                                : extent.height;
         return {clampedCopyExtentWidth, clampedCopyExtentHeight, extent.depthOrArrayLayers};
diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp
index 7024c7a..240df53 100644
--- a/src/dawn_native/null/DeviceNull.cpp
+++ b/src/dawn_native/null/DeviceNull.cpp
@@ -205,7 +205,7 @@
 
     MaybeError Device::IncrementMemoryUsage(uint64_t bytes) {
         static_assert(kMaxMemoryUsage <= std::numeric_limits<size_t>::max(), "");
-        if (bytes > kMaxMemoryUsage || mMemoryUsage + bytes > kMaxMemoryUsage) {
+        if (bytes > kMaxMemoryUsage || mMemoryUsage > kMaxMemoryUsage - bytes) {
             return DAWN_OUT_OF_MEMORY_ERROR("Out of memory.");
         }
         mMemoryUsage += bytes;
diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp
index b4e98fe..e97ffb6 100644
--- a/src/dawn_native/opengl/CommandBufferGL.cpp
+++ b/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -458,11 +458,13 @@
             Extent3D validTextureCopyExtent = copySize;
             const TextureBase* texture = textureCopy.texture.Get();
             Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(textureCopy.mipLevel);
-            if (textureCopy.origin.x + copySize.width > virtualSizeAtLevel.width) {
+            ASSERT(textureCopy.origin.x <= virtualSizeAtLevel.width);
+            ASSERT(textureCopy.origin.y <= virtualSizeAtLevel.height);
+            if (copySize.width > virtualSizeAtLevel.width - textureCopy.origin.x) {
                 ASSERT(texture->GetFormat().isCompressed);
                 validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
             }
-            if (textureCopy.origin.y + copySize.height > virtualSizeAtLevel.height) {
+            if (copySize.height > virtualSizeAtLevel.height - textureCopy.origin.y) {
                 ASSERT(texture->GetFormat().isCompressed);
                 validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
             }
diff --git a/src/dawn_native/vulkan/UtilsVulkan.cpp b/src/dawn_native/vulkan/UtilsVulkan.cpp
index 7375377..c6952d4 100644
--- a/src/dawn_native/vulkan/UtilsVulkan.cpp
+++ b/src/dawn_native/vulkan/UtilsVulkan.cpp
@@ -83,11 +83,13 @@
         Extent3D validTextureCopyExtent = copySize;
         const TextureBase* texture = textureCopy.texture.Get();
         Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(textureCopy.mipLevel);
-        if (textureCopy.origin.x + copySize.width > virtualSizeAtLevel.width) {
+        ASSERT(textureCopy.origin.x <= virtualSizeAtLevel.width);
+        ASSERT(textureCopy.origin.y <= virtualSizeAtLevel.height);
+        if (copySize.width > virtualSizeAtLevel.width - textureCopy.origin.x) {
             ASSERT(texture->GetFormat().isCompressed);
             validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
         }
-        if (textureCopy.origin.y + copySize.height > virtualSizeAtLevel.height) {
+        if (copySize.height > virtualSizeAtLevel.height - textureCopy.origin.y) {
             ASSERT(texture->GetFormat().isCompressed);
             validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
         }