Commit 035e0459 by Jamie Madill

Fix OOB access for dynamic attribs with offsets.

We were not properly adding the offset to compute the right bounds. Bug: chromium:943709 Change-Id: I93e714b46dd366d5833fffa858ea3ab0322ffa92 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1558955Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ff4224d6
...@@ -37,7 +37,23 @@ enum ...@@ -37,7 +37,23 @@ enum
CONSTANT_VERTEX_BUFFER_SIZE = 4096 CONSTANT_VERTEX_BUFFER_SIZE = 4096
}; };
// Warning: you should ensure binding really matches attrib.bindingIndex before using this function. // Warning: ensure the binding matches attrib.bindingIndex before using these functions.
int64_t GetMaxAttributeByteOffsetForDraw(const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
int64_t elementCount)
{
CheckedNumeric<int64_t> stride = ComputeVertexAttributeStride(attrib, binding);
CheckedNumeric<int64_t> offset = ComputeVertexAttributeOffset(attrib, binding);
CheckedNumeric<int64_t> size = ComputeVertexAttributeTypeSize(attrib);
ASSERT(elementCount > 0);
CheckedNumeric<int64_t> result =
stride * (CheckedNumeric<int64_t>(elementCount) - 1) + size + offset;
return result.ValueOrDefault(std::numeric_limits<int64_t>::max());
}
// Warning: ensure the binding matches attrib.bindingIndex before using these functions.
int ElementsInBuffer(const gl::VertexAttribute &attrib, int ElementsInBuffer(const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
unsigned int size) unsigned int size)
...@@ -489,10 +505,12 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex ...@@ -489,10 +505,12 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex
GLint firstVertexIndex = binding.getDivisor() > 0 ? 0 : start; GLint firstVertexIndex = binding.getDivisor() > 0 ? 0 : start;
int64_t maxVertexCount = int64_t maxVertexCount =
static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount); static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount);
int elementsInBuffer =
ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
ANGLE_CHECK(GetImplAs<ContextD3D>(context), maxVertexCount <= elementsInBuffer, int64_t maxByte = GetMaxAttributeByteOffsetForDraw(attrib, binding, maxVertexCount);
ASSERT(bufferD3D->getSize() <= static_cast<size_t>(std::numeric_limits<int64_t>::max()));
ANGLE_CHECK(GetImplAs<ContextD3D>(context),
maxByte <= static_cast<int64_t>(bufferD3D->getSize()),
"Vertex buffer is not big enough for the draw call.", GL_INVALID_OPERATION); "Vertex buffer is not big enough for the draw call.", GL_INVALID_OPERATION);
} }
return mStreamingBuffer.reserveVertexSpace(context, attrib, binding, totalCount, instances); return mStreamingBuffer.reserveVertexSpace(context, attrib, binding, totalCount, instances);
......
...@@ -1821,6 +1821,25 @@ TEST_P(RobustResourceInitTestES31, Multisample2DTextureArray) ...@@ -1821,6 +1821,25 @@ TEST_P(RobustResourceInitTestES31, Multisample2DTextureArray)
} }
} }
// Tests that using an out of bounds draw offset with a dynamic array succeeds.
TEST_P(RobustResourceInitTest, DynamicVertexArrayOffsetOutOfBounds)
{
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
glUseProgram(program);
GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
ASSERT_NE(-1, posLoc);
glEnableVertexAttribArray(posLoc);
GLBuffer buf;
glBindBuffer(GL_ARRAY_BUFFER, buf);
glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const void *>(500));
glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, 3);
// Either no error or invalid operation is okay.
}
ANGLE_INSTANTIATE_TEST(RobustResourceInitTest, ANGLE_INSTANTIATE_TEST(RobustResourceInitTest,
ES2_D3D9(), ES2_D3D9(),
ES2_D3D11(), ES2_D3D11(),
......
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