[Spirv] Fix Spirv Writer Fuzz by Validating Push Constant Blocks
This CL add validations about push constant blocks. It ensures
push constant block members offsets are valid and make sure there is
at most one user-declared push_constant
Bug:366291600,388654525,388592304
Change-Id: I274090f5eaeca8d30483197d0f99dae4ec1173eb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/221574
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/writer/writer_fuzz.cc b/src/tint/lang/spirv/writer/writer_fuzz.cc
index 9202b20..2323c72 100644
--- a/src/tint/lang/spirv/writer/writer_fuzz.cc
+++ b/src/tint/lang/spirv/writer/writer_fuzz.cc
@@ -59,13 +59,53 @@
}
// Check for unsupported module-scope variable address spaces and types.
+ // Also make sure there is at most one user-declared push_constant, and make a note of its size.
+ uint32_t user_push_constant_size = 0;
for (auto* inst : *module.root_block) {
auto* var = inst->As<core::ir::Var>();
auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
if (ptr->AddressSpace() == core::AddressSpace::kPixelLocal) {
return false;
}
+
+ if (ptr->AddressSpace() == core::AddressSpace::kPushConstant) {
+ if (user_push_constant_size > 0) {
+ // We've already seen a user-declared push constant.
+ return false;
+ }
+ user_push_constant_size = tint::RoundUp(4u, ptr->StoreType()->Size());
+ }
}
+
+ static constexpr uint32_t kMaxOffset = 0x1000;
+ Hashset<uint32_t, 4> push_constant_word_offsets;
+ auto check_push_constant_offset = [&](uint32_t offset) {
+ // Excessive values can cause OOM / timeouts when padding structures in the printer.
+ if (offset > kMaxOffset) {
+ return false;
+ }
+ // Offset must be 4-byte aligned.
+ if (offset & 0x3) {
+ return false;
+ }
+ // Offset must not have already been used.
+ if (!push_constant_word_offsets.Add(offset >> 2)) {
+ return false;
+ }
+ // Offset must be after the user-defined push constants.
+ if (offset < user_push_constant_size) {
+ return false;
+ }
+ return true;
+ };
+
+ if (options.depth_range_offsets) {
+ if (!check_push_constant_offset(options.depth_range_offsets->max) ||
+ !check_push_constant_offset(options.depth_range_offsets->min)) {
+ return false;
+ }
+ }
+
return true;
}