tint/resolver: Fix BuiltinCall validator nullptr deref

This patch fix a nullptr dereference case in Validator::BuiltinCall,
which check if a no-return-value built-in is called in something other
than call statement. Such call may don't have a statement context at all.

Bug: chromium:1346830
Change-Id: Ieef02daa5c93a3ac253cd7a7366a53e0fc7887b1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96986
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Zhaoming Jiang <zhaoming.jiang@intel.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
Zhaoming Jiang 2022-07-25 12:18:38 +00:00 committed by Dawn LUCI CQ
parent 401ac122d5
commit 659d58ceca
2 changed files with 26 additions and 3 deletions

View File

@ -1602,11 +1602,16 @@ bool Validator::IfStatement(const sem::IfStatement* stmt) const {
bool Validator::BuiltinCall(const sem::Call* call) const {
if (call->Type()->Is<sem::Void>()) {
bool is_call_statement = false;
if (auto* call_stmt = As<ast::CallStatement>(call->Stmt()->Declaration())) {
if (call_stmt->expr == call->Declaration()) {
// Some built-in call are not owned by a statement, e.g. a built-in called in global
// variable declaration. Calling no-return-value built-in in these context is invalid as
// well.
if (auto* call_stmt = call->Stmt()) {
if (auto* call_stmt_ast = As<ast::CallStatement>(call_stmt->Declaration())) {
if (call_stmt_ast->expr == call->Declaration()) {
is_call_statement = true;
}
}
}
if (!is_call_statement) {
// https://gpuweb.github.io/gpuweb/wgsl/#function-call-expr
// If the called function does not return a value, a function call

View File

@ -40,6 +40,24 @@ TEST_F(ResolverVariableValidationTest, GlobalVarNoInitializerNoType) {
EXPECT_EQ(r()->error(), "12:34 error: var declaration requires a type or initializer");
}
TEST_F(ResolverVariableValidationTest, VarInitializerNoReturnValueBuiltin) {
// fn f() { var a = storageBarrier(); }
auto* NoReturnValueBuiltin = Call(Source{{12, 34}}, "storageBarrier");
WrapInFunction(Var("a", nullptr, ast::StorageClass::kNone, NoReturnValueBuiltin));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: builtin 'storageBarrier' does not return a value");
}
TEST_F(ResolverVariableValidationTest, GlobalVarInitializerNoReturnValueBuiltin) {
// var a = storageBarrier();
auto* NoReturnValueBuiltin = Call(Source{{12, 34}}, "storageBarrier");
GlobalVar("a", nullptr, ast::StorageClass::kNone, NoReturnValueBuiltin);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: builtin 'storageBarrier' does not return a value");
}
TEST_F(ResolverVariableValidationTest, GlobalVarUsedAtModuleScope) {
// var<private> a : i32;
// var<private> b : i32 = a;