translator: Fix validation sometimes modifying builtins.
When validating some shaders with out-of-bounds array indexes,
we would write the sanitized index into the global symbol table.
We would then overwrite a wrong value for the builtin. This
fixes the WebGL test extensions/webgl-draw-buffers-max-draw-buffers.
Also mark const on as many uses ConstantUnion as we can.
BUG=angleproject:993
Change-Id: I110efaf1b7b0158b08b704277e3bc2472437902c
Reviewed-on: https://chromium-review.googlesource.com/268962
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 7580fb9..b339798 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -64,12 +64,12 @@
}
bool CompareStructure(const TType& leftNodeType,
- TConstantUnion *rightUnionArray,
- TConstantUnion *leftUnionArray);
+ const TConstantUnion *rightUnionArray,
+ const TConstantUnion *leftUnionArray);
bool CompareStruct(const TType &leftNodeType,
- TConstantUnion *rightUnionArray,
- TConstantUnion *leftUnionArray)
+ const TConstantUnion *rightUnionArray,
+ const TConstantUnion *leftUnionArray)
{
const TFieldList &fields = leftNodeType.getStruct()->fields();
@@ -102,8 +102,8 @@
}
bool CompareStructure(const TType &leftNodeType,
- TConstantUnion *rightUnionArray,
- TConstantUnion *leftUnionArray)
+ const TConstantUnion *rightUnionArray,
+ const TConstantUnion *leftUnionArray)
{
if (leftNodeType.isArray())
{
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index 06a0a7f..2fffe09 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -270,7 +270,8 @@
virtual bool hasSideEffects() const { return false; }
- TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
+ const TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
+ TConstantUnion *getUnionArrayPointer() { return mUnionArrayPointer; }
int getIConst(size_t index) const
{
@@ -289,6 +290,12 @@
return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
}
+ void replaceConstantUnion(TConstantUnion *safeConstantUnion)
+ {
+ // Previous union pointer freed on pool deallocation.
+ mUnionArrayPointer = safeConstantUnion;
+ }
+
virtual TIntermConstantUnion *getAsConstantUnion() { return this; }
virtual void traverse(TIntermTraverser *);
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
diff --git a/src/compiler/translator/Intermediate.cpp b/src/compiler/translator/Intermediate.cpp
index 81f8aa0..d3ab7d4 100644
--- a/src/compiler/translator/Intermediate.cpp
+++ b/src/compiler/translator/Intermediate.cpp
@@ -361,9 +361,9 @@
//
TIntermConstantUnion *TIntermediate::addConstantUnion(
- TConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
+ TConstantUnion *constantUnion, const TType &type, const TSourceLoc &line)
{
- TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
+ TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
node->setLine(line);
return node;
diff --git a/src/compiler/translator/Intermediate.h b/src/compiler/translator/Intermediate.h
index 74a3f89..4806b28 100644
--- a/src/compiler/translator/Intermediate.h
+++ b/src/compiler/translator/Intermediate.h
@@ -49,7 +49,8 @@
TIntermTyped *condition, const TSourceLoc &line);
TIntermTyped *addComma(
TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
- TIntermConstantUnion *addConstantUnion(TConstantUnion *, const TType &, const TSourceLoc &);
+ TIntermConstantUnion *addConstantUnion(
+ TConstantUnion *constantUnion, const TType &type, const TSourceLoc &line);
// TODO(zmo): Get rid of default value.
bool parseConstTree(const TSourceLoc &, TIntermNode *, TConstantUnion *,
TOperator, TType, bool singleConstantParam = false);
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index eb9328c..cd7ffc4 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -1814,7 +1814,7 @@
TIntermTyped* typedNode;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
- TConstantUnion *unionArray;
+ const TConstantUnion *unionArray;
if (tempConstantNode) {
unionArray = tempConstantNode->getUnionArrayPointer();
@@ -1868,7 +1868,7 @@
}
if (tempConstantNode) {
- TConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+ TConstantUnion *unionArray = tempConstantNode->getUnionArrayPointer();
int size = tempConstantNode->getType().getCols();
typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
} else {
@@ -2202,6 +2202,8 @@
}
else
{
+ int safeIndex = -1;
+
if (baseExpression->isArray())
{
if (index >= baseExpression->getType().getArraySize())
@@ -2211,13 +2213,13 @@
std::string extraInfo = extraInfoStream.str();
error(location, "", "[", extraInfo.c_str());
recover();
- index = baseExpression->getType().getArraySize() - 1;
+ safeIndex = baseExpression->getType().getArraySize() - 1;
}
else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
{
error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
recover();
- index = 0;
+ safeIndex = 0;
}
}
else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
@@ -2227,10 +2229,18 @@
std::string extraInfo = extraInfoStream.str();
error(location, "", "[", extraInfo.c_str());
recover();
- index = baseExpression->getType().getNominalSize() - 1;
+ safeIndex = baseExpression->getType().getNominalSize() - 1;
}
- indexConstantUnion->getUnionArrayPointer()->setIConst(index);
+ // Don't modify the data of the previous constant union, because it can point
+ // to builtins, like gl_MaxDrawBuffers. Instead use a new sanitized object.
+ if (safeIndex != -1)
+ {
+ TConstantUnion *safeConstantUnion = new TConstantUnion();
+ safeConstantUnion->setIConst(safeIndex);
+ indexConstantUnion->replaceConstantUnion(safeConstantUnion);
+ }
+
indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
}
}
diff --git a/src/compiler/translator/parseConst.cpp b/src/compiler/translator/parseConst.cpp
index cb9dfa8..2ace877 100644
--- a/src/compiler/translator/parseConst.cpp
+++ b/src/compiler/translator/parseConst.cpp
@@ -177,7 +177,7 @@
if (!mSingleConstantParam)
{
size_t objectSize = node->getType().getObjectSize();
- TConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ const TConstantUnion *rightUnionArray = node->getUnionArrayPointer();
for (size_t i=0; i < objectSize; i++)
{
if (mIndex >= instanceSize)
@@ -189,7 +189,7 @@
else
{
size_t totalSize = mIndex + mSize;
- TConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ const TConstantUnion *rightUnionArray = node->getUnionArrayPointer();
if (!mIsDiagonalMatrixInit)
{
int count = 0;