• 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> kChanceOfAddingGlobalVariable = {20, 90};
34 const std::pair<uint32_t, uint32_t> kChanceOfAddingLoad = {5, 50};
35 const std::pair<uint32_t, uint32_t> kChanceOfAddingLocalVariable = {20, 90};
36 const std::pair<uint32_t, uint32_t> kChanceOfAddingMatrixType = {20, 70};
37 const std::pair<uint32_t, uint32_t> kChanceOfAddingNoContractionDecoration = {
38     5, 70};
39 const std::pair<uint32_t, uint32_t> kChanceOfAddingStore = {5, 50};
40 const std::pair<uint32_t, uint32_t> kChanceOfAddingVectorType = {20, 70};
41 const std::pair<uint32_t, uint32_t> kChanceOfAdjustingFunctionControl = {20,
42                                                                          70};
43 const std::pair<uint32_t, uint32_t> kChanceOfAdjustingLoopControl = {20, 90};
44 const std::pair<uint32_t, uint32_t> kChanceOfAdjustingMemoryOperandsMask = {20,
45                                                                             90};
46 const std::pair<uint32_t, uint32_t> kChanceOfAdjustingSelectionControl = {20,
47                                                                           90};
48 const std::pair<uint32_t, uint32_t> kChanceOfCallingFunction = {1, 10};
49 const std::pair<uint32_t, uint32_t> kChanceOfChoosingStructTypeVsArrayType = {
50     20, 80};
51 const std::pair<uint32_t, uint32_t> kChanceOfConstructingComposite = {20, 50};
52 const std::pair<uint32_t, uint32_t> kChanceOfCopyingObject = {20, 50};
53 const std::pair<uint32_t, uint32_t> kChanceOfDonatingAdditionalModule = {5, 50};
54 const std::pair<uint32_t, uint32_t> kChanceOfGoingDeeperWhenMakingAccessChain =
55     {50, 95};
56 const std::pair<uint32_t, uint32_t> kChanceOfMakingDonorLivesafe = {40, 60};
57 const std::pair<uint32_t, uint32_t> kChanceOfMergingBlocks = {20, 95};
58 const std::pair<uint32_t, uint32_t> kChanceOfMovingBlockDown = {20, 50};
59 const std::pair<uint32_t, uint32_t> kChanceOfObfuscatingConstant = {10, 90};
60 const std::pair<uint32_t, uint32_t> kChanceOfOutliningFunction = {10, 90};
61 const std::pair<uint32_t, uint32_t> kChanceOfReplacingIdWithSynonym = {10, 90};
62 const std::pair<uint32_t, uint32_t> kChanceOfSplittingBlock = {40, 95};
63 
64 // Default limits for various quantities that are chosen during fuzzing.
65 // Keep them in alphabetical order.
66 const uint32_t kDefaultMaxLoopControlPartialCount = 100;
67 const uint32_t kDefaultMaxLoopControlPeelCount = 100;
68 const uint32_t kDefaultMaxLoopLimit = 20;
69 const uint32_t kDefaultMaxNewArraySizeLimit = 100;
70 
71 // Default functions for controlling how deep to go during recursive
72 // generation/transformation. Keep them in alphabetical order.
73 
74 const std::function<bool(uint32_t, RandomGenerator*)>
75     kDefaultGoDeeperInConstantObfuscation =
__anonaff695220202(uint32_t current_depth, RandomGenerator* random_generator) 76         [](uint32_t current_depth, RandomGenerator* random_generator) -> bool {
77   double chance = 1.0 / std::pow(3.0, static_cast<float>(current_depth + 1));
78   return random_generator->RandomDouble() < chance;
79 };
80 
81 }  // namespace
82 
FuzzerContext(RandomGenerator * random_generator,uint32_t min_fresh_id)83 FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
84                              uint32_t min_fresh_id)
85     : random_generator_(random_generator),
86       next_fresh_id_(min_fresh_id),
87       max_loop_control_partial_count_(kDefaultMaxLoopControlPartialCount),
88       max_loop_control_peel_count_(kDefaultMaxLoopControlPeelCount),
89       max_loop_limit_(kDefaultMaxLoopLimit),
90       max_new_array_size_limit_(kDefaultMaxNewArraySizeLimit),
91       go_deeper_in_constant_obfuscation_(
92           kDefaultGoDeeperInConstantObfuscation) {
93   chance_of_adding_access_chain_ =
94       ChooseBetweenMinAndMax(kChanceOfAddingAccessChain);
95   chance_of_adding_another_struct_field_ =
96       ChooseBetweenMinAndMax(kChanceOfAddingAnotherStructField);
97   chance_of_adding_array_or_struct_type_ =
98       ChooseBetweenMinAndMax(kChanceOfAddingArrayOrStructType);
99   chance_of_adding_dead_block_ =
100       ChooseBetweenMinAndMax(kChanceOfAddingDeadBlock);
101   chance_of_adding_dead_break_ =
102       ChooseBetweenMinAndMax(kChanceOfAddingDeadBreak);
103   chance_of_adding_dead_continue_ =
104       ChooseBetweenMinAndMax(kChanceOfAddingDeadContinue);
105   chance_of_adding_global_variable_ =
106       ChooseBetweenMinAndMax(kChanceOfAddingGlobalVariable);
107   chance_of_adding_load_ = ChooseBetweenMinAndMax(kChanceOfAddingLoad);
108   chance_of_adding_local_variable_ =
109       ChooseBetweenMinAndMax(kChanceOfAddingLocalVariable);
110   chance_of_adding_matrix_type_ =
111       ChooseBetweenMinAndMax(kChanceOfAddingMatrixType);
112   chance_of_adding_no_contraction_decoration_ =
113       ChooseBetweenMinAndMax(kChanceOfAddingNoContractionDecoration);
114   chance_of_adding_store_ = ChooseBetweenMinAndMax(kChanceOfAddingStore);
115   chance_of_adding_vector_type_ =
116       ChooseBetweenMinAndMax(kChanceOfAddingVectorType);
117   chance_of_adjusting_function_control_ =
118       ChooseBetweenMinAndMax(kChanceOfAdjustingFunctionControl);
119   chance_of_adjusting_loop_control_ =
120       ChooseBetweenMinAndMax(kChanceOfAdjustingLoopControl);
121   chance_of_adjusting_memory_operands_mask_ =
122       ChooseBetweenMinAndMax(kChanceOfAdjustingMemoryOperandsMask);
123   chance_of_adjusting_selection_control_ =
124       ChooseBetweenMinAndMax(kChanceOfAdjustingSelectionControl);
125   chance_of_calling_function_ =
126       ChooseBetweenMinAndMax(kChanceOfCallingFunction);
127   chance_of_choosing_struct_type_vs_array_type_ =
128       ChooseBetweenMinAndMax(kChanceOfChoosingStructTypeVsArrayType);
129   chance_of_constructing_composite_ =
130       ChooseBetweenMinAndMax(kChanceOfConstructingComposite);
131   chance_of_copying_object_ = ChooseBetweenMinAndMax(kChanceOfCopyingObject);
132   chance_of_donating_additional_module_ =
133       ChooseBetweenMinAndMax(kChanceOfDonatingAdditionalModule);
134   chance_of_going_deeper_when_making_access_chain_ =
135       ChooseBetweenMinAndMax(kChanceOfGoingDeeperWhenMakingAccessChain);
136   chance_of_making_donor_livesafe_ =
137       ChooseBetweenMinAndMax(kChanceOfMakingDonorLivesafe);
138   chance_of_merging_blocks_ = ChooseBetweenMinAndMax(kChanceOfMergingBlocks);
139   chance_of_moving_block_down_ =
140       ChooseBetweenMinAndMax(kChanceOfMovingBlockDown);
141   chance_of_obfuscating_constant_ =
142       ChooseBetweenMinAndMax(kChanceOfObfuscatingConstant);
143   chance_of_outlining_function_ =
144       ChooseBetweenMinAndMax(kChanceOfOutliningFunction);
145   chance_of_replacing_id_with_synonym_ =
146       ChooseBetweenMinAndMax(kChanceOfReplacingIdWithSynonym);
147   chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock);
148 }
149 
150 FuzzerContext::~FuzzerContext() = default;
151 
GetFreshId()152 uint32_t FuzzerContext::GetFreshId() { return next_fresh_id_++; }
153 
ChooseEven()154 bool FuzzerContext::ChooseEven() { return random_generator_->RandomBool(); }
155 
ChoosePercentage(uint32_t percentage_chance)156 bool FuzzerContext::ChoosePercentage(uint32_t percentage_chance) {
157   assert(percentage_chance <= 100);
158   return random_generator_->RandomPercentage() < percentage_chance;
159 }
160 
ChooseBetweenMinAndMax(const std::pair<uint32_t,uint32_t> & min_max)161 uint32_t FuzzerContext::ChooseBetweenMinAndMax(
162     const std::pair<uint32_t, uint32_t>& min_max) {
163   assert(min_max.first <= min_max.second);
164   return min_max.first +
165          random_generator_->RandomUint32(min_max.second - min_max.first + 1);
166 }
167 
168 }  // namespace fuzz
169 }  // namespace spvtools
170