wgsl::ParserImpl: Use sync() for postfix_expr()
postfix_expr() handles `[]` array accessors and call expressions `()`.
Have postfix_expr() use sync to parse these:
* It will use the end bracket token to attempt to resynchronize the parser on error
* It also considers maximum parser recursion depth, avoiding stack overflows
Fixed: chromium:1180573
Change-Id: I8c1c62c68e24a564e0e4e7d0de9f5a3fa7032369
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/42222
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index fb9535b..07c22ec 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -2136,34 +2136,38 @@
Maybe<ast::Expression*> ParserImpl::postfix_expr(ast::Expression* prefix) {
Source source;
if (match(Token::Type::kBracketLeft, &source)) {
- auto param = logical_or_expression();
- if (param.errored)
- return Failure::kErrored;
- if (!param.matched)
- return add_error(peek(), "unable to parse expression inside []");
+ return sync(Token::Type::kBracketRight, [&]() -> Maybe<ast::Expression*> {
+ auto param = logical_or_expression();
+ if (param.errored)
+ return Failure::kErrored;
+ if (!param.matched)
+ return add_error(peek(), "unable to parse expression inside []");
- if (!expect("array accessor", Token::Type::kBracketRight))
- return Failure::kErrored;
+ if (!expect("array accessor", Token::Type::kBracketRight))
+ return Failure::kErrored;
- return postfix_expr(
- create<ast::ArrayAccessorExpression>(source, prefix, param.value));
+ return postfix_expr(
+ create<ast::ArrayAccessorExpression>(source, prefix, param.value));
+ });
}
if (match(Token::Type::kParenLeft, &source)) {
- ast::ExpressionList params;
+ return sync(Token::Type::kParenRight, [&]() -> Maybe<ast::Expression*> {
+ ast::ExpressionList params;
- auto t = peek();
- if (!t.IsParenRight() && !t.IsEof()) {
- auto list = expect_argument_expression_list();
- if (list.errored)
+ auto t = peek();
+ if (!t.IsParenRight() && !t.IsEof()) {
+ auto list = expect_argument_expression_list();
+ if (list.errored)
+ return Failure::kErrored;
+ params = list.value;
+ }
+
+ if (!expect("call expression", Token::Type::kParenRight))
return Failure::kErrored;
- params = list.value;
- }
- if (!expect("call expression", Token::Type::kParenRight))
- return Failure::kErrored;
-
- return postfix_expr(create<ast::CallExpression>(source, prefix, params));
+ return postfix_expr(create<ast::CallExpression>(source, prefix, params));
+ });
}
if (match(Token::Type::kPeriod)) {