Unify fuzzer random number generation into a single class

BUG=tint:1098

Change-Id: I84931804515487d931bbbb5f0d5239d03ca76dfc
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/63300
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Alastair Donaldson <afdx@google.com>
This commit is contained in:
Ryan Harrison 2021-09-03 00:59:35 +00:00 committed by Tint LUCI CQ
parent 6a1eb45961
commit 5dc0ea7cce
26 changed files with 265 additions and 309 deletions

View File

@ -66,6 +66,8 @@ if (build_with_chromium) {
]
sources = [
"random_generator.cc",
"random_generator.h",
"tint_common_fuzzer.cc",
"tint_common_fuzzer.h",
]

View File

@ -17,6 +17,8 @@ function(add_tint_fuzzer NAME)
${NAME}.cc
cli.cc
cli.h
random_generator.cc
random_generator.h
tint_common_fuzzer.cc
tint_common_fuzzer.h
tint_init_fuzzer.cc

View File

@ -0,0 +1,89 @@
// 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.
#include "fuzzers/random_generator.h"
#include <algorithm>
#include <cassert>
#include <vector>
namespace tint {
namespace fuzzers {
namespace {
/// Generate integer from uniform distribution
/// @tparam I - integer type
/// @param engine - random number engine to use
/// @param lower - Lower bound of integer generated
/// @param upper - Upper bound of integer generated
/// @returns i, where lower <= i < upper
template <typename I>
I RandomUInt(std::mt19937* engine, I lower, I upper) {
assert(lower < upper && "|lower| must be stictly less than |upper|");
return std::uniform_int_distribution<I>(lower, upper - 1)(*engine);
}
} // namespace
RandomGenerator::RandomGenerator(uint32_t seed) : engine_(seed) {}
uint32_t RandomGenerator::GetUInt32(uint32_t lower, uint32_t upper) {
return RandomUInt(&engine_, lower, upper);
}
uint32_t RandomGenerator::GetUInt32(uint32_t bound) {
assert(bound > 0 && "|bound| must be greater than 0");
return RandomUInt(&engine_, 0u, bound);
}
uint64_t RandomGenerator::GetUInt64(uint64_t lower, uint64_t upper) {
return RandomUInt(&engine_, lower, upper);
}
uint64_t RandomGenerator::GetUInt64(uint64_t bound) {
assert(bound > 0 && "|bound| must be greater than 0");
return RandomUInt(&engine_, static_cast<uint64_t>(0), bound);
}
uint8_t RandomGenerator::GetByte() {
return std::independent_bits_engine<std::mt19937, 8, uint8_t>(engine_)();
}
uint32_t RandomGenerator::Get4Bytes() {
return std::independent_bits_engine<std::mt19937, 32, uint32_t>(engine_)();
}
std::vector<uint8_t> RandomGenerator::GetNBytes(size_t n) {
std::vector<uint8_t> result(n);
std::generate(
std::begin(result), std::end(result),
std::independent_bits_engine<std::mt19937, 8, uint8_t>(engine_));
return result;
}
bool RandomGenerator::GetBool() {
return RandomUInt(&engine_, 0u, 2u);
}
bool RandomGenerator::GetWeightedBool(uint32_t percentage) {
static const uint32_t kMaxPercentage = 100;
assert(percentage <= kMaxPercentage &&
"|percentage| needs to be within [0, 100]");
return RandomUInt(&engine_, 0u, kMaxPercentage) < percentage;
}
} // namespace fuzzers
} // namespace tint

View File

