mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-05 06:03:34 +00:00
spv: reject invalid SPIR-V
Use the SPIRV-Tools validator, with the WebGPU0 environment. Bug: tint:3 Change-Id: Id1132d209fd939ed68587034761e97da9b35b21d Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/16821 Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
parent
1ae7c7dba9
commit
e5dc367a7e
@ -319,6 +319,7 @@ endif()
|
||||
if(${TINT_BUILD_SPV_PARSER})
|
||||
list (APPEND TINT_TEST_SRCS
|
||||
reader/spv/fail_stream_test.cc
|
||||
reader/spv/parser_impl_test.cc
|
||||
reader/spv/parser_test.cc
|
||||
)
|
||||
endif()
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "src/reader/spv/parser_impl.h"
|
||||
|
||||
namespace tint {
|
||||
@ -26,9 +27,33 @@ ParserImpl::ParserImpl(const std::vector<uint32_t>& spv_binary)
|
||||
ParserImpl::~ParserImpl() = default;
|
||||
|
||||
bool ParserImpl::Parse() {
|
||||
// Exit early if we've already failed.
|
||||
if (!success_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up use of SPIRV-Tools utilities.
|
||||
// TODO(dneto): Add option to handle other environments.
|
||||
spvtools::SpirvTools spv_tools(SPV_ENV_WEBGPU_0);
|
||||
|
||||
// Error messages from SPIRV-Tools are forwarded as failures.
|
||||
auto message_consumer =
|
||||
[this](spv_message_level_t level, const char* /*source*/,
|
||||
const spv_position_t& position, const char* message) {
|
||||
switch (level) {
|
||||
// Drop info and warning message.
|
||||
case SPV_MSG_WARNING:
|
||||
case SPV_MSG_INFO:
|
||||
default:
|
||||
// For binary validation errors, we only have the instruction
|
||||
// number. It's not text, so there is no column number.
|
||||
this->Fail() << "line:" << position.index << ": " << message;
|
||||
}
|
||||
};
|
||||
spv_tools.SetMessageConsumer(message_consumer);
|
||||
|
||||
// Only consider valid modules.
|
||||
if (success_) {
|
||||
Fail() << "SPIR-V parsing is not supported yet";
|
||||
success_ = spv_tools.Validate(spv_binary_);
|
||||
}
|
||||
|
||||
return success_;
|
||||
|
@ -33,6 +33,7 @@ class ParserImpl : Reader {
|
||||
/// Creates a new parser
|
||||
/// @param input the input data to parse
|
||||
explicit ParserImpl(const std::vector<uint32_t>& input);
|
||||
/// Destructor
|
||||
~ParserImpl() override;
|
||||
|
||||
/// Run the parser
|
||||
|
79
src/reader/spv/parser_impl_test.cc
Normal file
79
src/reader/spv/parser_impl_test.cc
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright 2020 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 "src/reader/spv/parser_impl.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace spv {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
using SpvParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(SpvParserImplTest, Uint32VecEmpty) {
|
||||
std::vector<uint32_t> data;
|
||||
ParserImpl p{data};
|
||||
EXPECT_FALSE(p.Parse());
|
||||
// TODO(dneto): What message?
|
||||
}
|
||||
|
||||
/// @returns the SPIR-V module assembled from the given text. Numeric IDs
|
||||
/// are preserved.
|
||||
std::vector<uint32_t> Assemble(const std::string& spirv_assembly) {
|
||||
// TODO(dneto): Use ScopedTrace?
|
||||
|
||||
// (The target environment doesn't affect assembly.
|
||||
spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
|
||||
std::stringstream errors;
|
||||
std::vector<uint32_t> result;
|
||||
tools.SetMessageConsumer([&errors](spv_message_level_t, const char*,
|
||||
const spv_position_t& position,
|
||||
const char* message) {
|
||||
errors << "assembly error:" << position.line << ":" << position.column
|
||||
<< ": " << message;
|
||||
});
|
||||
|
||||
const auto success = tools.Assemble(
|
||||
spirv_assembly, &result, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
EXPECT_TRUE(success) << errors.str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST_F(SpvParserImplTest, InvalidModuleFails) {
|
||||
auto invalid_spv = Assemble("%ty = OpTypeInt 3 0");
|
||||
ParserImpl p{invalid_spv};
|
||||
EXPECT_FALSE(p.Parse());
|
||||
EXPECT_THAT(
|
||||
p.error(),
|
||||
HasSubstr("TypeInt cannot appear before the memory model instruction"));
|
||||
EXPECT_THAT(p.error(), HasSubstr("OpTypeInt 3 0"));
|
||||
}
|
||||
|
||||
// TODO(dneto): uint32 vec, valid SPIR-V
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace spv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
@ -14,8 +14,7 @@
|
||||
|
||||
#include "src/reader/spv/parser.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user