1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 Vasyl Teliman
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_pass_mutate_pointers.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_context.h"
18fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h"
19fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_mutate_pointer.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace fuzz {
23fd4e5da5Sopenharmony_ci
24fd4e5da5Sopenharmony_ciFuzzerPassMutatePointers::FuzzerPassMutatePointers(
25fd4e5da5Sopenharmony_ci    opt::IRContext* ir_context, TransformationContext* transformation_context,
26fd4e5da5Sopenharmony_ci    FuzzerContext* fuzzer_context,
27fd4e5da5Sopenharmony_ci    protobufs::TransformationSequence* transformations,
28fd4e5da5Sopenharmony_ci    bool ignore_inapplicable_transformations)
29fd4e5da5Sopenharmony_ci    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
30fd4e5da5Sopenharmony_ci                 transformations, ignore_inapplicable_transformations) {}
31fd4e5da5Sopenharmony_ci
32fd4e5da5Sopenharmony_civoid FuzzerPassMutatePointers::Apply() {
33fd4e5da5Sopenharmony_ci  ForEachInstructionWithInstructionDescriptor(
34fd4e5da5Sopenharmony_ci      [this](opt::Function* function, opt::BasicBlock* block,
35fd4e5da5Sopenharmony_ci             opt::BasicBlock::iterator inst_it,
36fd4e5da5Sopenharmony_ci             const protobufs::InstructionDescriptor& instruction_descriptor) {
37fd4e5da5Sopenharmony_ci        if (!GetFuzzerContext()->ChoosePercentage(
38fd4e5da5Sopenharmony_ci                GetFuzzerContext()->GetChanceOfMutatingPointer())) {
39fd4e5da5Sopenharmony_ci          return;
40fd4e5da5Sopenharmony_ci        }
41fd4e5da5Sopenharmony_ci
42fd4e5da5Sopenharmony_ci        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
43fd4e5da5Sopenharmony_ci                                                          inst_it)) {
44fd4e5da5Sopenharmony_ci          return;
45fd4e5da5Sopenharmony_ci        }
46fd4e5da5Sopenharmony_ci
47fd4e5da5Sopenharmony_ci        auto available_pointers = FindAvailableInstructions(
48fd4e5da5Sopenharmony_ci            function, block, inst_it,
49fd4e5da5Sopenharmony_ci            [](opt::IRContext* ir_context, opt::Instruction* inst) {
50fd4e5da5Sopenharmony_ci              return TransformationMutatePointer::IsValidPointerInstruction(
51fd4e5da5Sopenharmony_ci                  ir_context, *inst);
52fd4e5da5Sopenharmony_ci            });
53fd4e5da5Sopenharmony_ci
54fd4e5da5Sopenharmony_ci        if (available_pointers.empty()) {
55fd4e5da5Sopenharmony_ci          return;
56fd4e5da5Sopenharmony_ci        }
57fd4e5da5Sopenharmony_ci
58fd4e5da5Sopenharmony_ci        const auto* pointer_inst =
59fd4e5da5Sopenharmony_ci            available_pointers[GetFuzzerContext()->RandomIndex(
60fd4e5da5Sopenharmony_ci                available_pointers)];
61fd4e5da5Sopenharmony_ci
62fd4e5da5Sopenharmony_ci        // Make sure there is an irrelevant constant in the module.
63fd4e5da5Sopenharmony_ci        FindOrCreateZeroConstant(fuzzerutil::GetPointeeTypeIdFromPointerType(
64fd4e5da5Sopenharmony_ci                                     GetIRContext(), pointer_inst->type_id()),
65fd4e5da5Sopenharmony_ci                                 true);
66fd4e5da5Sopenharmony_ci
67fd4e5da5Sopenharmony_ci        ApplyTransformation(TransformationMutatePointer(
68fd4e5da5Sopenharmony_ci            pointer_inst->result_id(), GetFuzzerContext()->GetFreshId(),
69fd4e5da5Sopenharmony_ci            instruction_descriptor));
70fd4e5da5Sopenharmony_ci      });
71fd4e5da5Sopenharmony_ci}
72fd4e5da5Sopenharmony_ci
73fd4e5da5Sopenharmony_ci}  // namespace fuzz
74fd4e5da5Sopenharmony_ci}  // namespace spvtools
75