[wgsl-parser] Set max recursion depth on const_expr
The `const_expr` can recurse into itself if there are type declarations inside the const_expr (e.g. vec2<f32>(f32(1.0), f32(2.0))). Currently there is no limit on the amount of recursion which can be triggered. This CL sets a limit of 128 nested type declarations at which point an error will be emitted. Bug: chromium:1112144 Change-Id: Ifae45034dc9de35aed78ba8eddf584a46c7a55ce Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/27340 Reviewed-by: dan sinclair <dsinclair@chromium.org> Reviewed-by: Ryan Harrison <rharrison@chromium.org> Commit-Queue: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
a291fc1e7f
commit
deea295fc1
|
@ -67,6 +67,11 @@ namespace reader {
|
||||||
namespace wgsl {
|
namespace wgsl {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
/// Controls the maximum number of times we'll call into the const_expr function
|
||||||
|
/// from itself. This is to guard against stack overflow when there is an
|
||||||
|
/// excessive number of type constructors inside the const_expr.
|
||||||
|
uint32_t kMaxConstExprDepth = 128;
|
||||||
|
|
||||||
ast::Builtin ident_to_builtin(const std::string& str) {
|
ast::Builtin ident_to_builtin(const std::string& str) {
|
||||||
if (str == "position") {
|
if (str == "position") {
|
||||||
return ast::Builtin::kPosition;
|
return ast::Builtin::kPosition;
|
||||||
|
@ -2960,7 +2965,18 @@ std::unique_ptr<ast::Literal> ParserImpl::const_literal() {
|
||||||
// : type_decl PAREN_LEFT (const_expr COMMA)? const_expr PAREN_RIGHT
|
// : type_decl PAREN_LEFT (const_expr COMMA)? const_expr PAREN_RIGHT
|
||||||
// | const_literal
|
// | const_literal
|
||||||
std::unique_ptr<ast::ConstructorExpression> ParserImpl::const_expr() {
|
std::unique_ptr<ast::ConstructorExpression> ParserImpl::const_expr() {
|
||||||
|
return const_expr_internal(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ast::ConstructorExpression> ParserImpl::const_expr_internal(
|
||||||
|
uint32_t depth) {
|
||||||
auto t = peek();
|
auto t = peek();
|
||||||
|
|
||||||
|
if (depth > kMaxConstExprDepth) {
|
||||||
|
set_error(t, "max const_expr depth reached");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto source = t.source();
|
auto source = t.source();
|
||||||
|
|
||||||
auto* type = type_decl();
|
auto* type = type_decl();
|
||||||
|
@ -2972,7 +2988,7 @@ std::unique_ptr<ast::ConstructorExpression> ParserImpl::const_expr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExpressionList params;
|
ast::ExpressionList params;
|
||||||
auto param = const_expr();
|
auto param = const_expr_internal(depth + 1);
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (param == nullptr) {
|
if (param == nullptr) {
|
||||||
|
@ -2987,7 +3003,7 @@ std::unique_ptr<ast::ConstructorExpression> ParserImpl::const_expr() {
|
||||||
|
|
||||||
next(); // Consume the peek
|
next(); // Consume the peek
|
||||||
|
|
||||||
param = const_expr();
|
param = const_expr_internal(depth + 1);
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (param == nullptr) {
|
if (param == nullptr) {
|
||||||
|
|
|
@ -362,6 +362,9 @@ class ParserImpl {
|
||||||
uint32_t array_decoration_list();
|
uint32_t array_decoration_list();
|
||||||
ast::type::Type* type_decl_matrix(Token t);
|
ast::type::Type* type_decl_matrix(Token t);
|
||||||
|
|
||||||
|
std::unique_ptr<ast::ConstructorExpression> const_expr_internal(
|
||||||
|
uint32_t depth);
|
||||||
|
|
||||||
Context& ctx_;
|
Context& ctx_;
|
||||||
std::string error_;
|
std::string error_;
|
||||||
std::unique_ptr<Lexer> lexer_;
|
std::unique_ptr<Lexer> lexer_;
|
||||||
|
|
|
@ -122,6 +122,22 @@ TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) {
|
||||||
EXPECT_EQ(p->error(), "1:1: unknown type alias 'invalid'");
|
EXPECT_EQ(p->error(), "1:1: unknown type alias 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, ConstExpr_Recursion) {
|
||||||
|
std::stringstream out;
|
||||||
|
for (size_t i = 0; i < 200; i++) {
|
||||||
|
out << "f32(";
|
||||||
|
}
|
||||||
|
out << "1.0";
|
||||||
|
for (size_t i = 0; i < 200; i++) {
|
||||||
|
out << ")";
|
||||||
|
}
|
||||||
|
auto* p = parser(out.str());
|
||||||
|
auto e = p->const_expr();
|
||||||
|
ASSERT_TRUE(p->has_error());
|
||||||
|
ASSERT_EQ(e, nullptr);
|
||||||
|
EXPECT_EQ(p->error(), "1:517: max const_expr depth reached");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace wgsl
|
} // namespace wgsl
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
|
|
Loading…
Reference in New Issue