aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Marcy <mscott@apple.com>2024-03-28 15:30:59 -0600
committerAngle LUCI CQ <angle-scoped@luci-project-accounts.iam.gserviceaccount.com>2024-04-12 13:29:39 +0000
commite088af30ff462bae7db2179427ccedbe4bc82001 (patch)
treec214b7b06d3ef32ed4913c7228108758c1f7a1d0
parent34bb0ebf6ecbaef2b2694dc1591445a0f5499ac2 (diff)
downloadangle-e088af30ff462bae7db2179427ccedbe4bc82001.tar.gz
Parsing very long array declarations crash
Avoid stack overflow crash when parsing arrays with a huge number of dimensions. Limits the number of array dimensions to `mMaxExpressionComplexity` (typically 256). Use `YYABORT` to abort parsing. Bug: angleproject:8610 Change-Id: Icf3914871b167c820b84ae8f3acba80dbd698af3 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5424330 Auto-Submit: Kimmo Kinnunen <kkinnunen@apple.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
-rw-r--r--scripts/code_generation_hashes/ANGLE_shader_translator.json6
-rw-r--r--src/compiler/translator/ParseContext.cpp14
-rw-r--r--src/compiler/translator/ParseContext.h2
-rw-r--r--src/compiler/translator/glslang.y6
-rw-r--r--src/compiler/translator/glslang_lex_autogen.cpp2
-rw-r--r--src/compiler/translator/glslang_tab_autogen.cpp32
-rw-r--r--src/tests/compiler_tests/Parse_test.cpp36
7 files changed, 82 insertions, 16 deletions
diff --git a/scripts/code_generation_hashes/ANGLE_shader_translator.json b/scripts/code_generation_hashes/ANGLE_shader_translator.json
index 7ee7ddab89..cf1fa51782 100644
--- a/scripts/code_generation_hashes/ANGLE_shader_translator.json
+++ b/scripts/code_generation_hashes/ANGLE_shader_translator.json
@@ -6,11 +6,11 @@
"src/compiler/translator/glslang.l":
"c47eb888a67462feb27aaab02414ae27",
"src/compiler/translator/glslang.y":
- "b3b3edb114fdd4000c2b78e0bfc7e93d",
+ "2441bd917904b3911597c66e57e0ec0d",
"src/compiler/translator/glslang_lex_autogen.cpp":
- "e8b1dcb576768e279a226f3c072d32d7",
+ "e9fa08ed8de9fd90b3c9243e1b80396a",
"src/compiler/translator/glslang_tab_autogen.cpp":
- "9719a04ebc96f86619ef474678c6a878",
+ "927db5244b528a45016e9f67d8b5ccf4",
"src/compiler/translator/glslang_tab_autogen.h":
"028bdaebf359aefbcdaafae466993ebe",
"tools/flex-bison/linux/bison.sha1":
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 6a70f67be9..ffdfdab548 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -306,6 +306,9 @@ TParseContext::TParseContext(TSymbolTable &symt,
mDirectiveHandler(ext, *mDiagnostics, mShaderVersion, mShaderType),
mPreprocessor(mDiagnostics, &mDirectiveHandler, angle::pp::PreprocessorSettings(spec)),
mScanner(nullptr),
+ mMaxExpressionComplexity(static_cast<size_t>(options.limitExpressionComplexity
+ ? resources.MaxExpressionComplexity
+ : std::numeric_limits<size_t>::max())),
mMinProgramTexelOffset(resources.MinProgramTexelOffset),
mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset),
@@ -1256,6 +1259,17 @@ unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TInter
return size;
}
+bool TParseContext::checkIsValidArrayDimension(const TSourceLoc &line,
+ TVector<unsigned int> *arraySizes)
+{
+ if (arraySizes->size() > mMaxExpressionComplexity)
+ {
+ error(line, "array has too many dimensions", "");
+ return false;
+ }
+ return true;
+}
+
// See if this qualifier can be an array.
bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
const TPublicType &elementQualifier)
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 67961f8cdb..50f6794ffc 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -142,6 +142,7 @@ class TParseContext : angle::NonCopyable
// Returns a sanitized array size to use (the size is at least 1).
unsigned int checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr);
+ bool checkIsValidArrayDimension(const TSourceLoc &line, TVector<unsigned int> *arraySizes);
bool checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &elementQualifier);
bool checkArrayElementIsNotArray(const TSourceLoc &line, const TPublicType &elementType);
bool checkArrayOfArraysInOut(const TSourceLoc &line,
@@ -761,6 +762,7 @@ class TParseContext : angle::NonCopyable
TDirectiveHandler mDirectiveHandler;
angle::pp::Preprocessor mPreprocessor;
void *mScanner;
+ const size_t mMaxExpressionComplexity;
int mMinProgramTexelOffset;
int mMaxProgramTexelOffset;
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index fec89cffd8..8323f70ad3 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -997,6 +997,9 @@ array_specifier
ES3_1_OR_NEWER("[]", @2, "arrays of arrays");
$$ = $1;
$$->insert($$->begin(), 0u);
+ if (!context->checkIsValidArrayDimension(@2, $$)) {
+ YYABORT;
+ }
}
| array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
ES3_1_OR_NEWER("[]", @2, "arrays of arrays");
@@ -1005,6 +1008,9 @@ array_specifier
// Make the type an array even if size check failed.
// This ensures useless error messages regarding a variable's non-arrayness won't follow.
$$->insert($$->begin(), size);
+ if (!context->checkIsValidArrayDimension(@2, $$)) {
+ YYABORT;
+ }
}
;
diff --git a/src/compiler/translator/glslang_lex_autogen.cpp b/src/compiler/translator/glslang_lex_autogen.cpp
index 3d792c6cd5..a7558cbd1d 100644
--- a/src/compiler/translator/glslang_lex_autogen.cpp
+++ b/src/compiler/translator/glslang_lex_autogen.cpp
@@ -2783,7 +2783,7 @@ YY_DECL
} /* end of action switch */
} /* end of scanning one token */
} /* end of user's declarations */
-} /* end of yylex */
+} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
*
diff --git a/src/compiler/translator/glslang_tab_autogen.cpp b/src/compiler/translator/glslang_tab_autogen.cpp
index 233b571b79..6064c50d26 100644
--- a/src/compiler/translator/glslang_tab_autogen.cpp
+++ b/src/compiler/translator/glslang_tab_autogen.cpp
@@ -725,7 +725,7 @@ void *malloc(YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# ifndef YYFREE
# define YYFREE free
# if !defined free && !defined EXIT_SUCCESS
-void free(void *); /* INFRINGES ON USER NAME SPACE */
+void free(void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# endif
@@ -854,17 +854,17 @@ static const yytype_int16 yyrline[] = {
743, 747, 752, 759, 763, 767, 771, 776, 783, 787, 793, 796, 799, 809, 813, 820,
826, 832, 836, 840, 843, 846, 850, 858, 863, 867, 870, 873, 876, 879, 883, 891,
894, 898, 901, 904, 907, 910, 913, 917, 924, 931, 934, 937, 943, 950, 953, 959,
- 962, 965, 968, 974, 977, 984, 989, 996, 1001, 1012, 1015, 1018, 1021, 1024, 1027, 1031,
- 1035, 1039, 1043, 1047, 1051, 1055, 1059, 1063, 1067, 1071, 1075, 1079, 1083, 1087, 1091, 1095,
- 1099, 1103, 1107, 1111, 1118, 1121, 1124, 1127, 1130, 1133, 1136, 1144, 1152, 1162, 1165, 1168,
- 1171, 1174, 1177, 1180, 1188, 1196, 1206, 1209, 1212, 1215, 1218, 1221, 1224, 1232, 1240, 1250,
- 1253, 1256, 1259, 1267, 1275, 1282, 1292, 1299, 1306, 1309, 1312, 1315, 1318, 1321, 1324, 1327,
- 1330, 1333, 1336, 1339, 1342, 1350, 1358, 1366, 1374, 1382, 1390, 1400, 1410, 1420, 1423, 1430,
- 1437, 1444, 1447, 1455, 1455, 1458, 1458, 1464, 1467, 1473, 1476, 1483, 1487, 1493, 1496, 1502,
- 1506, 1510, 1511, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1527, 1531, 1531, 1531, 1538, 1539,
- 1543, 1543, 1544, 1544, 1549, 1553, 1560, 1564, 1571, 1572, 1576, 1582, 1586, 1595, 1595, 1602,
- 1605, 1611, 1615, 1621, 1621, 1626, 1626, 1630, 1630, 1638, 1641, 1647, 1650, 1656, 1660, 1667,
- 1670, 1673, 1676, 1679, 1687, 1693, 1699, 1702, 1708, 1708};
+ 962, 965, 968, 974, 977, 984, 989, 996, 1004, 1018, 1021, 1024, 1027, 1030, 1033, 1037,
+ 1041, 1045, 1049, 1053, 1057, 1061, 1065, 1069, 1073, 1077, 1081, 1085, 1089, 1093, 1097, 1101,
+ 1105, 1109, 1113, 1117, 1124, 1127, 1130, 1133, 1136, 1139, 1142, 1150, 1158, 1168, 1171, 1174,
+ 1177, 1180, 1183, 1186, 1194, 1202, 1212, 1215, 1218, 1221, 1224, 1227, 1230, 1238, 1246, 1256,
+ 1259, 1262, 1265, 1273, 1281, 1288, 1298, 1305, 1312, 1315, 1318, 1321, 1324, 1327, 1330, 1333,
+ 1336, 1339, 1342, 1345, 1348, 1356, 1364, 1372, 1380, 1388, 1396, 1406, 1416, 1426, 1429, 1436,
+ 1443, 1450, 1453, 1461, 1461, 1464, 1464, 1470, 1473, 1479, 1482, 1489, 1493, 1499, 1502, 1508,
+ 1512, 1516, 1517, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1533, 1537, 1537, 1537, 1544, 1545,
+ 1549, 1549, 1550, 1550, 1555, 1559, 1566, 1570, 1577, 1578, 1582, 1588, 1592, 1601, 1601, 1608,
+ 1611, 1617, 1621, 1627, 1627, 1632, 1632, 1636, 1636, 1644, 1647, 1653, 1656, 1662, 1666, 1673,
+ 1676, 1679, 1682, 1685, 1693, 1699, 1705, 1708, 1714, 1714};
#endif
/** Accessing symbol of state STATE. */
@@ -3501,6 +3501,10 @@ yyreduce:
ES3_1_OR_NEWER("[]", (yylsp[-1]), "arrays of arrays");
(yyval.interm.arraySizes) = (yyvsp[-2].interm.arraySizes);
(yyval.interm.arraySizes)->insert((yyval.interm.arraySizes)->begin(), 0u);
+ if (!context->checkIsValidArrayDimension((yylsp[-1]), (yyval.interm.arraySizes)))
+ {
+ YYABORT;
+ }
}
break;
@@ -3515,6 +3519,10 @@ yyreduce:
// This ensures useless error messages regarding a variable's non-arrayness won't
// follow.
(yyval.interm.arraySizes)->insert((yyval.interm.arraySizes)->begin(), size);
+ if (!context->checkIsValidArrayDimension((yylsp[-2]), (yyval.interm.arraySizes)))
+ {
+ YYABORT;
+ }
}
break;
diff --git a/src/tests/compiler_tests/Parse_test.cpp b/src/tests/compiler_tests/Parse_test.cpp
index 2408649262..eeebd76621 100644
--- a/src/tests/compiler_tests/Parse_test.cpp
+++ b/src/tests/compiler_tests/Parse_test.cpp
@@ -256,3 +256,39 @@ void main() {
EXPECT_TRUE(foundInIntermediateTree(
"cannot convert from 'const void' to 'highp 3-component vector of float'"));
}
+
+TEST_F(ParseTest, HugeUnsizedMultidimensionalArrayConstructorNoCrash)
+{
+ mCompileOptions.limitExpressionComplexity = true;
+ std::ostringstream shader;
+ shader << R"(#version 310 es
+int E=int)";
+ for (int i = 0; i < 10000; ++i)
+ {
+ shader << "[]";
+ }
+ shader << "()";
+ EXPECT_FALSE(compile(shader.str()));
+ EXPECT_TRUE(foundErrorInIntermediateTree());
+ EXPECT_TRUE(foundInIntermediateTree("array has too many dimensions"));
+}
+
+TEST_F(ParseTest, HugeMultidimensionalArrayConstructorNoCrash)
+{
+ mCompileOptions.limitExpressionComplexity = true;
+ std::ostringstream shader;
+ shader << R"(#version 310 es
+int E=int)";
+ for (int i = 0; i < 10000; ++i)
+ {
+ shader << "[1]";
+ }
+
+ for (int i = 0; i < 10000; ++i)
+ {
+ shader << "(2)";
+ }
+ EXPECT_FALSE(compile(shader.str()));
+ EXPECT_TRUE(foundErrorInIntermediateTree());
+ EXPECT_TRUE(foundInIntermediateTree("array has too many dimensions"));
+}