@ -0,0 +1,87 @@
// 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.
#ifndef FUZZERS_RANDOM_GENERATOR_H_
#define FUZZERS_RANDOM_GENERATOR_H_
#include <random>
#include <vector>
namespace tint {
namespace fuzzers {
/// Pseudo random generator utility class for fuzzing
class RandomGenerator {
public:
/// @brief Initializes the internal engine
/// @param seed - seed value passed to engine
explicit RandomGenerator(uint32_t seed);
~RandomGenerator() {}
/// Get uint32_t value from uniform distribution.
/// @param lower - lower bound of integer generated
/// @param upper - upper bound of integer generated
/// @returns i, where lower <= i < upper
uint32_t GetUInt32(uint32_t lower, uint32_t upper);
/// Get uint32_t value from uniform distribution.
/// @param bound - Upper bound of integer generated
/// @returns i, where 0 <= i < bound
uint32_t GetUInt32(uint32_t bound);
/// Get uint32_t value from uniform distribution.
/// @param lower - lower bound of integer generated
/// @param upper - upper bound of integer generated
/// @returns i, where lower <= i < upper
uint64_t GetUInt64(uint64_t lower, uint64_t upper);
/// Get uint64_t value from uniform distribution.
/// @param bound - Upper bound of integer generated
/// @returns i, where 0 <= i < bound
uint64_t GetUInt64(uint64_t bound);
/// Get 1 byte of pseudo-random data
/// Should be more efficient then calling GetNBytes(1);
/// @returns 1-byte of random data
uint8_t GetByte();
/// Get 4 bytes of pseudo-random data
/// Should be more efficient then calling GetNBytes(4);
/// @returns 4-bytes of random data
uint32_t Get4Bytes();
/// Get N bytes of pseudo-random data
/// @param n - number of bytes of data to generate
/// @returns |N|-bytes of random data as vector
std::vector<uint8_t> GetNBytes(size_t n);
/// Get random bool with even odds
/// @returns true 50% of the time and false %50 of time.
bool GetBool();
/// Get random bool with weighted odds
/// @param percentage - likelihood of true being returned
/// @returns true |percentage|% of the time, and false (100 - |percentage|)%
/// of the time.
bool GetWeightedBool(uint32_t percentage);
private:
std::mt19937 engine_;
}; // class RandomGenerator
} // namespace fuzzers
} // namespace tint
#endif // FUZZERS_RANDOM_GENERATOR_H_

View File

@ -42,8 +42,6 @@ if (build_with_chromium) {
"cli.cc",
"cli.h",
"fuzzer.cc",
"mt_rng.cc",
"mt_rng.h",
"mutation.cc",
"mutation.h",
"mutation_finder.cc",
@ -60,8 +58,6 @@ if (build_with_chromium) {
"probability_context.cc",
"probability_context.h",
"protobufs/tint_ast_fuzzer.h",
"random_number_generator.cc",
"random_number_generator.h",
"util.h",
]
}

View File

@ -35,7 +35,7 @@ add_custom_command(
COMMENT "Generate protobuf sources from proto definition file.")
set(LIBTINT_AST_FUZZER_SOURCES
mt_rng.h
../random_generator.h
mutation.h
mutation_finder.h
mutation_finders/replace_identifiers.h
@ -44,12 +44,11 @@ set(LIBTINT_AST_FUZZER_SOURCES
node_id_map.h
probability_context.h
protobufs/tint_ast_fuzzer.h
random_number_generator.h
util.h
${CMAKE_CURRENT_BINARY_DIR}/protobufs/tint_ast_fuzzer.pb.h)
set(LIBTINT_AST_FUZZER_SOURCES ${LIBTINT_AST_FUZZER_SOURCES}
mt_rng.cc
../random_generator.cc
mutation.cc
mutation_finder.cc
mutation_finders/replace_identifiers.cc
@ -57,7 +56,6 @@ set(LIBTINT_AST_FUZZER_SOURCES ${LIBTINT_AST_FUZZER_SOURCES}
mutator.cc
node_id_map.cc
probability_context.cc
random_number_generator.cc
${CMAKE_CURRENT_BINARY_DIR}/protobufs/tint_ast_fuzzer.pb.cc)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/protobufs/tint_ast_fuzzer.pb.cc PROPERTIES COMPILE_FLAGS -w)

View File

@ -15,8 +15,8 @@
#include <cstddef>
#include <cstdint>
#include "fuzzers/random_generator.h"
#include "fuzzers/tint_ast_fuzzer/cli.h"
#include "fuzzers/tint_ast_fuzzer/mt_rng.h"
#include "fuzzers/tint_ast_fuzzer/mutator.h"
#include "fuzzers/tint_ast_fuzzer/override_cli_params.h"
#include "fuzzers/tint_common_fuzzer.h"
@ -54,8 +54,8 @@ extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data,
}
// Run the mutator.
MtRng mt_rng(seed);
ProbabilityContext probability_context(&mt_rng);
RandomGenerator generator(seed);
ProbabilityContext probability_context(&generator);
program = Mutate(std::move(program), &probability_context,
cli_params.enable_all_mutations,
cli_params.mutation_batch_size, nullptr);

