Commit 8b7d8144 by Corentin Wallez Committed by Commit Bot

Clamp "count" in glUniform* before passing to the backend

The OpenGL spec allows "count" to overflow safely implemented but some drivers like the Intel Windows OpenGL driver don't handle this correctly and crash on overflow tests. BUG=661413 Change-Id: I10de9292c75daa375f002850900bb5e1cbfce3b6 Reviewed-on: https://chromium-review.googlesource.com/411387Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
parent 15ac534a
...@@ -1336,128 +1336,128 @@ GLuint Program::getUniformIndex(const std::string &name) const ...@@ -1336,128 +1336,128 @@ GLuint Program::getUniformIndex(const std::string &name) const
void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
{ {
setUniformInternal(location, count * 1, v); GLsizei clampedCount = setUniformInternal(location, count, 1, v);
mProgram->setUniform1fv(location, count, v); mProgram->setUniform1fv(location, clampedCount, v);
} }
void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
{ {
setUniformInternal(location, count * 2, v); GLsizei clampedCount = setUniformInternal(location, count, 2, v);
mProgram->setUniform2fv(location, count, v); mProgram->setUniform2fv(location, clampedCount, v);
} }
void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
{ {
setUniformInternal(location, count * 3, v); GLsizei clampedCount = setUniformInternal(location, count, 3, v);
mProgram->setUniform3fv(location, count, v); mProgram->setUniform3fv(location, clampedCount, v);
} }
void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
{ {
setUniformInternal(location, count * 4, v); GLsizei clampedCount = setUniformInternal(location, count, 4, v);
mProgram->setUniform4fv(location, count, v); mProgram->setUniform4fv(location, clampedCount, v);
} }
void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v) void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
{ {
setUniformInternal(location, count * 1, v); GLsizei clampedCount = setUniformInternal(location, count, 1, v);
mProgram->setUniform1iv(location, count, v); mProgram->setUniform1iv(location, clampedCount, v);
} }
void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v) void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
{ {
setUniformInternal(location, count * 2, v); GLsizei clampedCount = setUniformInternal(location, count, 2, v);
mProgram->setUniform2iv(location, count, v); mProgram->setUniform2iv(location, clampedCount, v);
} }
void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v) void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
{ {
setUniformInternal(location, count * 3, v); GLsizei clampedCount = setUniformInternal(location, count, 3, v);
mProgram->setUniform3iv(location, count, v); mProgram->setUniform3iv(location, clampedCount, v);
} }
void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v) void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
{ {
setUniformInternal(location, count * 4, v); GLsizei clampedCount = setUniformInternal(location, count, 4, v);
mProgram->setUniform4iv(location, count, v); mProgram->setUniform4iv(location, clampedCount, v);
} }
void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
{ {
setUniformInternal(location, count * 1, v); GLsizei clampedCount = setUniformInternal(location, count, 1, v);
mProgram->setUniform1uiv(location, count, v); mProgram->setUniform1uiv(location, clampedCount, v);
} }
void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
{ {
setUniformInternal(location, count * 2, v); GLsizei clampedCount = setUniformInternal(location, count, 2, v);
mProgram->setUniform2uiv(location, count, v); mProgram->setUniform2uiv(location, clampedCount, v);
} }
void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
{ {
setUniformInternal(location, count * 3, v); GLsizei clampedCount = setUniformInternal(location, count, 3, v);
mProgram->setUniform3uiv(location, count, v); mProgram->setUniform3uiv(location, clampedCount, v);
} }
void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
{ {
setUniformInternal(location, count * 4, v); GLsizei clampedCount = setUniformInternal(location, count, 4, v);
mProgram->setUniform4uiv(location, count, v); mProgram->setUniform4uiv(location, clampedCount, v);
} }
void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<2, 2>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<2, 2>(location, count, transpose, v);
mProgram->setUniformMatrix2fv(location, count, transpose, v); mProgram->setUniformMatrix2fv(location, clampedCount, transpose, v);
} }
void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<3, 3>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<3, 3>(location, count, transpose, v);
mProgram->setUniformMatrix3fv(location, count, transpose, v); mProgram->setUniformMatrix3fv(location, clampedCount, transpose, v);
} }
void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<4, 4>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<4, 4>(location, count, transpose, v);
mProgram->setUniformMatrix4fv(location, count, transpose, v); mProgram->setUniformMatrix4fv(location, clampedCount, transpose, v);
} }
void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<2, 3>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<2, 3>(location, count, transpose, v);
mProgram->setUniformMatrix2x3fv(location, count, transpose, v); mProgram->setUniformMatrix2x3fv(location, clampedCount, transpose, v);
} }
void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<2, 4>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<2, 4>(location, count, transpose, v);
mProgram->setUniformMatrix2x4fv(location, count, transpose, v); mProgram->setUniformMatrix2x4fv(location, clampedCount, transpose, v);
} }
void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<3, 2>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<3, 2>(location, count, transpose, v);
mProgram->setUniformMatrix3x2fv(location, count, transpose, v); mProgram->setUniformMatrix3x2fv(location, clampedCount, transpose, v);
} }
void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<3, 4>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<3, 4>(location, count, transpose, v);
mProgram->setUniformMatrix3x4fv(location, count, transpose, v); mProgram->setUniformMatrix3x4fv(location, clampedCount, transpose, v);
} }
void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<4, 2>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<4, 2>(location, count, transpose, v);
mProgram->setUniformMatrix4x2fv(location, count, transpose, v); mProgram->setUniformMatrix4x2fv(location, clampedCount, transpose, v);
} }
void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{ {
setMatrixUniformInternal<4, 3>(location, count, transpose, v); GLsizei clampedCount = setMatrixUniformInternal<4, 3>(location, count, transpose, v);
mProgram->setUniformMatrix4x3fv(location, count, transpose, v); mProgram->setUniformMatrix4x3fv(location, clampedCount, transpose, v);
} }
void Program::getUniformfv(GLint location, GLfloat *v) const void Program::getUniformfv(GLint location, GLfloat *v) const
...@@ -2842,7 +2842,7 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu ...@@ -2842,7 +2842,7 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
} }
template <typename T> template <typename T>
void Program::setUniformInternal(GLint location, GLsizei count, const T *v) GLsizei Program::setUniformInternal(GLint location, GLsizei countIn, int vectorSize, const T *v)
{ {
const VariableLocation &locationInfo = mState.mUniformLocations[location]; const VariableLocation &locationInfo = mState.mUniformLocations[location];
LinkedUniform *linkedUniform = &mState.mUniforms[locationInfo.index]; LinkedUniform *linkedUniform = &mState.mUniforms[locationInfo.index];
...@@ -2851,8 +2851,16 @@ void Program::setUniformInternal(GLint location, GLsizei count, const T *v) ...@@ -2851,8 +2851,16 @@ void Program::setUniformInternal(GLint location, GLsizei count, const T *v)
// OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
// element index used, as reported by GetActiveUniform, will be ignored by the GL." // element index used, as reported by GetActiveUniform, will be ignored by the GL."
unsigned int remainingElements = linkedUniform->elementCount() - locationInfo.element; unsigned int remainingElements = linkedUniform->elementCount() - locationInfo.element;
GLsizei clampedCount = std::min( GLsizei maxElementCount =
count, static_cast<GLsizei>(remainingElements * linkedUniform->getElementComponents())); static_cast<GLsizei>(remainingElements * linkedUniform->getElementComponents());
GLsizei count = countIn;
GLsizei clampedCount = count * vectorSize;
if (clampedCount > maxElementCount)
{
clampedCount = maxElementCount;
count = maxElementCount / vectorSize;
}
if (VariableComponentType(linkedUniform->type) == GL_BOOL) if (VariableComponentType(linkedUniform->type) == GL_BOOL)
{ {
...@@ -2874,18 +2882,19 @@ void Program::setUniformInternal(GLint location, GLsizei count, const T *v) ...@@ -2874,18 +2882,19 @@ void Program::setUniformInternal(GLint location, GLsizei count, const T *v)
memcpy(destPointer, v, sizeof(T) * clampedCount); memcpy(destPointer, v, sizeof(T) * clampedCount);
} }
return count;
} }
template <size_t cols, size_t rows, typename T> template <size_t cols, size_t rows, typename T>
void Program::setMatrixUniformInternal(GLint location, GLsizei Program::setMatrixUniformInternal(GLint location,
GLsizei count, GLsizei count,
GLboolean transpose, GLboolean transpose,
const T *v) const T *v)
{ {
if (!transpose) if (!transpose)
{ {
setUniformInternal(location, count * cols * rows, v); return setUniformInternal(location, count, cols * rows, v);
return;
} }
// Perform a transposing copy. // Perform a transposing copy.
...@@ -2910,6 +2919,8 @@ void Program::setMatrixUniformInternal(GLint location, ...@@ -2910,6 +2919,8 @@ void Program::setMatrixUniformInternal(GLint location,
} }
} }
} }
return clampedCount;
} }
template <typename DestT> template <typename DestT>
......
...@@ -460,11 +460,15 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -460,11 +460,15 @@ class Program final : angle::NonCopyable, public LabeledObject
void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType); void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
// Both these function update the cached uniform values and return a modified "count"
// so that the uniform update doesn't overflow the uniform.
template <typename T> template <typename T>
void setUniformInternal(GLint location, GLsizei count, const T *v); GLsizei setUniformInternal(GLint location, GLsizei count, int vectorSize, const T *v);
template <size_t cols, size_t rows, typename T> template <size_t cols, size_t rows, typename T>
void setMatrixUniformInternal(GLint location, GLsizei count, GLboolean transpose, const T *v); GLsizei setMatrixUniformInternal(GLint location,
GLsizei count,
GLboolean transpose,
const T *v);
template <typename DestT> template <typename DestT>
void getUniformInternal(GLint location, DestT *dataOut) const; void getUniformInternal(GLint location, DestT *dataOut) const;
......
...@@ -462,13 +462,6 @@ TEST_P(UniformTestES3, TranposedMatrixArrayUniformStateQuery) ...@@ -462,13 +462,6 @@ TEST_P(UniformTestES3, TranposedMatrixArrayUniformStateQuery)
// Check that trying setting too many elements of an array doesn't overflow // Check that trying setting too many elements of an array doesn't overflow
TEST_P(UniformTestES3, OverflowArray) TEST_P(UniformTestES3, OverflowArray)
{ {
// TODO(cwallez): fix on the Wintel OpenGL driver
if (IsIntel() && IsOpenGL() && IsWindows())
{
std::cout << "Test skipped on Intel Windows OpenGL." << std::endl;
return;
}
const std::string &vertexShader = const std::string &vertexShader =
"#version 300 es\n" "#version 300 es\n"
"void main() { gl_Position = vec4(1); }"; "void main() { gl_Position = vec4(1); }";
......
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