Commit 6e3a387c by Nicolas Capens Committed by Nicolas Capens

Exclude padding bytes from image size limit

Surface::size() adds 4 padding bytes due to reading byte4 as 8 bytes for efficient unpacking to short4 (less efficient prior to SSE 4.1 pmovzxbw instruction). This padding is never addressed separately so the offset can't overflow a signed 32-bit integer if we keep the total size minus the padding below 2 GiB. On the OpenGL side we currently impose a further limit of 1 GiB, but this should also take the padding into account to allow for effective image data up to this limit (e.g. 8192 * 8192 of four samples of 32-bit elements). Note that our scanline limit is also 8192 so allowing more than 1 GiB would run into that limit instead. Bug: chromium:835299 Bug: b/145229887 Change-Id: I4280fca88584235c0da6282ca622ee15b31bc34b Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/39690 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent ab210f92
......@@ -635,9 +635,12 @@ namespace gl
namespace egl
{
// We assume the data can be indexed with a signed 32-bit offset, including any padding,
// so we must keep the image size reasonable. 1 GiB ought to be enough for anybody.
enum { IMPLEMENTATION_MAX_IMAGE_SIZE_BYTES = 0x40000000 };
// We assume the image data can be indexed with a signed 32-bit offset,
// so we must keep the size reasonable. 1 GiB ought to be enough for anybody.
// 4 extra bytes account for the padding added in Surface::size().
// They are not addressed separately, so can't cause overflow.
// TODO(b/145229887): Eliminate or don't hard-code the padding bytes.
enum : uint64_t { IMPLEMENTATION_MAX_IMAGE_SIZE_BYTES = 0x40000000u + 4 };
enum TransferType
{
......
......@@ -2670,14 +2670,18 @@ namespace sw
{
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,
// We can only sample buffers smaller than 2 GiB, due to signed 32-bit offset calculations.
// Force an out-of-memory if larger, or let the caller report an error.
if(size >= 0x80000000u)
{
return std::numeric_limits<size_t>::max();
}
// 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();
// TODO(b/145229887): Eliminate if possible, or don't hard-code.
return size + 4;
}
case FORMAT_YV12_BT601:
case FORMAT_YV12_BT709:
......
......@@ -1331,6 +1331,12 @@ TEST_F(SwiftShaderTest, OutOfMemory)
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA, GL_FLOAT, nullptr);
EXPECT_GLENUM_EQ(GL_OUT_OF_MEMORY, glGetError());
// b/145229887: Allocating an image of exactly 1 GiB should succeed.
const int width8k = 8192;
const int height8k = 8192;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width8k, height8k, 0, GL_RGBA, GL_FLOAT, nullptr);
EXPECT_NO_GL_ERROR();
// The spec states that the GL is in an undefined state when GL_OUT_OF_MEMORY
// is returned, and the context must be recreated before attempting more rendering.
Uninitialize();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment