• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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