Fix validation of uniform block size.

Uniform block members should not be validated against the
GL_MAX_VERTEX_UNIFORM_VECTORS and GL_MAX_FRAGMENT_UNIFORM_VECTORS
limits. Instead, block sizes should not exceed MAX_UNIFORM_BLOCK_SIZE.

Also move uniform block index validation to the entry functions.

Bug b/111803744

Change-Id: I0ea530813d1f2c29141dc64a93aa10f50460885b
Reviewed-on: https://swiftshader-review.googlesource.com/20028
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/libGLESv2/Program.cpp b/src/OpenGL/libGLESv2/Program.cpp
index 9b10a7f..77912cc 100644
--- a/src/OpenGL/libGLESv2/Program.cpp
+++ b/src/OpenGL/libGLESv2/Program.cpp
@@ -51,14 +51,6 @@
 			matrixStride = uniform.blockInfo.matrixStride;
 			isRowMajorMatrix = uniform.blockInfo.isRowMajorMatrix;
 		}
-		else
-		{
-			index = -1;
-			offset = -1;
-			arrayStride = -1;
-			matrixStride = -1;
-			isRowMajorMatrix = false;
-		}
 	}
 
 	Uniform::Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo)
@@ -492,20 +484,15 @@
 
 	void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
 	{
-		if(uniformBlockIndex >= getActiveUniformBlockCount())
-		{
-			return error(GL_INVALID_VALUE);
-		}
+		ASSERT(uniformBlockIndex < getActiveUniformBlockCount());
 
 		uniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
 	}
 
 	GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
 	{
-		if(uniformBlockIndex >= getActiveUniformBlockCount())
-		{
-			return error(GL_INVALID_VALUE, GL_INVALID_INDEX);
-		}
+		ASSERT(uniformBlockIndex < getActiveUniformBlockCount());
+
 		return uniformBlockBindings[uniformBlockIndex];
 	}
 
@@ -1713,8 +1700,24 @@
 			{
 				const glsl::ActiveUniformBlocks &activeUniformBlocks = shader->activeUniformBlocks;
 				ASSERT(static_cast<size_t>(uniform.blockId) < activeUniformBlocks.size());
-				blockIndex = getUniformBlockIndex(activeUniformBlocks[uniform.blockId].name);
+				const std::string &uniformBlockName = activeUniformBlocks[uniform.blockId].name;
+				blockIndex = getUniformBlockIndex(uniformBlockName);
 				ASSERT(blockIndex != GL_INVALID_INDEX);
+
+				if(activeUniformBlocks[uniform.blockId].dataSize > MAX_UNIFORM_BLOCK_SIZE)
+				{
+					if(shader->getType() == GL_VERTEX_SHADER)
+					{
+						appendToInfoLog("Vertex shader active uniform block (%s) exceeds GL_MAX_UNIFORM_BLOCK_SIZE (%d)", uniformBlockName.c_str(), MAX_UNIFORM_BLOCK_SIZE);
+						return false;
+					}
+					else if(shader->getType() == GL_FRAGMENT_SHADER)
+					{
+						appendToInfoLog("Fragment shader active uniform block (%s) exceeds GL_MAX_UNIFORM_BLOCK_SIZE (%d)", uniformBlockName.c_str(), MAX_UNIFORM_BLOCK_SIZE);
+						return false;
+					}
+					else UNREACHABLE(shader->getType());
+				}
 			}
 
 			if(!defineUniform(shader->getType(), uniform, Uniform::BlockInfo(uniform, blockIndex)))
@@ -1865,23 +1868,26 @@
 		}
 		else UNREACHABLE(shader);
 
-		if(shader == GL_VERTEX_SHADER)
+		if(uniform->blockInfo.index < 0)
 		{
-			if(glslUniform.registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS)
+			if(shader == GL_VERTEX_SHADER)
 			{
-				appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS);
-				return false;
+				if(glslUniform.registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS)
+				{
+					appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS);
+					return false;
+				}
 			}
-		}
-		else if(shader == GL_FRAGMENT_SHADER)
-		{
-			if(glslUniform.registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS)
+			else if(shader == GL_FRAGMENT_SHADER)
 			{
-				appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS);
-				return false;
+				if(glslUniform.registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS)
+				{
+					appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS);
+					return false;
+				}
 			}
+			else UNREACHABLE(shader);
 		}
-		else UNREACHABLE(shader);
 
 		return true;
 	}
@@ -2859,10 +2865,7 @@
 
 	void Program::getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const
 	{
-		if(index >= getActiveUniformBlockCount())
-		{
-			return error(GL_INVALID_VALUE);
-		}
+		ASSERT(index < getActiveUniformBlockCount());
 
 		const UniformBlock &uniformBlock = *uniformBlocks[index];
 
diff --git a/src/OpenGL/libGLESv2/Program.h b/src/OpenGL/libGLESv2/Program.h
index 6f9940b..501d081 100644
--- a/src/OpenGL/libGLESv2/Program.h
+++ b/src/OpenGL/libGLESv2/Program.h
@@ -42,11 +42,11 @@
 		{
 			BlockInfo(const glsl::Uniform& uniform, int blockIndex);
 
-			int index;
-			int offset;
-			int arrayStride;
-			int matrixStride;
-			bool isRowMajorMatrix;
+			int index = -1;
+			int offset = -1;
+			int arrayStride = -1;
+			int matrixStride = -1;
+			bool isRowMajorMatrix = false;
 		};
 
 		Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo);
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index adb24d7..b4f5377 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -2629,6 +2629,11 @@
 			return error(GL_INVALID_OPERATION);
 		}
 
+		if(uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+		{
+			return error(GL_INVALID_VALUE);
+		}
+
 		switch(pname)
 		{
 		case GL_UNIFORM_BLOCK_BINDING:
@@ -2669,6 +2674,11 @@
 			return error(GL_INVALID_OPERATION);
 		}
 
+		if(uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+		{
+			return error(GL_INVALID_VALUE);
+		}
+
 		programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
 	}
 }
@@ -2694,6 +2704,11 @@
 			return error(GL_INVALID_VALUE);
 		}
 
+		if(uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+		{
+			return error(GL_INVALID_VALUE);
+		}
+
 		programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
 	}
 }