SPIR-V Tools fuzzer: check binary size

Adds assertions to check that the SPIR-V Tools fuzzer is not
inadvertently applied to SPIR-V binaries of an invalid size, which
guards against the fuzzer being run in a misconfigured fashion.

The CL also moves a memcpy that populates a SPIR-V binary buffer so
that the memcpy only happens when the input really is SPIR-V. This
avoids frequent redundant memory copies when fuzzing WGSL.

Change-Id: Iafccaa107ff34941d8878ed5be72a2e6d38d0f49
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58386
Auto-Submit: Alastair Donaldson <afdx@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Alastair Donaldson <afdx@google.com>
diff --git a/fuzzers/tint_common_fuzzer.cc b/fuzzers/tint_common_fuzzer.cc
index 153cf8f..88f0107 100644
--- a/fuzzers/tint_common_fuzzer.cc
+++ b/fuzzers/tint_common_fuzzer.cc
@@ -187,7 +187,6 @@
 
 #if TINT_BUILD_SPV_READER
   std::vector<uint32_t> spirv_input(size / sizeof(uint32_t));
-  std::memcpy(spirv_input.data(), data, spirv_input.size() * sizeof(uint32_t));
 
 #endif  // TINT_BUILD_SPV_READER
 
@@ -202,9 +201,16 @@
 #endif  // TINT_BUILD_WGSL_READER
 #if TINT_BUILD_SPV_READER
     case InputFormat::kSpv: {
-      if (!spirv_input.empty()) {
-        program = reader::spirv::Parse(spirv_input);
+      // `spirv_input` has been initialized with the capacity to store `size /
+      // sizeof(uint32_t)` uint32_t values. If `size` is not a multiple of
+      // sizeof(uint32_t) then not all of `data` can be copied into
+      // `spirv_input`, and any trailing bytes are discarded.
+      const size_t adjusted_size = (size / sizeof(uint32_t)) * sizeof(uint32_t);
+      std::memcpy(spirv_input.data(), data, adjusted_size);
+      if (spirv_input.empty()) {
+        return 0;
       }
+      program = reader::spirv::Parse(spirv_input);
       break;
     }
 #endif  // TINT_BUILD_SPV_READER
diff --git a/fuzzers/tint_spirv_tools_fuzzer/fuzzer.cc b/fuzzers/tint_spirv_tools_fuzzer/fuzzer.cc
index c1b3d64..29af73b 100644
--- a/fuzzers/tint_spirv_tools_fuzzer/fuzzer.cc
+++ b/fuzzers/tint_spirv_tools_fuzzer/fuzzer.cc
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <cassert>
 #include <memory>
 #include <random>
 #include <string>
@@ -99,6 +100,10 @@
                                           size_t size,
                                           size_t max_size,
                                           unsigned seed) {
+  assert((size % 4) == 0 &&
+         "A valid SPIR-V binary's size must be a multiple of 4, and the "
+         "SPIR-V Tools fuzzer should only work with valid binaries.");
+
   std::vector<uint32_t> binary(size / sizeof(uint32_t));
   std::memcpy(binary.data(), data, size);
 
@@ -169,6 +174,10 @@
     return 0;
   }
 
+  assert((size % 4) == 0 &&
+         "A valid SPIR-V binary's size is a multiple of 4 bytes, and the "
+         "SPIR-V Tools fuzzer should only work with valid binaries.");
+
   CommonFuzzer spv_to_wgsl(InputFormat::kSpv, OutputFormat::kWGSL);
   spv_to_wgsl.EnableInspector();
   spv_to_wgsl.Run(data, size);