Add SPIR-V Reader Fuzzer

Also clean up the mess I made of the build rules, so they actually work.

BUG=tint:57

Change-Id: I9c92d043a7be8f51ed7885a29eb153f078cc66d9
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/26125
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index b04d8c4..c2c957b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1157,16 +1157,32 @@
 if (build_with_chromium) {
   import("//testing/libfuzzer/fuzzer_test.gni")
 
-  fuzzer_test("tint_wgsl_reader_fuzzer") {
-    sources = [ "fuzzers/tint_wgsl_reader_fuzzer.cc" ]
+  # fuzzer_test doesn't have configs members, so need to define them in an empty
+  # source_set.
 
+  source_set("tint_fuzzer_common") {
     configs += [ ":tint_common_config" ]
     public_configs = [ ":tint_public_config" ]
+  }
 
-    deps = [
-      ":libtint_wgsl_reader_src",
-      ":tint_wgsl_reader_fuzzer_src",
-    ]
+  if (tint_build_wgsl_reader) {
+    fuzzer_test("tint_wgsl_reader_fuzzer") {
+      sources = [ "fuzzers/tint_wgsl_reader_fuzzer.cc" ]
+      deps = [
+        ":libtint_wgsl_reader_src",
+        ":tint_fuzzer_common",
+      ]
+    }
+  }
+
+  if (tint_build_spv_reader) {
+    fuzzer_test("tint_spv_reader_fuzzer") {
+      sources = [ "fuzzers/tint_spv_reader_fuzzer.cc" ]
+      deps = [
+        ":libtint_spv_reader_src",
+        ":tint_fuzzer_common",
+      ]
+    }
   }
 }
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a3cb4f8..79e8a41 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -212,11 +212,6 @@
 add_subdirectory(samples)
 
 if (${TINT_BUILD_FUZZERS})
-  # TODO(rharrison): Remove this check ones there are other fuzzers.
-  if (NOT ${TINT_BUILD_WGSL_READER})
-    message(ERROR, "Fuzzers require WGSL reader to be enabled")
-  endif()
-
   add_subdirectory(fuzzers)
 endif()
 
diff --git a/fuzzers/CMakeLists.txt b/fuzzers/CMakeLists.txt
index 2f0c7d5..90e3fb8 100644
--- a/fuzzers/CMakeLists.txt
+++ b/fuzzers/CMakeLists.txt
@@ -14,9 +14,9 @@
 
 function(add_tint_fuzzer NAME)
   add_executable(${NAME} ${NAME}.cc)
-  target_link_libraries(tint_fuzz libtint)
-  tint_default_compile_options(tint_fuzz)
-  target_link_options(tint_fuzz PRIVATE
+  target_link_libraries(${NAME} libtint)
+  tint_default_compile_options(${NAME})
+  target_link_options(${NAME} PRIVATE
     -fno-omit-frame-pointer
     -fsanitize=fuzzer,address,undefined
     -fsanitize-address-use-after-scope
@@ -30,6 +30,10 @@
   )
 endfunction()
 
-if ({TINT_BUILD_WGSL_READER})
+if (${TINT_BUILD_WGSL_READER})
   add_tint_fuzzer(tint_wgsl_reader_fuzzer)
 endif()
+
+if (${TINT_BUILD_SPV_READER})
+  add_tint_fuzzer(tint_spv_reader_fuzzer)
+endif()
diff --git a/fuzzers/tint_spv_reader_fuzzer.cc b/fuzzers/tint_spv_reader_fuzzer.cc
new file mode 100644
index 0000000..2498383
--- /dev/null
+++ b/fuzzers/tint_spv_reader_fuzzer.cc
@@ -0,0 +1,31 @@
+// 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 <vector>
+
+#include "src/reader/spirv/parser.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  size_t sizeInU32 = size / sizeof(uint32_t);
+  const uint32_t* u32Data = reinterpret_cast<const uint32_t*>(data);
+  std::vector<uint32_t> input(u32Data, u32Data + sizeInU32);
+
+  if (input.size() != 0) {
+    tint::Context ctx;
+    tint::reader::spirv::Parser parser(&ctx, input);
+    parser.Parse();
+  }
+
+  return 0;
+}