1 // Copyright (c) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "source/fuzz/fuzzer_context.h"
16
17 #include <cmath>
18
19 namespace spvtools {
20 namespace fuzz {
21
22 namespace {
23 // Default <minimum, maximum> pairs of probabilities for applying various
24 // transformations. All values are percentages. Keep them in alphabetical order.
25
26 const std::pair<uint32_t, uint32_t> kChanceOfAddingAccessChain = {5, 50};
27 const std::pair<uint32_t, uint32_t> kChanceOfAddingAnotherStructField = {20,
28 90};
29 const std::pair<uint32_t, uint32_t> kChanceOfAddingArrayOrStructType = {20, 90};
30 const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadBlock = {20, 90};
31 const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadBreak = {5, 80};
32 const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadContinue = {5, 80};
33 const std::pair<uint32_t, uint32_t> kChanceOfAddingEquationInstruction = {5,
34 90};
35 const std::pair<uint32_t, uint32_t> kChanceOfAddingGlobalVariable = {20, 90};
36 const std::pair<uint32_t, uint32_t> kChanceOfAddingLoad = {5, 50};
37 const std::pair<uint32_t, uint32_t> kChanceOfAddingLocalVariable = {20, 90};
38 const std::pair<uint32_t, uint32_t> kChanceOfAddingMatrixType = {20, 70};
39 const std::pair<uint32_t, uint32_t> kChanceOfAddingNoContractionDecoration = {
40 5, 70};
41 const std::pair<uint32_t, uint32_t> kChanceOfAddingStore = {5, 50};
42 const std::pair<uint32_t, uint32_t> kChanceOfAddingVectorType = {20, 70};
43 const std::pair<uint32_t, uint32_t> kChanceOfAdjustingFunctionControl = {20,
44 70};
45 const std::pair<uint32_t, uint32_t> kChanceOfAdjustingLoopControl = {20, 90};
46 const std::pair<uint32_t, uint32_t> kChanceOfAdjustingMemoryOperandsMask = {20,
47 90};
48 const std::pair<uint32_t, uint32_t> kChanceOfAdjustingSelectionControl = {20,
49 90};
50 const std::pair<uint32_t, uint32_t> kChanceOfCallingFunction = {1, 10};
51 const std::pair<uint32_t, uint32_t> kChanceOfChoosingStructTypeVsArrayType = {
52 20, 80};
53 const std::pair<uint32_t, uint32_t> kChanceOfConstructingComposite = {20, 50};
54 const std::pair<uint32_t, uint32_t> kChanceOfCopyingObject = {20, 50};
55 const std::pair<uint32_t, uint32_t> kChanceOfDonatingAdditionalModule = {5, 50};
56 const std::pair<uint32_t, uint32_t> kChanceOfGoingDeeperWhenMakingAccessChain =
57 {50, 95};
58 const std::pair<uint32_t, uint32_t> kChanceOfMakingDonorLivesafe = {40, 60};
59 const std::pair<uint32_t, uint32_t> kChanceOfMergingBlocks = {20, 95};
60 const std::pair<uint32_t, uint32_t> kChanceOfMovingBlockDown = {20, 50};
61 const std::pair<uint32_t, uint32_t> kChanceOfObfuscatingConstant = {10, 90};
62 const std::pair<uint32_t, uint32_t> kChanceOfOutliningFunction = {10, 90};
63 const std::pair<uint32_t, uint32_t> kChanceOfPermutingParameters = {30, 90};
64 const std::pair<uint32_t, uint32_t> kChanceOfReplacingIdWithSynonym = {10, 90};
65 const std::pair<uint32_t, uint32_t> kChanceOfSplittingBlock = {40, 95};
66 const std::pair<uint32_t, uint32_t> kChanceOfTogglingAccessChainInstruction = {
67 20, 90};
68
69 // Default limits for various quantities that are chosen during fuzzing.
70 // Keep them in alphabetical order.
71 const uint32_t kDefaultMaxLoopControlPartialCount = 100;
72 const uint32_t kDefaultMaxLoopControlPeelCount = 100;
73 const uint32_t kDefaultMaxLoopLimit = 20;
74 const uint32_t kDefaultMaxNewArraySizeLimit = 100;
75
76 // Default functions for controlling how deep to go during recursive
77 // generation/transformation. Keep them in alphabetical order.
78
79 const std::function<bool(uint32_t, RandomGenerator*)>
80 kDefaultGoDeeperInConstantObfuscation =
__anon0a4c58e80202(uint32_t current_depth, RandomGenerator* random_generator) 81 [](uint32_t current_depth, RandomGenerator* random_generator) -> bool {
82 double chance = 1.0 / std::pow(3.0, static_cast<float>(current_depth + 1));
83 return random_generator->RandomDouble() < chance;
84 };
85
86 } // namespace
87
FuzzerContext(RandomGenerator * random_generator,uint32_t min_fresh_id)88 FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
89 uint32_t min_fresh_id)
90 : random_generator_(random_generator),
91 next_fresh_id_(min_fresh_id),
92 max_loop_control_partial_count_(kDefaultMaxLoopControlPartialCount),
93 max_loop_control_peel_count_(kDefaultMaxLoopControlPeelCount),
94 max_loop_limit_(kDefaultMaxLoopLimit),
95 max_new_array_size_limit_(kDefaultMaxNewArraySizeLimit),
96 go_deeper_in_constant_obfuscation_(
97 kDefaultGoDeeperInConstantObfuscation) {
98 chance_of_adding_access_chain_ =
99 ChooseBetweenMinAndMax(kChanceOfAddingAccessChain);
100 chance_of_adding_another_struct_field_ =
101 ChooseBetweenMinAndMax(kChanceOfAddingAnotherStructField);
102 chance_of_adding_array_or_struct_type_ =
103 ChooseBetweenMinAndMax(kChanceOfAddingArrayOrStructType);
104 chance_of_adding_dead_block_ =
105 ChooseBetweenMinAndMax(kChanceOfAddingDeadBlock);
106 chance_of_adding_dead_break_ =
107 ChooseBetweenMinAndMax(kChanceOfAddingDeadBreak);
108 chance_of_adding_dead_continue_ =
109 ChooseBetweenMinAndMax(kChanceOfAddingDeadContinue);
110 chance_of_adding_equation_instruction_ =
111 ChooseBetweenMinAndMax(kChanceOfAddingEquationInstruction);
112 chance_of_adding_global_variable_ =
113 ChooseBetweenMinAndMax(kChanceOfAddingGlobalVariable);
114 chance_of_adding_load_ = ChooseBetweenMinAndMax(kChanceOfAddingLoad);
115 chance_of_adding_local_variable_ =
116 ChooseBetweenMinAndMax(kChanceOfAddingLocalVariable);
117 chance_of_adding_matrix_type_ =
118 ChooseBetweenMinAndMax(kChanceOfAddingMatrixType);
119 chance_of_adding_no_contraction_decoration_ =
120 ChooseBetweenMinAndMax(kChanceOfAddingNoContractionDecoration);
121 chance_of_adding_store_ = ChooseBetweenMinAndMax(kChanceOfAddingStore);
122 chance_of_adding_vector_type_ =
123 ChooseBetweenMinAndMax(kChanceOfAddingVectorType);
124 chance_of_adjusting_function_control_ =
125 ChooseBetweenMinAndMax(kChanceOfAdjustingFunctionControl);
126 chance_of_adjusting_loop_control_ =
127 ChooseBetweenMinAndMax(kChanceOfAdjustingLoopControl);
128 chance_of_adjusting_memory_operands_mask_ =
129 ChooseBetweenMinAndMax(kChanceOfAdjustingMemoryOperandsMask);
130 chance_of_adjusting_selection_control_ =
131 ChooseBetweenMinAndMax(kChanceOfAdjustingSelectionControl);
132 chance_of_calling_function_ =
133 ChooseBetweenMinAndMax(kChanceOfCallingFunction);
134 chance_of_choosing_struct_type_vs_array_type_ =
135 ChooseBetweenMinAndMax(kChanceOfChoosingStructTypeVsArrayType);
136 chance_of_constructing_composite_ =
137 ChooseBetweenMinAndMax(kChanceOfConstructingComposite);
138 chance_of_copying_object_ = ChooseBetweenMinAndMax(kChanceOfCopyingObject);
139 chance_of_donating_additional_module_ =
140 ChooseBetweenMinAndMax(kChanceOfDonatingAdditionalModule);
141 chance_of_going_deeper_when_making_access_chain_ =
142 ChooseBetweenMinAndMax(kChanceOfGoingDeeperWhenMakingAccessChain);
143 chance_of_making_donor_livesafe_ =
144 ChooseBetweenMinAndMax(kChanceOfMakingDonorLivesafe);
145 chance_of_merging_blocks_ = ChooseBetweenMinAndMax(kChanceOfMergingBlocks);
146 chance_of_moving_block_down_ =
147 ChooseBetweenMinAndMax(kChanceOfMovingBlockDown);
148 chance_of_obfuscating_constant_ =
149 ChooseBetweenMinAndMax(kChanceOfObfuscatingConstant);
150 chance_of_outlining_function_ =
151 ChooseBetweenMinAndMax(kChanceOfOutliningFunction);
152 chance_of_permuting_parameters_ =
153 ChooseBetweenMinAndMax(kChanceOfPermutingParameters);
154 chance_of_replacing_id_with_synonym_ =
155 ChooseBetweenMinAndMax(kChanceOfReplacingIdWithSynonym);
156 chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock);
157 chance_of_toggling_access_chain_instruction_ =
158 ChooseBetweenMinAndMax(kChanceOfTogglingAccessChainInstruction);
159 }
160
161 FuzzerContext::~FuzzerContext() = default;
162
GetFreshId()163 uint32_t FuzzerContext::GetFreshId() { return next_fresh_id_++; }
164
ChooseEven()165 bool FuzzerContext::ChooseEven() { return random_generator_->RandomBool(); }
166
ChoosePercentage(uint32_t percentage_chance)167 bool FuzzerContext::ChoosePercentage(uint32_t percentage_chance) {
168 assert(percentage_chance <= 100);
169 return random_generator_->RandomPercentage() < percentage_chance;
170 }
171
ChooseBetweenMinAndMax(const std::pair<uint32_t,uint32_t> & min_max)172 uint32_t FuzzerContext::ChooseBetweenMinAndMax(
173 const std::pair<uint32_t, uint32_t>& min_max) {
174 assert(min_max.first <= min_max.second);
175 return min_max.first +
176 random_generator_->RandomUint32(min_max.second - min_max.first + 1);
177 }
178
179 } // namespace fuzz
180 } // namespace spvtools
181