diff --git a/gfx/angle/src/libGLESv2/ProgramBinary.cpp b/gfx/angle/src/libGLESv2/ProgramBinary.cpp
--- a/gfx/angle/src/libGLESv2/ProgramBinary.cpp
+++ b/gfx/angle/src/libGLESv2/ProgramBinary.cpp
@@ -666,16 +666,22 @@ bool ProgramBinary::areMatchingInterface
 // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
 bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader)
 {
     const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
 
     unsigned int usedLocations = 0;
     const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes();
 
+    if (shaderAttributes.size() > gl::MAX_VERTEX_ATTRIBS)
+    {
+        infoLog.append("%u vertex attributes passed in exceeds maximum of %u.", shaderAttributes.size(), gl::MAX_VERTEX_ATTRIBS);
+        return false;
+    }
+
     // Link attributes that have a binding location
     for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
     {
         const sh::Attribute &attribute = shaderAttributes[attributeIndex];
 
         ASSERT(attribute.staticUse);
 
         const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
