Prevent 32-bit numeric overflow on image allocation.
We assume the pixels of an image can be addressed with a signed 32-bit
offset, including any padding. For a 3D image it's possible to exceed
this without exceeding the per-dimension limits. Lowering the per-
dimension limit so the allocation is always less than 2 GiB makes them
unreasonably small, so instead we must check the total size.
Use 1 GiB as the soft limit in OpenGL.
Bug chromium:835299
Change-Id: I9c5184002c1710e3923b549f8c21e7f6a516e1c7
Reviewed-on: https://swiftshader-review.googlesource.com/18869
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index 788ca63..83412a3 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -2648,14 +2648,23 @@
size_t Surface::size(int width, int height, int depth, int border, int samples, Format format)
{
+ samples = max(1, samples);
+
switch(format)
{
default:
- // FIXME: Unpacking byte4 to short4 in the sampler currently involves reading 8 bytes,
- // and stencil operations also read 8 bytes per four 8-bit stencil values,
- // so we have to allocate 4 extra bytes to avoid buffer overruns.
- return (size_t)sliceB(width, height, border, format, true) * depth * samples + 4;
+ {
+ uint64_t size = (uint64_t)sliceB(width, height, border, format, true) * depth * samples;
+ // FIXME: Unpacking byte4 to short4 in the sampler currently involves reading 8 bytes,
+ // and stencil operations also read 8 bytes per four 8-bit stencil values,
+ // so we have to allocate 4 extra bytes to avoid buffer overruns.
+ size += 4;
+
+ // We can only sample buffers smaller than 2 GiB.
+ // Force an out-of-memory if larger, or let the caller report an error.
+ return size < 0x80000000u ? (size_t)size : std::numeric_limits<size_t>::max();
+ }
case FORMAT_YV12_BT601:
case FORMAT_YV12_BT709:
case FORMAT_YV12_JFIF: