Fix infinite spin in wgsl parser
If the parser hits a `maximum parser recursive depth reached` situation, then we need to try and resynchronize the parser. If we fail to do this, then the synchronized_ flag may remain true, and the parser will believe progress is still being made. In this situation the parser may try to reparse the same token, forever. By calling sync_to() we either find the end of the block, and forward progress can be made, or synchronized_ is set to false, and the parser can error out cleanly. Add test case from fuzzer report. Fixed: chromium:1180128 Change-Id: I893077677fd3dfbd4b9b400cd32db842b06db500 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/42029 Reviewed-by: David Neto <dneto@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
527a0bbf25
commit
767df5f03b
1
BUILD.gn
1
BUILD.gn
|
@ -1036,6 +1036,7 @@ source_set("tint_unittests_wgsl_reader_src") {
|
|||
"src/reader/wgsl/parser_impl_assignment_stmt_test.cc",
|
||||
"src/reader/wgsl/parser_impl_body_stmt_test.cc",
|
||||
"src/reader/wgsl/parser_impl_break_stmt_test.cc",
|
||||
"src/reader/wgsl/parser_impl_bug_cases_test.cc",
|
||||
"src/reader/wgsl/parser_impl_call_stmt_test.cc",
|
||||
"src/reader/wgsl/parser_impl_case_body_test.cc",
|
||||
"src/reader/wgsl/parser_impl_const_expr_test.cc",
|
||||
|
|
|
@ -567,6 +567,7 @@ if(${TINT_BUILD_TESTS})
|
|||
reader/wgsl/parser_impl_assignment_stmt_test.cc
|
||||
reader/wgsl/parser_impl_body_stmt_test.cc
|
||||
reader/wgsl/parser_impl_break_stmt_test.cc
|
||||
reader/wgsl/parser_impl_bug_cases_test.cc
|
||||
reader/wgsl/parser_impl_call_stmt_test.cc
|
||||
reader/wgsl/parser_impl_case_body_test.cc
|
||||
reader/wgsl/parser_impl_const_expr_test.cc
|
||||
|
|
|
@ -3162,7 +3162,15 @@ T ParserImpl::expect_lt_gt_block(const std::string& use, F&& body) {
|
|||
template <typename F, typename T>
|
||||
T ParserImpl::sync(Token::Type tok, F&& body) {
|
||||
if (sync_depth_ >= kMaxSyncDepth) {
|
||||
return add_error(peek(), "maximum parser recursive depth reached");
|
||||
// We've hit a maximum parser recursive depth.
|
||||
// We can't call into body() as we might stack overflow.
|
||||
// Instead, report an error...
|
||||
add_error(peek(), "maximum parser recursive depth reached");
|
||||
// ...and try to resynchronize. If we cannot resynchronize to `tok` then
|
||||
// synchronized_ is set to false, and the parser knows that forward progress
|
||||
// is not being made.
|
||||
sync_to(tok, /* consume: */ true);
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
sync_tokens_.push_back(tok);
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/ast/break_statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
namespace {
|
||||
|
||||
TEST_F(ParserImplTest, Bug_chromium_1180130) {
|
||||
auto p = parser(
|
||||
R"(a;{}}a;}};{{{;{}};{};{}}a;{}};{{{}};{{{;{}};{};{}}a;{}};{{{}}{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}}{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}}{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{{{;u[([[,a;{}}a;{}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{z{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}}{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}}{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}}{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}}{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}}{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}}{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}}i;{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};{}{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{{;u[({}};{{{}};{{}a;{}};{{{}};{{{;{}};{};}a;{}};{{{}};{{;u[[a,([}};{{{;{}})");
|
||||
EXPECT_FALSE(p->Parse());
|
||||
EXPECT_TRUE(p->has_error());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace wgsl
|
||||
} // namespace reader
|
||||
} // namespace tint
|
Loading…
Reference in New Issue