Commit fc32e8b7 by Geoff Lang Committed by Commit Bot

WebGL: Validate shader entry point names do not contain invalid characters.

Section 6.20 of the WebGL spec states that all shader-related entry points that accept strings must validate that the string does not contain characters that are not valid in ESSL. TEST=conformance/misc/invalid-passed-params BUG=2016 Change-Id: I220d9dd79c4b0e8e0195277093268b9e1e66f9d9 Reviewed-on: https://chromium-review.googlesource.com/519445 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 948bbe51
...@@ -781,6 +781,31 @@ bool ValidCap(const Context *context, GLenum cap, bool queryOnly) ...@@ -781,6 +781,31 @@ bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
} }
} }
// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
// 3.1.
bool IsValidESSLCharacter(unsigned char c)
{
// Printing characters are valid except " $ ` @ \ ' DEL.
if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
c != '\'')
{
return true;
}
// Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
if (c >= 9 && c <= 13)
{
return true;
}
return false;
}
bool IsValidESSLString(const char *str, size_t len)
{
return len == 0 || std::find_if_not(str, str + len, IsValidESSLCharacter) == str + len;
}
} // anonymous namespace } // anonymous namespace
bool ValidateES2TexImageParameters(Context *context, bool ValidateES2TexImageParameters(Context *context,
...@@ -2658,6 +2683,14 @@ bool ValidateBindUniformLocationCHROMIUM(Context *context, ...@@ -2658,6 +2683,14 @@ bool ValidateBindUniformLocationCHROMIUM(Context *context,
return false; return false;
} }
// The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
// shader-related entry points
if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
{
context->handleError(Error(GL_INVALID_VALUE, "Uniform name contains invalid characters"));
return false;
}
if (strncmp(name, "gl_", 3) == 0) if (strncmp(name, "gl_", 3) == 0)
{ {
context->handleError( context->handleError(
...@@ -4002,6 +4035,14 @@ bool ValidateBindAttribLocation(ValidationContext *context, ...@@ -4002,6 +4035,14 @@ bool ValidateBindAttribLocation(ValidationContext *context,
return false; return false;
} }
// The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
// shader-related entry points
if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
{
context->handleError(Error(GL_INVALID_VALUE, "Attribute name contains invalid characters"));
return false;
}
return GetValidProgram(context, program) != nullptr; return GetValidProgram(context, program) != nullptr;
} }
...@@ -4732,6 +4773,14 @@ bool ValidateGetAttachedShaders(ValidationContext *context, ...@@ -4732,6 +4773,14 @@ bool ValidateGetAttachedShaders(ValidationContext *context,
bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name) bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
{ {
// The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
// shader-related entry points
if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
{
context->handleError(Error(GL_INVALID_VALUE, "Attribute name contains invalid characters"));
return false;
}
Program *programObject = GetValidProgram(context, program); Program *programObject = GetValidProgram(context, program);
if (!programObject) if (!programObject)
...@@ -4882,6 +4931,14 @@ bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, cons ...@@ -4882,6 +4931,14 @@ bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, cons
return false; return false;
} }
// The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
// shader-related entry points
if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
{
context->handleError(Error(GL_INVALID_VALUE, "Uniform name contains invalid characters"));
return false;
}
Program *programObject = GetValidProgram(context, program); Program *programObject = GetValidProgram(context, program);
if (!programObject) if (!programObject)
...@@ -5097,6 +5154,22 @@ bool ValidateShaderSource(ValidationContext *context, ...@@ -5097,6 +5154,22 @@ bool ValidateShaderSource(ValidationContext *context,
return false; return false;
} }
// The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
// shader-related entry points
if (context->getExtensions().webglCompatibility)
{
for (GLsizei i = 0; i < count; i++)
{
size_t len = length ? static_cast<size_t>(length[i]) : strlen(string[i]);
if (!IsValidESSLString(string[i], len))
{
context->handleError(
Error(GL_INVALID_VALUE, "Shader source contains invalid characters"));
return false;
}
}
}
Shader *shaderObject = GetValidShader(context, shader); Shader *shaderObject = GetValidShader(context, shader);
if (!shaderObject) if (!shaderObject)
{ {
......
...@@ -837,6 +837,78 @@ TEST_P(WebGLCompatibilityTest, BlendWithConstantColor) ...@@ -837,6 +837,78 @@ TEST_P(WebGLCompatibilityTest, BlendWithConstantColor)
} }
} }
// Test that binding/querying uniforms and attributes with invalid names generates errors
TEST_P(WebGLCompatibilityTest, InvalidAttributeAndUniformNames)
{
const std::string validAttribName =
"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
const std::string validUniformName =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
const char invalidSet[] = {'"', '$', '`', '@', '\\', '\''};
std::string vert = "attribute float ";
vert += validAttribName;
vert +=
";\n"
"void main()\n"
"{\n"
" gl_Position = vec4(1.0);\n"
"}\n";
std::string frag =
"precision highp float;\n"
"uniform vec4 ";
frag += validUniformName;
frag +=
";\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
ANGLE_GL_PROGRAM(program, vert, frag);
EXPECT_GL_NO_ERROR();
for (char invalidChar : invalidSet)
{
std::string invalidName = validAttribName + invalidChar;
glGetAttribLocation(program, invalidName.c_str());
EXPECT_GL_ERROR(GL_INVALID_VALUE)
<< "glGetAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
glBindAttribLocation(program, 0, invalidName.c_str());
EXPECT_GL_ERROR(GL_INVALID_VALUE)
<< "glBindAttribLocation unexpectedly succeeded for name \"" << invalidName << "\".";
}
for (char invalidChar : invalidSet)
{
std::string invalidName = validUniformName + invalidChar;
glGetUniformLocation(program, invalidName.c_str());
EXPECT_GL_ERROR(GL_INVALID_VALUE)
<< "glGetUniformLocation unexpectedly succeeded for name \"" << invalidName << "\".";
}
for (char invalidChar : invalidSet)
{
std::string invalidAttribName = validAttribName + invalidChar;
const char *invalidVert[] = {
"attribute float ",
invalidAttribName.c_str(),
";\n",
"void main()\n",
"{\n",
" gl_Position = vec4(1.0);\n",
"}\n",
};
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(shader, static_cast<GLsizei>(ArraySize(invalidVert)), invalidVert, nullptr);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
glDeleteShader(shader);
}
}
// Test the checks for OOB reads in the vertex buffers, instanced version // Test the checks for OOB reads in the vertex buffers, instanced version
TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced) TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
{ {
......
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