mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-09 21:47:47 +00:00
tint/resolver: Limit scope depth / if-chains.
DXC will bail if these get too deeply nested (~256). This is also a risk for stack-overflows, so apply a limit agreed by the WGSL working group. Fixed: tint:1518 Change-Id: Idacdba85b36b27a0a89a3a7958fd4c6cce7dc84d Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105964 Auto-Submit: Ben Clayton <bclayton@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
3a6b5362d5
commit
bd5bd247f0
@@ -93,6 +93,7 @@ namespace tint::resolver {
|
||||
namespace {
|
||||
|
||||
constexpr int64_t kMaxArrayElementCount = 65536;
|
||||
constexpr uint32_t kMaxStatementDepth = 127;
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -3400,6 +3401,14 @@ SEM* Resolver::StatementScope(const ast::Statement* ast, SEM* sem, F&& callback)
|
||||
TINT_SCOPED_ASSIGNMENT(current_statement_, sem);
|
||||
TINT_SCOPED_ASSIGNMENT(current_compound_statement_,
|
||||
as_compound ? as_compound : current_compound_statement_);
|
||||
TINT_SCOPED_ASSIGNMENT(current_scoping_depth_, current_scoping_depth_ + 1);
|
||||
|
||||
if (current_scoping_depth_ > kMaxStatementDepth) {
|
||||
AddError("statement nesting depth / chaining length exceeds limit of " +
|
||||
std::to_string(kMaxStatementDepth),
|
||||
ast->source);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!callback()) {
|
||||
return nullptr;
|
||||
|
||||
@@ -377,7 +377,8 @@ class Resolver {
|
||||
/// * Assigns `sem` to #current_compound_statement_ if `sem` derives from
|
||||
/// sem::CompoundStatement.
|
||||
/// * Then calls `callback`.
|
||||
/// * Before returning #current_statement_ and #current_compound_statement_ are restored to their original values.
|
||||
/// * Before returning #current_statement_ and #current_compound_statement_ are restored to
|
||||
/// their original values.
|
||||
/// @returns `sem` if `callback` returns true, otherwise `nullptr`.
|
||||
template <typename SEM, typename F>
|
||||
SEM* StatementScope(const ast::Statement* ast, SEM* sem, F&& callback);
|
||||
@@ -439,6 +440,7 @@ class Resolver {
|
||||
sem::Function* current_function_ = nullptr;
|
||||
sem::Statement* current_statement_ = nullptr;
|
||||
sem::CompoundStatement* current_compound_statement_ = nullptr;
|
||||
uint32_t current_scoping_depth_ = 0;
|
||||
};
|
||||
|
||||
} // namespace tint::resolver
|
||||
|
||||
@@ -2331,5 +2331,47 @@ TEST_F(ResolverTest, Literal_F16WithExtension) {
|
||||
EXPECT_TRUE(r()->Resolve());
|
||||
}
|
||||
|
||||
// Windows debug builds have significantly smaller stack than other builds, and these tests will stack
|
||||
// overflow.
|
||||
#if !defined(NDEBUG)
|
||||
|
||||
TEST_F(ResolverTest, ScopeDepth_NestedBlocks) {
|
||||
const ast::Statement* stmt = Return();
|
||||
for (size_t i = 0; i < 150; i++) {
|
||||
stmt = Block(Source{{i, 1}}, stmt);
|
||||
}
|
||||
WrapInFunction(stmt);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"23:1 error: statement nesting depth / chaining length exceeds limit of 127");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, ScopeDepth_NestedIf) {
|
||||
const ast::Statement* stmt = Return();
|
||||
for (size_t i = 0; i < 150; i++) {
|
||||
stmt = If(Source{{i, 1}}, false, Block(Source{{i, 2}}, stmt));
|
||||
}
|
||||
WrapInFunction(stmt);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"86:1 error: statement nesting depth / chaining length exceeds limit of 127");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, ScopeDepth_IfElseChain) {
|
||||
const ast::Statement* stmt = nullptr;
|
||||
for (size_t i = 0; i < 150; i++) {
|
||||
stmt = If(Source{{i, 1}}, false, Block(Source{{i, 2}}), Else(stmt));
|
||||
}
|
||||
WrapInFunction(stmt);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"24:2 error: statement nesting depth / chaining length exceeds limit of 127");
|
||||
}
|
||||
|
||||
#endif // !defined(NDEBUG)
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::resolver
|
||||
|
||||
Reference in New Issue
Block a user