Regex fuzzer: replace the value of an integer with
a value in the set {INT_MAX, INT_MIN, -1 or 0}.
A mutation that replaces the value of a randomly-chosen integer with a value
in the set {INT_MAX, INT_MIN, -1, 0}.
Fixes: tint:1093.
Change-Id: I5ec69e1813785760ed6e7b06d0cbd9c481f69ade
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/60920
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Alastair Donaldson <afdx@google.com>
Commit-Queue: Alastair Donaldson <afdx@google.com>
diff --git a/fuzzers/tint_regex_fuzzer/fuzzer.cc b/fuzzers/tint_regex_fuzzer/fuzzer.cc
index cc87cf5..57eecff 100644
--- a/fuzzers/tint_regex_fuzzer/fuzzer.cc
+++ b/fuzzers/tint_regex_fuzzer/fuzzer.cc
@@ -35,6 +35,8 @@
kSwapIntervals,
kDeleteInterval,
kDuplicateInterval,
+ kReplaceIdentifier,
+ kReplaceLiteral,
kNumMutationKinds
};
@@ -78,6 +80,18 @@
}
break;
+ case MutationKind::kReplaceIdentifier:
+ if (!ReplaceRandomIdentifier(wgsl_code, generator)) {
+ return 0;
+ }
+ break;
+
+ case MutationKind::kReplaceLiteral:
+ if (!ReplaceRandomIntLiteral(wgsl_code, generator)) {
+ return 0;
+ }
+ break;
+
default:
assert(false && "Unreachable");
return 0;
diff --git a/fuzzers/tint_regex_fuzzer/regex_fuzzer_tests.cc b/fuzzers/tint_regex_fuzzer/regex_fuzzer_tests.cc
index 252958c..94fe68f 100644
--- a/fuzzers/tint_regex_fuzzer/regex_fuzzer_tests.cc
+++ b/fuzzers/tint_regex_fuzzer/regex_fuzzer_tests.cc
@@ -226,6 +226,40 @@
ASSERT_EQ(ground_truth, identifiers_pos);
}
+TEST(TestGetLiteralsValues, TestGetLiteralsValues1) {
+ std::string wgsl_code =
+ "fn clamp_0acf8f() {"
+ "var res: vec2<f32> = clamp(vec2<f32>(), vec2<f32>(), vec2<f32>());}"
+ "[[stage(vertex)]]"
+ "fn vertex_main() -> [[builtin(position)]] vec4<f32> {"
+ " clamp_0acf8f();"
+ "var foo_1: i32 = 3;"
+ " return vec4<f32>();}"
+ "[[stage(fragment)]]"
+ "fn fragment_main() {"
+ " clamp_0acf8f();}"
+ "[[stage(compute), workgroup_size(1)]]"
+ "fn compute_main() {"
+ "var<private> foo: f32 = 0.0;"
+ "var foo_2: i32 = 10;"
+ " clamp_0acf8f();}"
+ "foo_1 = 5 + 7;"
+ "var foo_3 : i32 = -20;";
+
+ std::vector<std::pair<size_t, size_t>> literals_pos =
+ GetIntLiterals(wgsl_code);
+
+ std::vector<std::string> ground_truth = {"3", "10", "5", "7", "-20"};
+
+ std::vector<std::string> result;
+
+ for (auto pos : literals_pos) {
+ result.push_back(wgsl_code.substr(pos.first, pos.second));
+ }
+
+ ASSERT_EQ(ground_truth, result);
+}
+
} // namespace
} // namespace regex_fuzzer
} // namespace fuzzers
diff --git a/fuzzers/tint_regex_fuzzer/wgsl_mutator.cc b/fuzzers/tint_regex_fuzzer/wgsl_mutator.cc
index cb1f850..2745001 100644
--- a/fuzzers/tint_regex_fuzzer/wgsl_mutator.cc
+++ b/fuzzers/tint_regex_fuzzer/wgsl_mutator.cc
@@ -67,6 +67,29 @@
return result;
}
+std::vector<std::pair<size_t, size_t>> GetIntLiterals(const std::string& s) {
+ std::vector<std::pair<size_t, size_t>> result;
+
+ // Looks for integer literals in decimal or hexadecimal form.
+ // Regex obtained here: https://www.w3.org/TR/WGSL/#literals
+ std::regex int_literal_regex("-?0x[0-9a-fA-F]+ | 0 | -?[1-9][0-9]*");
+ std::regex uint_literal_regex("0x[0-9a-fA-F]+u | 0u | [1-9][0-9]*u");
+ std::smatch match;
+
+ std::string::const_iterator search_start(s.cbegin());
+ std::string prefix = "";
+
+ while (regex_search(search_start, s.cend(), match, int_literal_regex) ||
+ regex_search(search_start, s.cend(), match, uint_literal_regex)) {
+ prefix += match.prefix();
+ result.push_back(
+ std::make_pair(prefix.size() + 1, match.str(0).size() - 1));
+ prefix += match.str(0);
+ search_start = match.suffix().first;
+ }
+ return result;
+}
+
void SwapIntervals(size_t idx1,
size_t reg1_len,
size_t idx2,
@@ -76,7 +99,7 @@
std::string region_2 = wgsl_code.substr(idx2 + 1, reg2_len - 1);
- // The second transformation is done first as it doesn't affect ind1 and ind2
+ // The second transformation is done first as it doesn't affect idx2.
wgsl_code.replace(idx2 + 1, region_2.size(), region_1);
wgsl_code.replace(idx1 + 1, region_1.size(), region_2);
@@ -104,6 +127,14 @@
wgsl_code.replace(idx2, region_2.size(), region_1);
}
+void ReplaceInterval(size_t start_index,
+ size_t length,
+ std::string replacement_text,
+ std::string& wgsl_code) {
+ std::string region_1 = wgsl_code.substr(start_index, length);
+ wgsl_code.replace(start_index, length, replacement_text);
+}
+
bool SwapRandomIntervals(const std::string& delimiter,
std::string& wgsl_code,
std::mt19937& generator) {
@@ -211,6 +242,29 @@
return true;
}
+bool ReplaceRandomIntLiteral(std::string& wgsl_code, std::mt19937& generator) {
+ std::vector<std::pair<size_t, size_t>> literals = GetIntLiterals(wgsl_code);
+
+ // Need at least one integer literal
+ if (literals.size() < 1) {
+ return false;
+ }
+
+ size_t id1_index = GetRandomIntFromRange(0, literals.size() - 1U, generator);
+
+ // 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);
+
+ ReplaceInterval(literals[id1_index].first, literals[id1_index].second,
+ boundary_values[boundary_index], wgsl_code);
+
+ return true;
+}
+
} // namespace regex_fuzzer
} // namespace fuzzers
} // namespace tint
diff --git a/fuzzers/tint_regex_fuzzer/wgsl_mutator.h b/fuzzers/tint_regex_fuzzer/wgsl_mutator.h
index bd7975b..1af6b02 100644
--- a/fuzzers/tint_regex_fuzzer/wgsl_mutator.h
+++ b/fuzzers/tint_regex_fuzzer/wgsl_mutator.h
@@ -39,6 +39,15 @@
std::vector<std::pair<size_t, size_t>> GetIdentifiers(
const std::string& wgsl_code);
+/// A function that returns returns the starting position
+/// and the length of all the integer literals in a WGSL-like string.
+/// @param wgsl_code - the WGSL-like string where the int literals
+/// will be found.
+/// @return a vector with the starting positions and the length
+/// of all the integer literals.
+std::vector<std::pair<size_t, size_t>> GetIntLiterals(
+ const std::string& wgsl_code);
+
/// Given 4 indices, idx1, idx2, idx3 and idx4 it swaps the regions
/// in the interval (idx1, idx2] with the region in the interval (idx3, idx4]
/// in wgsl_text.
@@ -74,16 +83,28 @@
/// Replaces a region of a WGSL-like string of length id2_len starting
/// at position idx2 with a region of length id1_len starting at
/// position idx1.
-/// @param idx1 - starting position of the first region.
-/// @param id1_len - length of the first region.
-/// @param idx2 - starting position of the second region.
-/// @param id2_len - length of the second region.
+/// @param idx1 - starting position of the first region.
+/// @param id1_len - length of the first region.
+/// @param idx2 - starting position of the second region.
+/// @param id2_len - length of the second region.
+/// @param wgsl_code - the string where the replacement will occur.
void ReplaceRegion(size_t idx1,
size_t id1_len,
size_t idx2,
size_t id2_len,
std::string& wgsl_code);
+/// Replaces an interval of length interval1_len starting at start_index
+/// with the interval interval2.
+/// @param start_index - starting position of the interval to be replaced.
+/// @param interval1_len - length of the interval to be replaced.
+/// @param replacement_text - the interval that will be used as a replacement.
+/// @param wgsl_code - the WGSL-like string where the replacement will occur.
+void ReplaceInterval(size_t start_index,
+ size_t length,
+ std::string replacement_text,
+ std::string& wgsl_code);
+
/// A function that, given WGSL-like string and a delimiter,
/// generates another WGSL-like string by picking two random regions
/// enclosed by the delimiter and swapping them.
@@ -117,13 +138,19 @@
std::string& wgsl_code,
std::mt19937& generator);
-/// Replaces a random identifier in wgsl_code.
+/// 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);
+/// 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);
+
} // namespace regex_fuzzer
} // namespace fuzzers
} // namespace tint