diff options
author | Scott Marcy <mscott@apple.com> | 2024-03-28 15:30:59 -0600 |
---|---|---|
committer | Angle LUCI CQ <angle-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2024-04-12 13:29:39 +0000 |
commit | e088af30ff462bae7db2179427ccedbe4bc82001 (patch) | |
tree | c214b7b06d3ef32ed4913c7228108758c1f7a1d0 | |
parent | 34bb0ebf6ecbaef2b2694dc1591445a0f5499ac2 (diff) | |
download | angle-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.json | 6 | ||||
-rw-r--r-- | src/compiler/translator/ParseContext.cpp | 14 | ||||
-rw-r--r-- | src/compiler/translator/ParseContext.h | 2 | ||||
-rw-r--r-- | src/compiler/translator/glslang.y | 6 | ||||
-rw-r--r-- | src/compiler/translator/glslang_lex_autogen.cpp | 2 | ||||
-rw-r--r-- | src/compiler/translator/glslang_tab_autogen.cpp | 32 | ||||
-rw-r--r-- | src/tests/compiler_tests/Parse_test.cpp | 36 |
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")); +} |