parser/wgsl: Fix stack overflow in postfix_expression()

Have postfix_expression() use a loop instead of recursively calling itself.

Fixed chromium:1229669

Change-Id: Ied7684d00ba453a8b89ab0251d42e2a72169421f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58381
Auto-Submit: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2021-07-16 17:55:14 +00:00 committed by Tint LUCI CQ
parent fa4d4341f4
commit 29c70796d3

View File

@ -2224,6 +2224,7 @@ Maybe<ast::Expression*> ParserImpl::postfix_expression(
ast::Expression* prefix) { ast::Expression* prefix) {
Source source; Source source;
while (continue_parsing()) {
if (match(Token::Type::kPlusPlus, &source) || if (match(Token::Type::kPlusPlus, &source) ||
match(Token::Type::kMinusMinus, &source)) { match(Token::Type::kMinusMinus, &source)) {
add_error(source, add_error(source,
@ -2233,33 +2234,47 @@ Maybe<ast::Expression*> ParserImpl::postfix_expression(
} }
if (match(Token::Type::kBracketLeft, &source)) { if (match(Token::Type::kBracketLeft, &source)) {
return sync(Token::Type::kBracketRight, [&]() -> Maybe<ast::Expression*> { auto res =
sync(Token::Type::kBracketRight, [&]() -> Maybe<ast::Expression*> {
auto param = logical_or_expression(); auto param = logical_or_expression();
if (param.errored) if (param.errored)
return Failure::kErrored; return Failure::kErrored;
if (!param.matched) if (!param.matched) {
return add_error(peek(), "unable to parse expression inside []"); return add_error(peek(), "unable to parse expression inside []");
}
if (!expect("array accessor", Token::Type::kBracketRight)) if (!expect("array accessor", Token::Type::kBracketRight)) {
return Failure::kErrored; return Failure::kErrored;
}
return postfix_expression( return create<ast::ArrayAccessorExpression>(source, prefix,
create<ast::ArrayAccessorExpression>(source, prefix, param.value)); param.value);
}); });
if (res.errored) {
return res;
}
prefix = res.value;
continue;
} }
if (match(Token::Type::kPeriod)) { if (match(Token::Type::kPeriod)) {
auto ident = expect_ident("member accessor"); auto ident = expect_ident("member accessor");
if (ident.errored) if (ident.errored) {
return Failure::kErrored; return Failure::kErrored;
}
return postfix_expression(create<ast::MemberAccessorExpression>( prefix = create<ast::MemberAccessorExpression>(
ident.source, prefix, ident.source, prefix,
create<ast::IdentifierExpression>( create<ast::IdentifierExpression>(
ident.source, builder_.Symbols().Register(ident.value)))); ident.source, builder_.Symbols().Register(ident.value)));
continue;
} }
return prefix; return prefix;
}
return Failure::kErrored;
} }
// singular_expression // singular_expression