• 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 #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