2021-07-28 11:11:26 +00:00
|
|
|
// Copyright 2021 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.
|
|
|
|
|
2021-07-29 15:40:57 +00:00
|
|
|
#include <cassert>
|
2021-07-28 11:11:26 +00:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
|
2021-09-03 00:59:35 +00:00
|
|
|
#include "fuzzers/random_generator.h"
|
2021-07-28 11:11:26 +00:00
|
|
|
#include "fuzzers/tint_common_fuzzer.h"
|
|
|
|
#include "fuzzers/tint_regex_fuzzer/cli.h"
|
2021-08-31 22:07:17 +00:00
|
|
|
#include "fuzzers/tint_regex_fuzzer/override_cli_params.h"
|
2021-07-28 11:11:26 +00:00
|
|
|
#include "fuzzers/tint_regex_fuzzer/wgsl_mutator.h"
|
2021-10-05 19:19:26 +00:00
|
|
|
#include "fuzzers/transform_builder.h"
|
2021-07-28 11:11:26 +00:00
|
|
|
#include "src/reader/wgsl/parser.h"
|
|
|
|
#include "src/writer/wgsl/generator.h"
|
|
|
|
|
|
|
|
namespace tint {
|
|
|
|
namespace fuzzers {
|
|
|
|
namespace regex_fuzzer {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
CliParams cli_params{};
|
|
|
|
|
2021-07-29 15:40:57 +00:00
|
|
|
enum class MutationKind {
|
|
|
|
kSwapIntervals,
|
|
|
|
kDeleteInterval,
|
|
|
|
kDuplicateInterval,
|
2021-08-05 22:24:20 +00:00
|
|
|
kReplaceIdentifier,
|
|
|
|
kReplaceLiteral,
|
2021-09-28 14:57:54 +00:00
|
|
|
kInsertReturnStatement,
|
2021-07-29 15:40:57 +00:00
|
|
|
kNumMutationKinds
|
|
|
|
};
|
|
|
|
|
2021-07-28 11:11:26 +00:00
|
|
|
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
|
|
|
// Parse CLI parameters. `ParseCliParams` will call `exit` if some parameter
|
|
|
|
// is invalid.
|
|
|
|
cli_params = ParseCliParams(argc, *argv);
|
2021-08-31 22:07:17 +00:00
|
|
|
// For some fuzz targets it is desirable to force the values of certain CLI
|
|
|
|
// parameters after parsing.
|
|
|
|
OverrideCliParams(cli_params);
|
2021-07-28 11:11:26 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data,
|
|
|
|
size_t size,
|
|
|
|
size_t max_size,
|
|
|
|
unsigned seed) {
|
2021-07-29 15:40:57 +00:00
|
|
|
std::string wgsl_code(data, data + size);
|
2021-07-28 11:11:26 +00:00
|
|
|
const std::vector<std::string> delimiters{";"};
|
2021-09-03 00:59:35 +00:00
|
|
|
RandomGenerator generator(seed);
|
2021-07-29 15:40:57 +00:00
|
|
|
|
2021-08-02 20:56:39 +00:00
|
|
|
std::string delimiter =
|
2021-09-21 16:16:58 +00:00
|
|
|
delimiters[generator.GetUInt32(static_cast<uint32_t>(delimiters.size()))];
|
2021-08-02 20:56:39 +00:00
|
|
|
|
2021-09-21 16:16:58 +00:00
|
|
|
MutationKind mutation_kind = static_cast<MutationKind>(generator.GetUInt32(
|
|
|
|
static_cast<uint32_t>(MutationKind::kNumMutationKinds)));
|
2021-07-29 15:40:57 +00:00
|
|
|
|
|
|
|
switch (mutation_kind) {
|
|
|
|
case MutationKind::kSwapIntervals:
|
|
|
|
if (!SwapRandomIntervals(delimiter, wgsl_code, generator)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MutationKind::kDeleteInterval:
|
|
|
|
if (!DeleteRandomInterval(delimiter, wgsl_code, generator)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MutationKind::kDuplicateInterval:
|
|
|
|
if (!DuplicateRandomInterval(delimiter, wgsl_code, generator)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-08-05 22:24:20 +00:00
|
|
|
case MutationKind::kReplaceIdentifier:
|
|
|
|
if (!ReplaceRandomIdentifier(wgsl_code, generator)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MutationKind::kReplaceLiteral:
|
|
|
|
if (!ReplaceRandomIntLiteral(wgsl_code, generator)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-09-28 14:57:54 +00:00
|
|
|
case MutationKind::kInsertReturnStatement:
|
|
|
|
if (!InsertReturnStatement(wgsl_code, generator)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-07-29 15:40:57 +00:00
|
|
|
default:
|
|
|
|
assert(false && "Unreachable");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wgsl_code.size() > max_size) {
|
|
|
|
return 0;
|
|
|
|
}
|
2021-07-28 11:11:26 +00:00
|
|
|
|
2021-07-29 15:40:57 +00:00
|
|
|
memcpy(data, wgsl_code.c_str(), wgsl_code.size());
|
|
|
|
return wgsl_code.size();
|
2021-07-28 11:11:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|
|
|
if (size == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Target {
|
|
|
|
FuzzingTarget fuzzing_target;
|
|
|
|
OutputFormat output_format;
|
|
|
|
const char* name;
|
|
|
|
};
|
|
|
|
|
|
|
|
Target targets[] = {{FuzzingTarget::kWgsl, OutputFormat::kWGSL, "WGSL"},
|
|
|
|
{FuzzingTarget::kHlsl, OutputFormat::kHLSL, "HLSL"},
|
|
|
|
{FuzzingTarget::kMsl, OutputFormat::kMSL, "MSL"},
|
|
|
|
{FuzzingTarget::kSpv, OutputFormat::kSpv, "SPV"}};
|
|
|
|
|
|
|
|
for (auto target : targets) {
|
|
|
|
if ((target.fuzzing_target & cli_params.fuzzing_target) !=
|
|
|
|
target.fuzzing_target) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-10-05 19:19:26 +00:00
|
|
|
TransformBuilder tb(data, size);
|
|
|
|
tb.AddTransform<tint::transform::Robustness>();
|
2021-08-11 13:02:45 +00:00
|
|
|
|
2021-07-28 11:11:26 +00:00
|
|
|
CommonFuzzer fuzzer(InputFormat::kWGSL, target.output_format);
|
|
|
|
fuzzer.EnableInspector();
|
2021-10-05 19:19:26 +00:00
|
|
|
fuzzer.SetTransformManager(tb.manager(), tb.data_map());
|
2021-08-11 13:02:45 +00:00
|
|
|
|
2021-07-28 11:11:26 +00:00
|
|
|
fuzzer.Run(data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
} // namespace regex_fuzzer
|
|
|
|
} // namespace fuzzers
|
|
|
|
} // namespace tint
|