Assert that casting memory sizes to 32-bit doesn't overflow
VkPhysicalDeviceMaintenance3Properties::maxMemoryAllocationSize is
currently 1 GiB. This ensures that the memory of all resources can be
addressed using 32-bit indices. We return VK_ERROR_OUT_OF_DEVICE_MEMORY
when this limit is exceeded, but it's still best to ensure we don't
inadvertently end up calculating sizes larger than 4 GiB that would
cause arithmetic overflow due to casting to 32-bit integers.
Bug: b/200806413
Change-Id: I10e828a93d6c24624f049a0809f0b962d473f44f
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/60068
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Sean Risser <srisser@google.com>
diff --git a/src/Device/Blitter.cpp b/src/Device/Blitter.cpp
index 0537db8..197b408 100644
--- a/src/Device/Blitter.cpp
+++ b/src/Device/Blitter.cpp
@@ -116,10 +116,10 @@
BlitData data = {
pixel, nullptr, // source, dest
- static_cast<uint32_t>(format.bytes()), // sPitchB
- static_cast<uint32_t>(dest->rowPitchBytes(aspect, subres.mipLevel)), // dPitchB
+ assert_cast<uint32_t>(format.bytes()), // sPitchB
+ assert_cast<uint32_t>(dest->rowPitchBytes(aspect, subres.mipLevel)), // dPitchB
0, // sSliceB (unused in clear operations)
- static_cast<uint32_t>(dest->slicePitchBytes(aspect, subres.mipLevel)), // dSliceB
+ assert_cast<uint32_t>(dest->slicePitchBytes(aspect, subres.mipLevel)), // dSliceB
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, // x0, y0, z0, w, h, d
@@ -1903,10 +1903,10 @@
BlitData data = {
nullptr, // source
nullptr, // dest
- static_cast<uint32_t>(src->rowPitchBytes(srcAspect, region.srcSubresource.mipLevel)), // sPitchB
- static_cast<uint32_t>(dst->rowPitchBytes(dstAspect, region.dstSubresource.mipLevel)), // dPitchB
- static_cast<uint32_t>(src->slicePitchBytes(srcAspect, region.srcSubresource.mipLevel)), // sSliceB
- static_cast<uint32_t>(dst->slicePitchBytes(dstAspect, region.dstSubresource.mipLevel)), // dSliceB
+ assert_cast<uint32_t>(src->rowPitchBytes(srcAspect, region.srcSubresource.mipLevel)), // sPitchB
+ assert_cast<uint32_t>(dst->rowPitchBytes(dstAspect, region.dstSubresource.mipLevel)), // dPitchB
+ assert_cast<uint32_t>(src->slicePitchBytes(srcAspect, region.srcSubresource.mipLevel)), // sSliceB
+ assert_cast<uint32_t>(dst->slicePitchBytes(dstAspect, region.dstSubresource.mipLevel)), // dSliceB
x0,
y0,
@@ -2354,8 +2354,8 @@
VkExtent3D extent = image->getMipLevelExtent(aspect, subresource.mipLevel);
CubeBorderData data = {
image->getTexelPointer({ 0, 0, 0 }, posX),
- static_cast<uint32_t>(image->rowPitchBytes(aspect, subresource.mipLevel)),
- static_cast<uint32_t>(image->getLayerSize(aspect)),
+ assert_cast<uint32_t>(image->rowPitchBytes(aspect, subresource.mipLevel)),
+ assert_cast<uint32_t>(image->getLayerSize(aspect)),
extent.width
};
cornerUpdateRoutine(&data);
diff --git a/src/System/Types.hpp b/src/System/Types.hpp
index f7d16ae..8266d7b 100644
--- a/src/System/Types.hpp
+++ b/src/System/Types.hpp
@@ -15,6 +15,7 @@
#ifndef sw_Types_hpp
#define sw_Types_hpp
+#include <cassert>
#include <limits>
#include <type_traits>
@@ -49,6 +50,16 @@
namespace sw {
+// assert_cast<> is like a static_cast<> which asserts that no information was lost.
+template<typename To, typename From>
+To assert_cast(From x)
+{
+ To y = static_cast<To>(x);
+ assert(static_cast<From>(y) == x);
+
+ return y;
+}
+
// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
constexpr inline uint32_t bit_ceil(uint32_t i)
{