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>
This commit is contained in:
Alastair Donaldson 2021-07-20 20:56:30 +00:00 committed by Tint LUCI CQ
parent 33afd6ce97
commit 0c7332b2ba
2 changed files with 18 additions and 3 deletions

View File

@ -187,7 +187,6 @@ int CommonFuzzer::Run(const uint8_t* data, size_t size) {
#if TINT_BUILD_SPV_READER #if TINT_BUILD_SPV_READER
std::vector<uint32_t> spirv_input(size / sizeof(uint32_t)); 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 #endif // TINT_BUILD_SPV_READER
@ -202,9 +201,16 @@ int CommonFuzzer::Run(const uint8_t* data, size_t size) {
#endif // TINT_BUILD_WGSL_READER #endif // TINT_BUILD_WGSL_READER
#if TINT_BUILD_SPV_READER #if TINT_BUILD_SPV_READER
case InputFormat::kSpv: { case InputFormat::kSpv: {
if (!spirv_input.empty()) { // `spirv_input` has been initialized with the capacity to store `size /
program = reader::spirv::Parse(spirv_input); // 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; break;
} }
#endif // TINT_BUILD_SPV_READER #endif // TINT_BUILD_SPV_READER

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <cassert>
#include <memory> #include <memory>
#include <random> #include <random>
#include <string> #include <string>
@ -99,6 +100,10 @@ extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data,
size_t size, size_t size,
size_t max_size, size_t max_size,
unsigned seed) { 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::vector<uint32_t> binary(size / sizeof(uint32_t));
std::memcpy(binary.data(), data, size); std::memcpy(binary.data(), data, size);
@ -169,6 +174,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
return 0; 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); CommonFuzzer spv_to_wgsl(InputFormat::kSpv, OutputFormat::kWGSL);
spv_to_wgsl.EnableInspector(); spv_to_wgsl.EnableInspector();
spv_to_wgsl.Run(data, size); spv_to_wgsl.Run(data, size);