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 #ifndef SOURCE_FUZZ_FUZZER_CONTEXT_H_ 16 #define SOURCE_FUZZ_FUZZER_CONTEXT_H_ 17 18 #include <functional> 19 #include <utility> 20 21 #include "source/fuzz/random_generator.h" 22 #include "source/opt/function.h" 23 24 namespace spvtools { 25 namespace fuzz { 26 27 // Encapsulates all parameters that control the fuzzing process, such as the 28 // source of randomness and the probabilities with which transformations are 29 // applied. 30 class FuzzerContext { 31 public: 32 // Constructs a fuzzer context with a given random generator and the minimum 33 // value that can be used for fresh ids. 34 FuzzerContext(RandomGenerator* random_generator, uint32_t min_fresh_id); 35 36 ~FuzzerContext(); 37 38 // Returns a random boolean. 39 bool ChooseEven(); 40 41 // Returns true if and only if a randomly-chosen integer in the range [0, 100] 42 // is less than |percentage_chance|. 43 bool ChoosePercentage(uint32_t percentage_chance); 44 45 // Returns a random index into |sequence|, which is expected to have a 'size' 46 // method, and which must be non-empty. Typically 'HasSizeMethod' will be an 47 // std::vector. 48 template <typename HasSizeMethod> RandomIndex(const HasSizeMethod & sequence)49 uint32_t RandomIndex(const HasSizeMethod& sequence) const { 50 assert(sequence.size() > 0); 51 return random_generator_->RandomUint32( 52 static_cast<uint32_t>(sequence.size())); 53 } 54 55 // Selects a random index into |sequence|, removes the element at that index 56 // and returns it. 57 template <typename T> RemoveAtRandomIndex(std::vector<T> * sequence)58 T RemoveAtRandomIndex(std::vector<T>* sequence) const { 59 uint32_t index = RandomIndex(*sequence); 60 T result = sequence->at(index); 61 sequence->erase(sequence->begin() + index); 62 return result; 63 } 64 65 // Yields an id that is guaranteed not to be used in the module being fuzzed, 66 // or to have been issued before. 67 uint32_t GetFreshId(); 68 69 // Probabilities associated with applying various transformations. 70 // Keep them in alphabetical order. GetChanceOfAddingAccessChain()71 uint32_t GetChanceOfAddingAccessChain() { 72 return chance_of_adding_access_chain_; 73 } GetChanceOfAddingAnotherStructField()74 uint32_t GetChanceOfAddingAnotherStructField() { 75 return chance_of_adding_another_struct_field_; 76 } GetChanceOfAddingArrayOrStructType()77 uint32_t GetChanceOfAddingArrayOrStructType() { 78 return chance_of_adding_array_or_struct_type_; 79 } GetChanceOfAddingDeadBlock()80 uint32_t GetChanceOfAddingDeadBlock() { return chance_of_adding_dead_block_; } GetChanceOfAddingDeadBreak()81 uint32_t GetChanceOfAddingDeadBreak() { return chance_of_adding_dead_break_; } GetChanceOfAddingDeadContinue()82 uint32_t GetChanceOfAddingDeadContinue() { 83 return chance_of_adding_dead_continue_; 84 } GetChanceOfAddingGlobalVariable()85 uint32_t GetChanceOfAddingGlobalVariable() { 86 return chance_of_adding_global_variable_; 87 } GetChanceOfAddingLoad()88 uint32_t GetChanceOfAddingLoad() { return chance_of_adding_load_; } GetChanceOfAddingLocalVariable()89 uint32_t GetChanceOfAddingLocalVariable() { 90 return chance_of_adding_local_variable_; 91 } GetChanceOfAddingMatrixType()92 uint32_t GetChanceOfAddingMatrixType() { 93 return chance_of_adding_matrix_type_; 94 } GetChanceOfAddingNoContractionDecoration()95 uint32_t GetChanceOfAddingNoContractionDecoration() { 96 return chance_of_adding_no_contraction_decoration_; 97 } GetChanceOfAddingStore()98 uint32_t GetChanceOfAddingStore() { return chance_of_adding_store_; } GetChanceOfAddingVectorType()99 uint32_t GetChanceOfAddingVectorType() { 100 return chance_of_adding_vector_type_; 101 } GetChanceOfAdjustingFunctionControl()102 uint32_t GetChanceOfAdjustingFunctionControl() { 103 return chance_of_adjusting_function_control_; 104 } GetChanceOfAdjustingLoopControl()105 uint32_t GetChanceOfAdjustingLoopControl() { 106 return chance_of_adjusting_loop_control_; 107 } GetChanceOfAdjustingMemoryOperandsMask()108 uint32_t GetChanceOfAdjustingMemoryOperandsMask() { 109 return chance_of_adjusting_memory_operands_mask_; 110 } GetChanceOfAdjustingSelectionControl()111 uint32_t GetChanceOfAdjustingSelectionControl() { 112 return chance_of_adjusting_selection_control_; 113 } GetChanceOfCallingFunction()114 uint32_t GetChanceOfCallingFunction() { return chance_of_calling_function_; } GetChanceOfChoosingStructTypeVsArrayType()115 uint32_t GetChanceOfChoosingStructTypeVsArrayType() { 116 return chance_of_choosing_struct_type_vs_array_type_; 117 } GetChanceOfConstructingComposite()118 uint32_t GetChanceOfConstructingComposite() { 119 return chance_of_constructing_composite_; 120 } GetChanceOfCopyingObject()121 uint32_t GetChanceOfCopyingObject() { return chance_of_copying_object_; } GetChanceOfDonatingAdditionalModule()122 uint32_t GetChanceOfDonatingAdditionalModule() { 123 return chance_of_donating_additional_module_; 124 } GetChanceOfGoingDeeperWhenMakingAccessChain()125 uint32_t GetChanceOfGoingDeeperWhenMakingAccessChain() { 126 return chance_of_going_deeper_when_making_access_chain_; 127 } ChanceOfMakingDonorLivesafe()128 uint32_t ChanceOfMakingDonorLivesafe() { 129 return chance_of_making_donor_livesafe_; 130 } GetChanceOfMergingBlocks()131 uint32_t GetChanceOfMergingBlocks() { return chance_of_merging_blocks_; } GetChanceOfMovingBlockDown()132 uint32_t GetChanceOfMovingBlockDown() { return chance_of_moving_block_down_; } GetChanceOfObfuscatingConstant()133 uint32_t GetChanceOfObfuscatingConstant() { 134 return chance_of_obfuscating_constant_; 135 } GetChanceOfOutliningFunction()136 uint32_t GetChanceOfOutliningFunction() { 137 return chance_of_outlining_function_; 138 } GetChanceOfReplacingIdWithSynonym()139 uint32_t GetChanceOfReplacingIdWithSynonym() { 140 return chance_of_replacing_id_with_synonym_; 141 } GetChanceOfSplittingBlock()142 uint32_t GetChanceOfSplittingBlock() { return chance_of_splitting_block_; } GetRandomLoopControlPeelCount()143 uint32_t GetRandomLoopControlPeelCount() { 144 return random_generator_->RandomUint32(max_loop_control_peel_count_); 145 } GetRandomLoopControlPartialCount()146 uint32_t GetRandomLoopControlPartialCount() { 147 return random_generator_->RandomUint32(max_loop_control_partial_count_); 148 } GetRandomLoopLimit()149 uint32_t GetRandomLoopLimit() { 150 return random_generator_->RandomUint32(max_loop_limit_); 151 } GetRandomSizeForNewArray()152 uint32_t GetRandomSizeForNewArray() { 153 // Ensure that the array size is non-zero. 154 return random_generator_->RandomUint32(max_new_array_size_limit_ - 1) + 1; 155 } 156 157 // Other functions to control transformations. Keep them in alphabetical 158 // order. GetRandomIndexForAccessChain(uint32_t composite_size_bound)159 uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) { 160 return random_generator_->RandomUint32(composite_size_bound); 161 } GoDeeperInConstantObfuscation(uint32_t depth)162 bool GoDeeperInConstantObfuscation(uint32_t depth) { 163 return go_deeper_in_constant_obfuscation_(depth, random_generator_); 164 } 165 166 private: 167 // The source of randomness. 168 RandomGenerator* random_generator_; 169 // The next fresh id to be issued. 170 uint32_t next_fresh_id_; 171 172 // Probabilities associated with applying various transformations. 173 // Keep them in alphabetical order. 174 uint32_t chance_of_adding_access_chain_; 175 uint32_t chance_of_adding_another_struct_field_; 176 uint32_t chance_of_adding_array_or_struct_type_; 177 uint32_t chance_of_adding_dead_block_; 178 uint32_t chance_of_adding_dead_break_; 179 uint32_t chance_of_adding_dead_continue_; 180 uint32_t chance_of_adding_global_variable_; 181 uint32_t chance_of_adding_load_; 182 uint32_t chance_of_adding_local_variable_; 183 uint32_t chance_of_adding_matrix_type_; 184 uint32_t chance_of_adding_no_contraction_decoration_; 185 uint32_t chance_of_adding_store_; 186 uint32_t chance_of_adding_vector_type_; 187 uint32_t chance_of_adjusting_function_control_; 188 uint32_t chance_of_adjusting_loop_control_; 189 uint32_t chance_of_adjusting_memory_operands_mask_; 190 uint32_t chance_of_adjusting_selection_control_; 191 uint32_t chance_of_calling_function_; 192 uint32_t chance_of_choosing_struct_type_vs_array_type_; 193 uint32_t chance_of_constructing_composite_; 194 uint32_t chance_of_copying_object_; 195 uint32_t chance_of_donating_additional_module_; 196 uint32_t chance_of_going_deeper_when_making_access_chain_; 197 uint32_t chance_of_making_donor_livesafe_; 198 uint32_t chance_of_merging_blocks_; 199 uint32_t chance_of_moving_block_down_; 200 uint32_t chance_of_obfuscating_constant_; 201 uint32_t chance_of_outlining_function_; 202 uint32_t chance_of_replacing_id_with_synonym_; 203 uint32_t chance_of_splitting_block_; 204 205 // Limits associated with various quantities for which random values are 206 // chosen during fuzzing. 207 // Keep them in alphabetical order. 208 uint32_t max_loop_control_partial_count_; 209 uint32_t max_loop_control_peel_count_; 210 uint32_t max_loop_limit_; 211 uint32_t max_new_array_size_limit_; 212 213 // Functions to determine with what probability to go deeper when generating 214 // or mutating constructs recursively. 215 const std::function<bool(uint32_t, RandomGenerator*)>& 216 go_deeper_in_constant_obfuscation_; 217 218 // Requires |min_max.first| <= |min_max.second|, and returns a value in the 219 // range [ |min_max.first|, |min_max.second| ] 220 uint32_t ChooseBetweenMinAndMax(const std::pair<uint32_t, uint32_t>& min_max); 221 }; 222 223 } // namespace fuzz 224 } // namespace spvtools 225 226 #endif // SOURCE_FUZZ_FUZZER_CONTEXT_H_ 227