Commit 92db6947 by Corentin Wallez Committed by Commit Bot

Tighten the validation for staying in array buffer bounds

BUG=angleproject:1523 Change-Id: I685a9b884e5de73b94900c5b6016ce914b9bfe7f Reviewed-on: https://chromium-review.googlesource.com/418458 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent f52fe93d
...@@ -34,7 +34,10 @@ const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum ele ...@@ -34,7 +34,10 @@ const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum ele
namespace namespace
{ {
bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex) bool ValidateDrawAttribs(ValidationContext *context,
GLint primcount,
GLint maxVertex,
GLint vertexCount)
{ {
const gl::State &state = context->getGLState(); const gl::State &state = context->getGLState();
const gl::Program *program = state.getProgram(); const gl::Program *program = state.getProgram();
...@@ -51,32 +54,40 @@ bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxV ...@@ -51,32 +54,40 @@ bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxV
if (buffer) if (buffer)
{ {
GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib)); CheckedNumeric<GLint64> maxVertexElement = 0;
GLint64 maxVertexElement = 0; bool readsData = false;
if (attrib.divisor == 0)
if (attrib.divisor > 0)
{ {
maxVertexElement = readsData = vertexCount > 0;
static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor); maxVertexElement = static_cast<GLint64>(maxVertex);
} }
else else if (primcount > 0)
{ {
maxVertexElement = static_cast<GLint64>(maxVertex); readsData = true;
maxVertexElement =
static_cast<GLint64>(primcount - 1) / static_cast<GLint64>(attrib.divisor);
} }
// If we're drawing zero vertices, we have enough data. // If we're drawing zero vertices, we have enough data.
if (maxVertexElement > 0) if (readsData)
{ {
// Note: Last vertex element does not take the full stride! // Note: Last vertex element does not take the full stride!
GLint64 attribSize = CheckedNumeric<GLint64> attribStride = ComputeVertexAttributeStride(attrib);
static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib)); CheckedNumeric<GLint64> attribSize = ComputeVertexAttributeTypeSize(attrib);
GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize; CheckedNumeric<GLint64> attribDataSize =
GLint64 attribOffset = static_cast<GLint64>(attrib.offset); maxVertexElement * attribStride + attribSize;
CheckedNumeric<GLint64> maxOffset = attribDataSize + attrib.offset;
if (!maxOffset.IsValid())
{
context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
return false;
}
// [OpenGL ES 3.0.2] section 2.9.4 page 40: // [OpenGL ES 3.0.2] section 2.9.4 page 40:
// We can return INVALID_OPERATION if our vertex attribute does not have // We can return INVALID_OPERATION if our vertex attribute does not have
// enough backing data. // enough backing data.
if (attribDataSize + attribOffset > buffer->getSize()) if (maxOffset.ValueOrDie() > buffer->getSize())
{ {
context->handleError( context->handleError(
Error(GL_INVALID_OPERATION, Error(GL_INVALID_OPERATION,
...@@ -3172,7 +3183,17 @@ bool ValidateDrawArrays(ValidationContext *context, ...@@ -3172,7 +3183,17 @@ bool ValidateDrawArrays(ValidationContext *context,
return false; return false;
} }
if (!ValidateDrawAttribs(context, primcount, count)) CheckedNumeric<GLint> maxVertex = first;
maxVertex += count;
maxVertex -= 1;
if (!maxVertex.IsValid())
{
context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
return false;
}
if (!ValidateDrawAttribs(context, primcount, maxVertex.ValueOrDie(), count))
{ {
return false; return false;
} }
...@@ -3355,7 +3376,8 @@ bool ValidateDrawElements(ValidationContext *context, ...@@ -3355,7 +3376,8 @@ bool ValidateDrawElements(ValidationContext *context,
return false; return false;
} }
if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount()))) if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
static_cast<GLint>(indexRangeOut->vertexCount())))
{ {
return false; return false;
} }
......
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