View File

@ -1,44 +0,0 @@
// 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.
#include "fuzzers/tint_ast_fuzzer/mt_rng.h"
#include <cassert>
namespace tint {
namespace fuzzers {
namespace ast_fuzzer {
namespace {
template <typename T>
T RandomUInt(std::mt19937* rng, T bound) {
assert(bound > 0 && "`bound` must be positive");
return std::uniform_int_distribution<T>(0, bound - 1)(*rng);
}
} // namespace
MtRng::MtRng(uint32_t seed) : rng_(seed) {}
uint32_t MtRng::RandomUint32(uint32_t bound) {
return RandomUInt(&rng_, bound);
}
uint64_t MtRng::RandomUint64(uint64_t bound) {
return RandomUInt(&rng_, bound);
}
} // namespace ast_fuzzer
} // namespace fuzzers
} // namespace tint

View File

@ -1,45 +0,0 @@
// 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.
#ifndef FUZZERS_TINT_AST_FUZZER_MT_RNG_H_
#define FUZZERS_TINT_AST_FUZZER_MT_RNG_H_
#include <random>
#include "fuzzers/tint_ast_fuzzer/random_number_generator.h"
namespace tint {
namespace fuzzers {
namespace ast_fuzzer {
/// The random number generator that uses STL's Mersenne Twister (std::mt19937)
/// under the hood.
class MtRng : public RandomNumberGenerator {
public:
/// @brief Initializes this RNG with some `seed`.
/// @param seed - passed down to the `std::mt19937`.
explicit MtRng(uint32_t seed);
uint32_t RandomUint32(uint32_t bound) override;
uint64_t RandomUint64(uint64_t bound) override;
private:
std::mt19937 rng_;
};
} // namespace ast_fuzzer
} // namespace fuzzers
} // namespace tint
#endif // FUZZERS_TINT_AST_FUZZER_MT_RNG_H_

View File

@ -16,7 +16,6 @@
#include "gtest/gtest.h"
#include "fuzzers/tint_ast_fuzzer/mt_rng.h"
#include "fuzzers/tint_ast_fuzzer/mutations/replace_identifier.h"
#include "fuzzers/tint_ast_fuzzer/mutator.h"
#include "fuzzers/tint_ast_fuzzer/probability_context.h"

View File

@ -20,7 +20,6 @@
#include "fuzzers/tint_ast_fuzzer/node_id_map.h"
#include "fuzzers/tint_ast_fuzzer/probability_context.h"
#include "fuzzers/tint_ast_fuzzer/protobufs/tint_ast_fuzzer.h"
#include "fuzzers/tint_ast_fuzzer/random_number_generator.h"
#include "src/program.h"

View File

@ -14,6 +14,8 @@
#include "fuzzers/tint_ast_fuzzer/probability_context.h"
#include <cassert>
namespace tint {
namespace fuzzers {
namespace ast_fuzzer {
@ -23,15 +25,18 @@ const std::pair<uint32_t, uint32_t> kChanceOfReplacingIdentifiers = {30, 70};
} // namespace
ProbabilityContext::ProbabilityContext(RandomNumberGenerator* rng)
: rng_(rng),
ProbabilityContext::ProbabilityContext(RandomGenerator* generator)
: generator_(generator),
chance_of_replacing_identifiers_(
RandomFromRange(kChanceOfReplacingIdentifiers)) {}
RandomFromRange(kChanceOfReplacingIdentifiers)) {
assert(generator != nullptr && "generator must not be nullptr");
}
uint32_t ProbabilityContext::RandomFromRange(
std::pair<uint32_t, uint32_t> range) {
assert(range.first <= range.second && "Range must be non-decreasing");
return range.first + rng_->RandomUint32(range.second - range.first + 1);
return generator_->GetUInt32(
range.first, range.second + 1); // + 1 need since range is inclusive.
}
} // namespace ast_fuzzer

View File

