Fixed all OOB accesses in VertexProgram and PixelProgram
A lot of arrays in VertexProgram and PixelProgram have fixed sizes,
so programs that have more nested loops or ifs or deeper call stacks
can cause OOB accesses, which causes security issues in Chromium.
Index clamping was added to prevent any OOB memory accesses here.
This could eventually be fixed properly by first verifying these sizes
and giving shader compile errors when these limits are exceeded.
Bug chromium:915197 chromium:915206 chromium:915218 b/116373662
Change-Id: I2d0710ed0ce6585f139cba49d5b5d8c909ae6391
Reviewed-on: https://swiftshader-review.googlesource.com/c/23568
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Corentin Wallez <cwallez@google.com>
diff --git a/src/Shader/VertexProgram.cpp b/src/Shader/VertexProgram.cpp
index bde7531..05f8dfb 100644
--- a/src/Shader/VertexProgram.cpp
+++ b/src/Shader/VertexProgram.cpp
@@ -26,7 +26,7 @@
VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader)
: VertexRoutine(state, shader), shader(shader), r(shader->indirectAddressableTemporaries)
{
- for(int i = 0; i < 2048; i++)
+ for(int i = 0; i < MAX_SHADER_CALL_SITES; i++)
{
labelBlock[i] = 0;
}
@@ -979,7 +979,7 @@
return Int4(0xFFFFFFFF);
}
- Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
+ Int4 enable = instruction->analysisBranch ? Int4(enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))]) : Int4(0xFFFFFFFF);
if(shader->containsBreakInstruction() && instruction->analysisBreak)
{
@@ -1058,7 +1058,7 @@
void VertexProgram::BREAK()
{
- enableBreak = enableBreak & ~enableStack[enableIndex];
+ enableBreak = enableBreak & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
}
void VertexProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
@@ -1094,14 +1094,14 @@
void VertexProgram::BREAK(Int4 &condition)
{
- condition &= enableStack[enableIndex];
+ condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
enableBreak = enableBreak & ~condition;
}
void VertexProgram::CONTINUE()
{
- enableContinue = enableContinue & ~enableStack[enableIndex];
+ enableContinue = enableContinue & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
}
void VertexProgram::TEST()
@@ -1124,7 +1124,7 @@
if(callRetBlock[labelIndex].size() > 1)
{
- callStack[stackIndex++] = UInt(callSiteIndex);
+ callStack[Min(stackIndex++, Int(MAX_SHADER_CALL_STACK_SIZE))] = UInt(callSiteIndex);
}
Int4 restoreLeave = enableLeave;
@@ -1164,7 +1164,7 @@
if(callRetBlock[labelIndex].size() > 1)
{
- callStack[stackIndex++] = UInt(callSiteIndex);
+ callStack[Min(stackIndex++, Int(MAX_SHADER_CALL_STACK_SIZE))] = UInt(callSiteIndex);
}
Int4 restoreLeave = enableLeave;
@@ -1184,7 +1184,7 @@
condition = ~condition;
}
- condition &= enableStack[enableIndex];
+ condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
if(!labelBlock[labelIndex])
{
@@ -1193,11 +1193,11 @@
if(callRetBlock[labelIndex].size() > 1)
{
- callStack[stackIndex++] = UInt(callSiteIndex);
+ callStack[Min(stackIndex++, Int(MAX_SHADER_CALL_STACK_SIZE))] = UInt(callSiteIndex);
}
enableIndex++;
- enableStack[enableIndex] = condition;
+ enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
Int4 restoreLeave = enableLeave;
Bool notAllFalse = SignMask(condition) != 0;
@@ -1217,12 +1217,12 @@
if(isConditionalIf[ifDepth])
{
- Int4 condition = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
+ Int4 condition = ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] & enableStack[Min(enableIndex - 1, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
Bool notAllFalse = SignMask(condition) != 0;
branch(notAllFalse, falseBlock, endBlock);
- enableStack[enableIndex] = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
+ enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] & enableStack[Min(enableIndex - 1, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
}
else
{
@@ -1376,10 +1376,10 @@
void VertexProgram::IF(Int4 &condition)
{
- condition &= enableStack[enableIndex];
+ condition &= enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
enableIndex++;
- enableStack[enableIndex] = condition;
+ enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
BasicBlock *trueBlock = Nucleus::createBasicBlock();
BasicBlock *falseBlock = Nucleus::createBasicBlock();
@@ -1484,10 +1484,10 @@
const Vector4f &src = fetchRegister(temporaryRegister);
Int4 condition = As<Int4>(src.x);
- condition &= enableStack[enableIndex - 1];
+ condition &= enableStack[Min(enableIndex - 1, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
if(shader->containsLeaveInstruction()) condition &= enableLeave;
if(shader->containsBreakInstruction()) condition &= enableBreak;
- enableStack[enableIndex] = condition;
+ enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))] = condition;
Bool notAllFalse = SignMask(condition) != 0;
branch(notAllFalse, loopBlock, endBlock);
@@ -1560,7 +1560,7 @@
void VertexProgram::LEAVE()
{
- enableLeave = enableLeave & ~enableStack[enableIndex];
+ enableLeave = enableLeave & ~enableStack[Min(enableIndex, Int(MAX_SHADER_ENABLE_STACK_SIZE))];
// FIXME: Return from function if all instances left
// FIXME: Use enableLeave in other control-flow constructs