Commit 0844f2db by Corentin Wallez Committed by Commit Bot

WebGLCompatibility: add tests for OOB in DrawElements' index buffer

Also add a small fix for a WebGL test where DrawElements with a count of 0 should skip OOB checks. BUG=angleproject:1523 BUG=chromium:668223 Change-Id: I67fbe939f6c8b925551b658b6178dbbae982df89 Reviewed-on: https://chromium-review.googlesource.com/435279Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
parent 1aa728e3
......@@ -3456,7 +3456,7 @@ bool ValidateDrawElements(ValidationContext *context,
// Check for mapped buffers
if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
{
context->handleError(Error(GL_INVALID_OPERATION));
context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
return false;
}
......@@ -3488,34 +3488,39 @@ bool ValidateDrawElements(ValidationContext *context,
}
}
if (elementArrayBuffer)
if (count > 0)
{
GLint64 offset = reinterpret_cast<GLint64>(indices);
GLint64 byteCount = static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
// check for integer overflows
if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
if (elementArrayBuffer)
{
context->handleError(Error(GL_OUT_OF_MEMORY));
return false;
}
GLint64 offset = reinterpret_cast<GLint64>(indices);
GLint64 byteCount =
static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
// Check for reading past the end of the bound buffer object
if (byteCount > elementArrayBuffer->getSize())
// check for integer overflows
if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
{
context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
return false;
}
// Check for reading past the end of the bound buffer object
if (byteCount > elementArrayBuffer->getSize())
{
context->handleError(
Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
return false;
}
}
else if (!indices)
{
context->handleError(Error(GL_INVALID_OPERATION));
// This is an application error that would normally result in a crash,
// but we catch it and return an error
context->handleError(
Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
return false;
}
}
else if (!indices && count > 0)
{
// This is an application error that would normally result in a crash,
// but we catch it and return an error
context->handleError(
Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
return false;
}
if (!ValidateDrawBase(context, mode, count))
{
......
......@@ -361,37 +361,56 @@ TEST_P(WebGLCompatibilityTest, DrawArraysBufferOutOfBoundsNonInstanced)
ASSERT_GL_NO_ERROR();
}
// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
TEST_P(WebGLCompatibilityTest, NPOT)
// Test the checks for OOB reads in the index buffer
TEST_P(WebGLCompatibilityTest, DrawElementsBufferOutOfBoundsInIndexBuffer)
{
EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
const std::string &vert =
"attribute float a_pos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
"}\n";
// Create a texture and set an NPOT mip 0, should always be acceptable.
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
const std::string &frag =
"precision highp float;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
ANGLE_GL_PROGRAM(program, vert, frag);
GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
ASSERT_NE(-1, posLocation);
glUseProgram(program.get());
GLBuffer vertexBuffer;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
glEnableVertexAttribArray(posLocation);
const uint8_t *zeroOffset = nullptr;
const uint8_t zeroIndices[] = {0, 0, 0, 0, 0, 0, 0, 0};
glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, zeroOffset);
GLBuffer indexBuffer;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(zeroIndices), zeroIndices, GL_STATIC_DRAW);
ASSERT_GL_NO_ERROR();
// Try setting an NPOT mip 1 and verify the error if WebGL 1
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
if (getClientMajorVersion() < 3)
{
ASSERT_GL_ERROR(GL_INVALID_VALUE);
}
else
{
ASSERT_GL_NO_ERROR();
}
// Test touching the last index is valid
glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 4);
ASSERT_GL_NO_ERROR();
if (extensionRequestable("GL_OES_texture_npot"))
{
glRequestExtensionANGLE("GL_OES_texture_npot");
ASSERT_GL_NO_ERROR();
// Test touching the last + 1 element is invalid
glDrawElements(GL_POINTS, 4, GL_UNSIGNED_BYTE, zeroOffset + 5);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
// Try again to set NPOT mip 1
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
ASSERT_GL_NO_ERROR();
}
// Test any offset if valid if count is zero
glDrawElements(GL_POINTS, 0, GL_UNSIGNED_BYTE, zeroOffset + 42);
ASSERT_GL_NO_ERROR();
}
// Test the checks for OOB reads in the vertex buffers, instanced version
......@@ -452,6 +471,39 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
ASSERT_GL_NO_ERROR();
}
// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
TEST_P(WebGLCompatibilityTest, NPOT)
{
EXPECT_FALSE(extensionEnabled("GL_OES_texture_npot"));
// Create a texture and set an NPOT mip 0, should always be acceptable.
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
ASSERT_GL_NO_ERROR();
// Try setting an NPOT mip 1 and verify the error if WebGL 1
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
if (getClientMajorVersion() < 3)
{
ASSERT_GL_ERROR(GL_INVALID_VALUE);
}
else
{
ASSERT_GL_NO_ERROR();
}
if (extensionRequestable("GL_OES_texture_npot"))
{
glRequestExtensionANGLE("GL_OES_texture_npot");
ASSERT_GL_NO_ERROR();
// Try again to set NPOT mip 1
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
ASSERT_GL_NO_ERROR();
}
}
// Tests that a rendering feedback loop triggers a GL error under WebGL.
// Based on WebGL test conformance/renderbuffers/feedback-loop.html.
TEST_P(WebGLCompatibilityTest, RenderingFeedbackLoop)
......
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