@ -18,7 +18,7 @@
#include <utility>
#include <vector>
#include "fuzzers/tint_ast_fuzzer/random_number_generator.h"
#include "fuzzers/random_generator.h"
namespace tint {
namespace fuzzers {
@ -29,16 +29,21 @@ namespace ast_fuzzer {
class ProbabilityContext {
public:
/// Initializes this instance with a random number generator.
/// @param rng - may not be a `nullptr`. Must remain in scope as long as this
/// @param generator - must not be a `nullptr`. Must remain in scope as long
/// as this
/// instance exists.
explicit ProbabilityContext(RandomNumberGenerator* rng);
explicit ProbabilityContext(RandomGenerator* generator);
/// @copydoc RandomNumberGenerator::RandomBool
bool RandomBool() { return rng_->RandomBool(); }
/// Get random bool with even odds
/// @returns true 50% of the time and false %50 of time.
bool RandomBool() { return generator_->GetBool(); }
/// @copydoc RandomNumberGenerator::ChoosePercentage
/// Get random bool with weighted odds
/// @param percentage - likelihood of true being returned
/// @returns true |percentage|% of the time, and false (100 - |percentage|)%
/// of the time.
bool ChoosePercentage(uint32_t percentage) {
return rng_->ChoosePercentage(percentage);
return generator_->GetWeightedBool(percentage);
}
/// Returns a random value in the range `[0; arr.size())`.
@ -47,7 +52,7 @@ class ProbabilityContext {
/// @return the random index in the `arr`.
template <typename T>
size_t GetRandomIndex(const std::vector<T>& arr) {
return static_cast<size_t>(rng_->RandomUint64(arr.size()));
return static_cast<size_t>(generator_->GetUInt64(arr.size()));
}
/// @return the probability of replacing some identifier with some other one.
@ -60,7 +65,7 @@ class ProbabilityContext {
/// @return an random number in the range `[a; b]`.
uint32_t RandomFromRange(std::pair<uint32_t, uint32_t> range);
RandomNumberGenerator* rng_;
RandomGenerator* generator_;
uint32_t chance_of_replacing_identifiers_;
};

View File

@ -1,37 +0,0 @@
// 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.
#include "fuzzers/tint_ast_fuzzer/random_number_generator.h"
namespace tint {
namespace fuzzers {
namespace ast_fuzzer {
RandomNumberGenerator::~RandomNumberGenerator() = default;
bool RandomNumberGenerator::RandomBool() {
return RandomUint32(2);
}
bool RandomNumberGenerator::ChoosePercentage(uint32_t percentage) {
assert(percentage <= 100 && "|percentage| is invalid");
// 100 is used as a bound instead of 101 because otherwise it would be
// possible to return `false` when `percentage == 100` holds. This would
// happen when the result of `RandomUint32` is 100 as well.
return RandomUint32(100) < percentage;
}
} // namespace ast_fuzzer
} // namespace fuzzers
} // namespace tint

View File

@ -1,57 +0,0 @@
// 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.
#ifndef FUZZERS_TINT_AST_FUZZER_RANDOM_NUMBER_GENERATOR_H_
#define FUZZERS_TINT_AST_FUZZER_RANDOM_NUMBER_GENERATOR_H_
#include <cassert>
#include <cstdint>
#include <vector>
namespace tint {
namespace fuzzers {
namespace ast_fuzzer {
/// Abstracts away the underlying algorithm that is used to generate random
/// numbers.
class RandomNumberGenerator {
public:
/// Virtual destructor.
virtual ~RandomNumberGenerator();
/// @brief Compute a random `uint32_t` value in the range `[0; bound)`.
/// @param bound - the upper exclusive bound for the computed integer
/// (must be positive).
/// @return the random number.
virtual uint32_t RandomUint32(uint32_t bound) = 0;
/// @brief Compute a random `uint64_t` value in the range `[0; bound)`.
/// @param bound - the upper exclusive bound for the computed integer
/// (must be positive).
/// @return the random number.
virtual uint64_t RandomUint64(uint64_t bound) = 0;
/// @return a randomly generated boolean value.
bool RandomBool();
/// @param percentage - must be in the range `[0; 100]`.
/// @return `true` with `percentage` probability.
bool ChoosePercentage(uint32_t percentage);
};
} // namespace ast_fuzzer
} // namespace fuzzers
} // namespace tint
#endif // FUZZERS_TINT_AST_FUZZER_RANDOM_NUMBER_GENERATOR_H_

View File

@ -21,7 +21,8 @@ function(add_tint_regex_fuzzer NAME)
endfunction()
set(LIBTINT_REGEX_FUZZER_SOURCES
util.h
../random_generator.cc
../random_generator.h
wgsl_mutator.cc
wgsl_mutator.h)

View File

@ -16,12 +16,11 @@
#include <cstddef>
#include <cstdint>
#include "fuzzers/random_generator.h"
#include "fuzzers/tint_common_fuzzer.h"
#include "fuzzers/tint_regex_fuzzer/cli.h"
#include "fuzzers/tint_regex_fuzzer/override_cli_params.h"
#include "fuzzers/tint_regex_fuzzer/util.h"
#include "fuzzers/tint_regex_fuzzer/wgsl_mutator.h"
#include "src/reader/wgsl/parser.h"
#include "src/writer/wgsl/generator.h"
@ -57,13 +56,13 @@ extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data,
unsigned seed) {
std::string wgsl_code(data, data + size);
const std::vector<std::string> delimiters{";"};
std::mt19937 generator(seed);
RandomGenerator generator(seed);
std::string delimiter =
delimiters[GetRandomIntFromRange(0, delimiters.size() - 1, generator)];
delimiters[generator.GetUInt64(delimiters.size() - 1u)];
MutationKind mutation_kind = static_cast<MutationKind>(GetRandomIntFromRange(
0, static_cast<size_t>(MutationKind::kNumMutationKinds) - 1, generator));
MutationKind mutation_kind = static_cast<MutationKind>(generator.GetUInt64(
static_cast<size_t>(MutationKind::kNumMutationKinds) - 1u));
switch (mutation_kind) {
case MutationKind::kSwapIntervals:

View File

@ -1,33 +0,0 @@
// 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.
#ifndef FUZZERS_TINT_REGEX_FUZZER_UTIL_H_
#define FUZZERS_TINT_REGEX_FUZZER_UTIL_H_
#include <random>
namespace tint {
namespace fuzzers {
namespace regex_fuzzer {
inline size_t GetRandomIntFromRange(size_t lower_bound,
size_t upper_bound,
std::mt19937& generator) {
std::uniform_int_distribution<size_t> dist(lower_bound, upper_bound);
return dist(generator);
}
} // namespace regex_fuzzer
} // namespace fuzzers
} // namespace tint
#endif // FUZZERS_TINT_REGEX_FUZZER_UTIL_H_

View File

@ -17,13 +17,12 @@
#include <cassert>
#include <cstring>
#include <map>
#include <random>
#include <regex>
#include <string>
#include <utility>
#include <vector>
#include "fuzzers/tint_regex_fuzzer/util.h"
#include "fuzzers/random_generator.h"
namespace tint {
namespace fuzzers {
@ -137,7 +136,7 @@ void ReplaceInterval(size_t start_index,
bool SwapRandomIntervals(const std::string& delimiter,
std::string& wgsl_code,
std::mt19937& generator) {
RandomGenerator& generator) {
std::vector<size_t> delimiter_positions =
FindDelimiterIndices(delimiter, wgsl_code);
@ -148,14 +147,10 @@ bool SwapRandomIntervals(const std::string& delimiter,
// When generating the i-th random number, we should make sure that there are
// at least (3-i) numbers greater than this number.
size_t ind1 =
GetRandomIntFromRange(0, delimiter_positions.size() - 3U, generator);
size_t ind2 = GetRandomIntFromRange(
ind1 + 1U, delimiter_positions.size() - 2U, generator);
size_t ind3 =
GetRandomIntFromRange(ind2, delimiter_positions.size() - 2U, generator);
size_t ind4 = GetRandomIntFromRange(
ind3 + 1U, delimiter_positions.size() - 1U, generator);
size_t ind1 = generator.GetUInt64(delimiter_positions.size() - 3u);
size_t ind2 = generator.GetUInt64(ind1 + 1u, delimiter_positions.size() - 2u);
size_t ind3 = generator.GetUInt64(ind2, delimiter_positions.size() - 2u);
size_t ind4 = generator.GetUInt64(ind3 + 1u, delimiter_positions.size() - 1u);
SwapIntervals(delimiter_positions[ind1],
delimiter_positions[ind2] - delimiter_positions[ind1],
@ -168,7 +163,7 @@ bool SwapRandomIntervals(const std::string& delimiter,
bool DeleteRandomInterval(const std::string& delimiter,
std::string& wgsl_code,
std::mt19937& generator) {
RandomGenerator& generator) {
std::vector<size_t> delimiter_positions =
FindDelimiterIndices(delimiter, wgsl_code);
@ -177,10 +172,8 @@ bool DeleteRandomInterval(const std::string& delimiter,
return false;
}
size_t ind1 =
GetRandomIntFromRange(0, delimiter_positions.size() - 2U, generator);
size_t ind2 = GetRandomIntFromRange(
ind1 + 1U, delimiter_positions.size() - 1U, generator);
size_t ind1 = generator.GetUInt64(delimiter_positions.size() - 2u);
size_t ind2 = generator.GetUInt64(ind1 + 1u, delimiter_positions.size() - 1u);
DeleteInterval(delimiter_positions[ind1],
delimiter_positions[ind2] - delimiter_positions[ind1],
@ -191,7 +184,7 @@ bool DeleteRandomInterval(const std::string& delimiter,
bool DuplicateRandomInterval(const std::string& delimiter,
std::string& wgsl_code,
std::mt19937& generator) {
RandomGenerator& generator) {
std::vector<size_t> delimiter_positions =
FindDelimiterIndices(delimiter, wgsl_code);
@ -200,13 +193,9 @@ bool DuplicateRandomInterval(const std::string& delimiter,
return false;
}
size_t ind1 =
GetRandomIntFromRange(0, delimiter_positions.size() - 2U, generator);
size_t ind2 = GetRandomIntFromRange(
ind1 + 1U, delimiter_positions.size() - 1U, generator);
size_t ind3 =
GetRandomIntFromRange(0, delimiter_positions.size() - 1U, generator);
size_t ind1 = generator.GetUInt64(delimiter_positions.size() - 2u);
size_t ind2 = generator.GetUInt64(ind1 + 1u, delimiter_positions.size() - 1u);
size_t ind3 = generator.GetUInt64(delimiter_positions.size() - 1u);
DuplicateInterval(delimiter_positions[ind1],
delimiter_positions[ind2] - delimiter_positions[ind1],
@ -215,7 +204,8 @@ bool DuplicateRandomInterval(const std::string& delimiter,
return true;
}
bool ReplaceRandomIdentifier(std::string& wgsl_code, std::mt19937& generator) {
bool ReplaceRandomIdentifier(std::string& wgsl_code,
RandomGenerator& generator) {
std::vector<std::pair<size_t, size_t>> identifiers =
GetIdentifiers(wgsl_code);
@ -224,15 +214,12 @@ bool ReplaceRandomIdentifier(std::string& wgsl_code, std::mt19937& generator) {
return false;
}
size_t id1_index =
GetRandomIntFromRange(0, identifiers.size() - 1U, generator);
size_t id2_index =
GetRandomIntFromRange(0, identifiers.size() - 1U, generator);
size_t id1_index = generator.GetUInt64(identifiers.size() - 1u);
size_t id2_index = generator.GetUInt64(identifiers.size() - 1u);
// The two identifiers must be different
while (id1_index == id2_index) {
id2_index = GetRandomIntFromRange(0, identifiers.size() - 1U, generator);
id2_index = generator.GetUInt64(identifiers.size() - 1u);
}
ReplaceRegion(identifiers[id1_index].first, identifiers[id1_index].second,
@ -242,7 +229,8 @@ bool ReplaceRandomIdentifier(std::string& wgsl_code, std::mt19937& generator) {
return true;
}
bool ReplaceRandomIntLiteral(std::string& wgsl_code, std::mt19937& generator) {
bool ReplaceRandomIntLiteral(std::string& wgsl_code,
RandomGenerator& generator) {
std::vector<std::pair<size_t, size_t>> literals = GetIntLiterals(wgsl_code);
// Need at least one integer literal
@ -250,14 +238,13 @@ bool ReplaceRandomIntLiteral(std::string& wgsl_code, std::mt19937& generator) {
return false;
}
size_t id1_index = GetRandomIntFromRange(0, literals.size() - 1U, generator);
size_t id1_index = generator.GetUInt64(literals.size() - 1u);
// INT_MAX = 2147483647, INT_MIN = -2147483648
std::vector<std::string> boundary_values = {
"2147483647", "-2147483648", "1", "-1", "0", "4294967295"};
size_t boundary_index =
GetRandomIntFromRange(0, boundary_values.size() - 1U, generator);
size_t boundary_index = generator.GetUInt64(boundary_values.size() - 1u);
ReplaceInterval(literals[id1_index].first, literals[id1_index].second,
boundary_values[boundary_index], wgsl_code);

View File

@ -15,11 +15,12 @@
#ifndef FUZZERS_TINT_REGEX_FUZZER_WGSL_MUTATOR_H_
#define FUZZERS_TINT_REGEX_FUZZER_WGSL_MUTATOR_H_
#include <random>
#include <string>
#include <utility>
#include <vector>
#include "fuzzers/random_generator.h"
namespace tint {
namespace fuzzers {
namespace regex_fuzzer {
@ -114,7 +115,7 @@ void ReplaceInterval(size_t start_index,
/// @return true if a swap happened or false otherwise.
bool SwapRandomIntervals(const std::string& delimiter,
std::string& wgsl_code,
std::mt19937& generator);
RandomGenerator& generator);
/// A function that, given a WGSL-like string and a delimiter,
/// generates another WGSL-like string by deleting a random
@ -125,7 +126,7 @@ bool SwapRandomIntervals(const std::string& delimiter,
/// @return true if a deletion happened or false otherwise.
bool DeleteRandomInterval(const std::string& delimiter,
std::string& wgsl_code,
std::mt19937& generator);
RandomGenerator& generator);
/// A function that, given a WGSL-like string and a delimiter,
/// generates another WGSL-like string by duplicating a random
@ -136,20 +137,22 @@ bool DeleteRandomInterval(const std::string& delimiter,
/// @return true if a duplication happened or false otherwise.
bool DuplicateRandomInterval(const std::string& delimiter,
std::string& wgsl_code,
std::mt19937& generator);
RandomGenerator& generator);
/// Replaces a randomly-chosen identifier in wgsl_code.
/// @param wgsl_code - WGSL-like string where the replacement will occur.
/// @param generator - the random number generator.
/// @return true if a replacement happened or false otherwise.
bool ReplaceRandomIdentifier(std::string& wgsl_code, std::mt19937& generator);
bool ReplaceRandomIdentifier(std::string& wgsl_code,
RandomGenerator& generator);
/// Replaces the value of a randomly-chosen integer with one of
/// the values in the set {INT_MAX, INT_MIN, 0, -1}.
/// @param wgsl_code - WGSL-like string where the replacement will occur.
/// @param generator - the random number generator.
/// @return true if a replacement happened or false otherwise.
bool ReplaceRandomIntLiteral(std::string& wgsl_code, std::mt19937& generator);
bool ReplaceRandomIntLiteral(std::string& wgsl_code,
RandomGenerator& generator);
} // namespace regex_fuzzer
} // namespace fuzzers

View File

@ -13,6 +13,7 @@
# limitations under the License.
set(FUZZER_SOURCES
../random_generator.cc
cli.cc
fuzzer.cc
mutator.cc
@ -23,6 +24,7 @@ set(FUZZER_SOURCES
util.cc)
set(FUZZER_SOURCES ${FUZZER_SOURCES}
../random_generator.h
cli.h
mutator.h
mutator_cache.h
@ -32,8 +34,8 @@ set(FUZZER_SOURCES ${FUZZER_SOURCES}
util.h)
set(FUZZER_SOURCES ${FUZZER_SOURCES}
../tint_common_fuzzer.h
../tint_common_fuzzer.cc)
../tint_common_fuzzer.cc
../tint_common_fuzzer.h)
function(configure_spirv_tools_fuzzer_target NAME SOURCES)
add_executable(${NAME} ${SOURCES})
@ -61,6 +63,7 @@ target_compile_definitions(tint_spirv_tools_fuzzer PRIVATE TARGET_FUZZER)
target_link_libraries(tint_spirv_tools_fuzzer libtint-fuzz)
set(DEBUGGER_SOURCES
../random_generator.cc
cli.cc
mutator.cc
mutator_debugger.cc
@ -70,6 +73,7 @@ set(DEBUGGER_SOURCES
util.cc)
set(DEBUGGER_SOURCES ${DEBUGGER_SOURCES}
../random_generator.h
cli.h
mutator.h
spirv_fuzz_mutator.h

View File

@ -14,10 +14,10 @@
#include <cassert>
#include <memory>
#include <random>
#include <string>
#include <vector>
#include "fuzzers/random_generator.h"
#include "fuzzers/tint_common_fuzzer.h"
#include "fuzzers/tint_spirv_tools_fuzzer/cli.h"
#include "fuzzers/tint_spirv_tools_fuzzer/mutator_cache.h"
@ -67,9 +67,8 @@ std::unique_ptr<Mutator> CreateMutator(const std::vector<uint32_t>& binary,
}
assert(!types.empty() && "At least one mutator type must be specified");
std::mt19937 rng(seed);
auto mutator_type =
types[std::uniform_int_distribution<size_t>(0, types.size() - 1)(rng)];
RandomGenerator generator(seed);
auto mutator_type = types[generator.GetUInt64(types.size())];
const auto& mutator_params = context->params.mutator_params;
switch (mutator_type) {

View File

@ -66,7 +66,7 @@ SpirvOptMutator::SpirvOptMutator(spv_target_env target_env,
optimized_binary_(),
validate_after_each_opt_(validate_after_each_opt),
opt_batch_size_(opt_batch_size),
rng_(seed) {
generator_(seed) {
assert(spvtools::SpirvTools(target_env).Validate(original_binary_) &&
"Initial binary is invalid");
assert(!opt_passes_.empty() && "Must be at least one pass");
@ -105,8 +105,7 @@ SpirvOptMutator::Result SpirvOptMutator::Mutate() {
std::vector<std::string> passes;
while (passes.size() < num_of_passes) {
auto idx = std::uniform_int_distribution<size_t>(
0, opt_passes_.size() - 1)(rng_);
auto idx = generator_.GetUInt64(opt_passes_.size());
passes.push_back(opt_passes_[idx]);
}

View File

@ -15,11 +15,11 @@
#ifndef FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_OPT_MUTATOR_H_
#define FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_OPT_MUTATOR_H_
#include <random>
#include <sstream>
#include <string>
#include <vector>
#include "fuzzers/random_generator.h"
#include "fuzzers/tint_spirv_tools_fuzzer/mutator.h"
#include "spirv-tools/libspirv.h"
@ -86,7 +86,7 @@ class SpirvOptMutator : public Mutator {
std::stringstream errors_;
// The random number generator initialized with `seed_`.
std::mt19937 rng_;
RandomGenerator generator_;
};
} // namespace spvtools_fuzzer

View File

@ -44,7 +44,7 @@ SpirvReduceMutator::SpirvReduceMutator(spv_target_env target_env,
bool validate_after_each_reduction)
: ir_context_(nullptr),
finders_(),
rng_(seed),
generator_(seed),
errors_(),
is_valid_(true),
reductions_batch_size_(reductions_batch_size),

View File

@ -16,12 +16,12 @@
#define FUZZERS_TINT_SPIRV_TOOLS_FUZZER_SPIRV_REDUCE_MUTATOR_H_
#include <memory>
#include <random>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "fuzzers/random_generator.h"
#include "fuzzers/tint_spirv_tools_fuzzer/mutator.h"
#include "source/reduce/reduction_opportunity_finder.h"
@ -65,7 +65,7 @@ class SpirvReduceMutator : public Mutator {
private:
template <typename T, typename... Args>
void MaybeAddFinder(Args&&... args) {
if (enable_all_reductions_ || std::uniform_int_distribution<>(0, 1)(rng_)) {
if (enable_all_reductions_ || generator_.GetBool()) {
finders_.push_back(std::make_unique<T>(std::forward<Args>(args)...));
}
}
@ -73,16 +73,14 @@ class SpirvReduceMutator : public Mutator {
template <typename T>
T* GetRandomElement(std::vector<T>* arr) {
assert(!arr->empty() && "Can't get random element from an empty vector");
auto index =
std::uniform_int_distribution<size_t>(0, arr->size() - 1)(rng_);
auto index = generator_.GetUInt64(arr->size());
return &(*arr)[index];
}
template <typename T>
T* GetRandomElement(std::vector<std::unique_ptr<T>>* arr) {
assert(!arr->empty() && "Can't get random element from an empty vector");
auto index =
std::uniform_int_distribution<size_t>(0, arr->size() - 1)(rng_);
auto index = generator_.GetUInt64(arr->size());
return (*arr)[index].get();
}
@ -97,7 +95,7 @@ class SpirvReduceMutator : public Mutator {
finders_;
// Random number generator initialized with `seed_`.
std::mt19937 rng_;
RandomGenerator generator_;
// All the errors produced by the reducer.
std::stringstream errors_;