mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2025-01-12 09:20:15 +00:00
Validate that SPIR-V binary is encoded as little endian for WebGPU (#2523)
Fixes #2522
This commit is contained in:
parent
3aad3e9228
commit
21712068fe
@ -281,6 +281,12 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
|
||||
<< "Invalid SPIR-V magic number.";
|
||||
}
|
||||
|
||||
if (spvIsWebGPUEnv(context.target_env) && endian != SPV_ENDIANNESS_LITTLE) {
|
||||
return DiagnosticStream(position, context.consumer, "",
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "WebGPU requires SPIR-V to be little endian.";
|
||||
}
|
||||
|
||||
spv_header_t header;
|
||||
if (spvBinaryHeaderGet(binary.get(), endian, &header)) {
|
||||
return DiagnosticStream(position, context.consumer, "",
|
||||
|
@ -276,6 +276,63 @@ TEST_F(ValidateWebGPU, NonVulkanKHRMemoryModelExtensionBad) {
|
||||
"\"SPV_KHR_8bit_storage\"\n"));
|
||||
}
|
||||
|
||||
spv_binary GenerateTrivialBinary(bool need_little_endian) {
|
||||
// Smallest possible valid WebGPU SPIR-V binary in little endian. Contains all
|
||||
// the required boilerplate and a trivial entry point function.
|
||||
static const uint8_t binary_bytes[] = {
|
||||
// clang-format off
|
||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00,
|
||||
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0xE1, 0x14, 0x00, 0x00,
|
||||
0x0A, 0x00, 0x08, 0x00, 0x53, 0x50, 0x56, 0x5F, 0x4B, 0x48, 0x52, 0x5F,
|
||||
0x76, 0x75, 0x6C, 0x6B, 0x61, 0x6E, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72,
|
||||
0x79, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x6C, 0x00, 0x0E, 0x00, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x05, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x68, 0x61, 0x64,
|
||||
0x65, 0x72, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
|
||||
// clang-format on
|
||||
};
|
||||
static const size_t word_count = sizeof(binary_bytes) / sizeof(uint32_t);
|
||||
std::unique_ptr<spv_binary_t> result(new spv_binary_t);
|
||||
if (!result) return nullptr;
|
||||
|
||||
result->wordCount = word_count;
|
||||
result->code = new uint32_t[word_count];
|
||||
if (!result->code) return nullptr;
|
||||
|
||||
if (need_little_endian) {
|
||||
memcpy(result->code, binary_bytes, sizeof(binary_bytes));
|
||||
} else {
|
||||
uint8_t* code_bytes = reinterpret_cast<uint8_t*>(result->code);
|
||||
for (size_t word = 0; word < word_count; ++word) {
|
||||
code_bytes[4 * word] = binary_bytes[4 * word + 3];
|
||||
code_bytes[4 * word + 1] = binary_bytes[4 * word + 2];
|
||||
code_bytes[4 * word + 2] = binary_bytes[4 * word + 1];
|
||||
code_bytes[4 * word + 3] = binary_bytes[4 * word];
|
||||
}
|
||||
}
|
||||
|
||||
return result.release();
|
||||
}
|
||||
|
||||
TEST_F(ValidateWebGPU, LittleEndianGood) {
|
||||
DestroyBinary();
|
||||
binary_ = GenerateTrivialBinary(true);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
|
||||
}
|
||||
|
||||
TEST_F(ValidateWebGPU, BigEndianBad) {
|
||||
DestroyBinary();
|
||||
binary_ = GenerateTrivialBinary(false);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("WebGPU requires SPIR-V to be little endian."));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
Loading…
Reference in New Issue
Block a user