Clamped negative index access.
Fixed error that allowed negative index for accessing
vector, matrix, and array. Now we report compile error
and clamp the index to 0.
Re-arranged code around it to handle negative index
at the one location.
BUG=crbug.com/239411
TEST=bug test case
R=aedla@chromium.org, kbr@chromium.org
Review URL: https://codereview.appspot.com/9193045
git-svn-id: https://angleproject.googlecode.com/svn/trunk@2207 736b8ea6-26fd-11df-bfd4-992fa37f6226
TRAC #23333
Authored-by: alokp@chromium.org
Signed-off-by: Shannon Woods
Signed-off-by Nicolas Capens
Merged-by: Jamie Madill
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index 35bf68e..8ae2829 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -2098,93 +2098,102 @@
}
recover();
}
- if (baseExpression->getType().getQualifier() == EvqConst && indexExpression->getQualifier() == EvqConst)
- {
- if (baseExpression->isArray())
- {
- // constant folding for arrays
- indexedExpression = addConstArrayNode(indexExpression->getAsConstantUnion()->getIConst(0), baseExpression, location);
- }
- else if (baseExpression->isVector())
- {
- // constant folding for vectors
- TVectorFields fields;
- fields.num = 1;
- fields.offsets[0] = indexExpression->getAsConstantUnion()->getIConst(0); // need to do it this way because v.xy sends fields integer array
- indexedExpression = addConstVectorNode(fields, baseExpression, location);
- }
- else if (baseExpression->isMatrix())
- {
- // constant folding for matrices
- indexedExpression = addConstMatrixNode(indexExpression->getAsConstantUnion()->getIConst(0), baseExpression, location);
- }
- }
- else
- {
- if (indexExpression->getQualifier() == EvqConst)
- {
- const bool isMatrixOrVector = (baseExpression->isVector() || baseExpression->isMatrix());
- const bool indexOOR = (isMatrixOrVector && baseExpression->getType().getNominalSize() <= indexExpression->getAsConstantUnion()->getIConst(0));
- // check for index out-of-range
- if (indexOOR && !baseExpression->isArray())
+ if (indexExpression->getQualifier() == EvqConst)
+ {
+ int index = indexExpression->getAsConstantUnion()->getIConst(0);
+ if (index < 0)
+ {
+ std::stringstream infoStream;
+ infoStream << index;
+ std::string info = infoStream.str();
+ error(location, "negative index", info.c_str());
+ recover();
+ index = 0;
+ }
+ if (baseExpression->getType().getQualifier() == EvqConst)
+ {
+ if (baseExpression->isArray())
{
- std::stringstream extraInfoStream;
- extraInfoStream << "field selection out of range '" << indexExpression->getAsConstantUnion()->getIConst(0) << "'";
- std::string extraInfo = extraInfoStream.str();
- error(location, "", "[", extraInfo.c_str());
- recover();
+ // constant folding for arrays
+ indexedExpression = addConstArrayNode(index, baseExpression, location);
}
- else
+ else if (baseExpression->isVector())
{
- if (baseExpression->isArray())
- {
- if (baseExpression->getType().getArraySize() == 0)
- {
- if (baseExpression->getType().getMaxArraySize() <= indexExpression->getAsConstantUnion()->getIConst(0))
- {
- if (arraySetMaxSize(baseExpression->getAsSymbolNode(), baseExpression->getTypePointer(), indexExpression->getAsConstantUnion()->getIConst(0), true, location))
- recover();
- }
- else
- {
- if (arraySetMaxSize(baseExpression->getAsSymbolNode(), baseExpression->getTypePointer(), 0, false, location))
- recover();
- }
- }
- else if ( indexExpression->getAsConstantUnion()->getIConst(0) >= baseExpression->getType().getArraySize())
- {
- std::stringstream extraInfoStream;
- extraInfoStream << "array index out of range '" << indexExpression->getAsConstantUnion()->getIConst(0) << "'";
- std::string extraInfo = extraInfoStream.str();
- error(location, "", "[", extraInfo.c_str());
- recover();
- }
- }
- indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
+ // constant folding for vectors
+ TVectorFields fields;
+ fields.num = 1;
+ fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
+ indexedExpression = addConstVectorNode(fields, baseExpression, location);
+ }
+ else if (baseExpression->isMatrix())
+ {
+ // constant folding for matrices
+ indexedExpression = addConstMatrixNode(index, baseExpression, location);
}
}
else
{
- if (baseExpression->isArray() && baseExpression->getType().getArraySize() == 0)
+ if (baseExpression->isArray())
{
- error(location, "", "[", "array must be redeclared with a size before being indexed with a variable");
- recover();
+ if (baseExpression->getType().getArraySize() == 0)
+ {
+ if (baseExpression->getType().getMaxArraySize() <= index)
+ {
+ if (arraySetMaxSize(baseExpression->getAsSymbolNode(), baseExpression->getTypePointer(), index, true, location))
+ recover();
+ }
+ else
+ {
+ if (arraySetMaxSize(baseExpression->getAsSymbolNode(), baseExpression->getTypePointer(), 0, false, location))
+ recover();
+ }
+ }
+ else if (index >= baseExpression->getType().getArraySize())
+ {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "array index out of range '" << index << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(location, "", "[", extraInfo.c_str());
+ recover();
+ index = baseExpression->getType().getArraySize() - 1;
+ }
}
- else if (baseExpression->getBasicType() == EbtInterfaceBlock)
+ else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
{
- error(location, "", "[", "array indexes for interface blocks arrays must be constant integeral expressions");
+ std::stringstream extraInfoStream;
+ extraInfoStream << "field selection out of range '" << index << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(location, "", "[", extraInfo.c_str());
recover();
- }
- else if (baseExpression->getQualifier() == EvqFragmentOutput)
- {
- error(location, "", "[", "array indexes for output variables must be constant integeral expressions");
- recover();
+ index = baseExpression->getType().getNominalSize() - 1;
}
- indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
+ indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
+ indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
}
}
+ else
+ {
+ if (baseExpression->isArray() && baseExpression->getType().getArraySize() == 0)
+ {
+ error(location, "", "[", "array must be redeclared with a size before being indexed with a variable");
+ recover();
+ }
+ else if (baseExpression->getBasicType() == EbtInterfaceBlock)
+ {
+ error(location, "", "[", "array indexes for interface blocks arrays must be constant integeral expressions");
+ recover();
+ }
+ else if (baseExpression->getQualifier() == EvqFragmentOutput)
+ {
+ error(location, "", "[", "array indexes for output variables must be constant integeral expressions");
+ recover();
+ }
+
+ indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
+ }
+
if (indexedExpression == 0)
{
ConstantUnion *unionArray = new ConstantUnion[1];
@@ -2209,21 +2218,15 @@
indexedExpression->getTypePointer()->setQualifier(EvqConst);
}
}
- else if (baseExpression->isMatrix() && baseExpression->getType().getQualifier() == EvqConst)
- {
- indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst, baseExpression->getRows()));
- }
else if (baseExpression->isMatrix())
{
- indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getRows()));
- }
- else if (baseExpression->isVector() && baseExpression->getType().getQualifier() == EvqConst)
- {
- indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst));
+ TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getRows()));
}
else if (baseExpression->isVector())
{
- indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
+ TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
}
else
{