fuzzer_pass_add_local_variables.cpp 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright (c) 2020 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. #include "source/fuzz/fuzzer_pass_add_local_variables.h"
  15. #include "source/fuzz/fuzzer_util.h"
  16. #include "source/fuzz/transformation_add_local_variable.h"
  17. #include "source/fuzz/transformation_add_type_pointer.h"
  18. namespace spvtools {
  19. namespace fuzz {
  20. FuzzerPassAddLocalVariables::FuzzerPassAddLocalVariables(
  21. opt::IRContext* ir_context, TransformationContext* transformation_context,
  22. FuzzerContext* fuzzer_context,
  23. protobufs::TransformationSequence* transformations,
  24. bool ignore_inapplicable_transformations)
  25. : FuzzerPass(ir_context, transformation_context, fuzzer_context,
  26. transformations, ignore_inapplicable_transformations) {}
  27. void FuzzerPassAddLocalVariables::Apply() {
  28. auto basic_type_ids_and_pointers =
  29. GetAvailableBasicTypesAndPointers(spv::StorageClass::Function);
  30. // These are the basic types that are available to this fuzzer pass.
  31. auto& basic_types = basic_type_ids_and_pointers.first;
  32. if (basic_types.empty()) {
  33. // The pass cannot do anything if there are no basic types.
  34. return;
  35. }
  36. // These are the pointers to those basic types that are *initially* available
  37. // to the fuzzer pass. The fuzzer pass might add pointer types in cases where
  38. // none are available for a given basic type.
  39. auto& basic_type_to_pointers = basic_type_ids_and_pointers.second;
  40. // Consider every function in the module.
  41. for (auto& function : *GetIRContext()->module()) {
  42. // Probabilistically keep adding random variables to this function.
  43. while (GetFuzzerContext()->ChoosePercentage(
  44. GetFuzzerContext()->GetChanceOfAddingLocalVariable())) {
  45. // Choose a random basic type; the new variable's type will be a pointer
  46. // to this basic type.
  47. uint32_t basic_type =
  48. basic_types[GetFuzzerContext()->RandomIndex(basic_types)];
  49. uint32_t pointer_type;
  50. std::vector<uint32_t>& available_pointers_to_basic_type =
  51. basic_type_to_pointers.at(basic_type);
  52. // Determine whether there is at least one pointer to this basic type.
  53. if (available_pointers_to_basic_type.empty()) {
  54. // There is not. Make one, to use here, and add it to the available
  55. // pointers for the basic type so that future variables can potentially
  56. // use it.
  57. pointer_type = GetFuzzerContext()->GetFreshId();
  58. ApplyTransformation(TransformationAddTypePointer(
  59. pointer_type, spv::StorageClass::Function, basic_type));
  60. available_pointers_to_basic_type.push_back(pointer_type);
  61. } else {
  62. // There is - grab one.
  63. pointer_type =
  64. available_pointers_to_basic_type[GetFuzzerContext()->RandomIndex(
  65. available_pointers_to_basic_type)];
  66. }
  67. ApplyTransformation(TransformationAddLocalVariable(
  68. GetFuzzerContext()->GetFreshId(), pointer_type, function.result_id(),
  69. FindOrCreateZeroConstant(basic_type, false), true));
  70. }
  71. }
  72. }
  73. } // namespace fuzz
  74. } // namespace spvtools