xref: /aosp_15_r20/external/grpc-grpc/test/core/transport/binder/end2end/fuzzers/fuzzer_utils.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 // Copyright 2021 gRPC authors.
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 GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FUZZERS_FUZZER_UTILS_H
16 #define GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FUZZERS_FUZZER_UTILS_H
17 
18 #include <memory>
19 #include <queue>
20 #include <string>
21 #include <thread>
22 #include <vector>
23 
24 #include "absl/memory/memory.h"
25 #include "absl/status/status.h"
26 
27 #include <grpc/support/log.h>
28 
29 #include "src/core/ext/transport/binder/wire_format/binder.h"
30 #include "src/core/ext/transport/binder/wire_format/wire_reader.h"
31 #include "src/core/lib/gprpp/crash.h"
32 #include "test/core/transport/binder/end2end/fuzzers/binder_transport_fuzzer.pb.h"
33 
34 namespace grpc_binder {
35 namespace fuzzing {
36 
37 // A WritableParcel implementation that simply does nothing. Don't use
38 // MockWritableParcel here since capturing calls is expensive.
39 class NoOpWritableParcel : public WritableParcel {
40  public:
GetDataSize()41   int32_t GetDataSize() const override { return 0; }
WriteInt32(int32_t)42   absl::Status WriteInt32(int32_t /*data*/) override {
43     return absl::OkStatus();
44   }
WriteInt64(int64_t)45   absl::Status WriteInt64(int64_t /*data*/) override {
46     return absl::OkStatus();
47   }
WriteBinder(HasRawBinder *)48   absl::Status WriteBinder(HasRawBinder* /*binder*/) override {
49     return absl::OkStatus();
50   }
WriteString(absl::string_view)51   absl::Status WriteString(absl::string_view /*s*/) override {
52     return absl::OkStatus();
53   }
WriteByteArray(const int8_t *,int32_t)54   absl::Status WriteByteArray(const int8_t* /*buffer*/,
55                               int32_t /*length*/) override {
56     return absl::OkStatus();
57   }
58 };
59 
60 // Binder implementation used in fuzzing.
61 //
62 // Most of its the functionalities are no-op, except ConstructTxReceiver now
63 // returns a TransactionReceiverForFuzzing.
64 class BinderForFuzzing : public Binder {
65  public:
BinderForFuzzing()66   BinderForFuzzing() : input_(std::make_unique<NoOpWritableParcel>()) {}
67 
BinderForFuzzing(const binder_transport_fuzzer::IncomingParcels & p)68   explicit BinderForFuzzing(const binder_transport_fuzzer::IncomingParcels& p)
69       : incoming_parcels_(p), input_(std::make_unique<NoOpWritableParcel>()) {}
70 
Initialize()71   void Initialize() override {}
PrepareTransaction()72   absl::Status PrepareTransaction() override { return absl::OkStatus(); }
73 
Transact(BinderTransportTxCode)74   absl::Status Transact(BinderTransportTxCode /*tx_code*/) override {
75     return absl::OkStatus();
76   }
77 
78   std::unique_ptr<TransactionReceiver> ConstructTxReceiver(
79       grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
80       TransactionReceiver::OnTransactCb cb) const override;
81 
GetWritableParcel()82   WritableParcel* GetWritableParcel() const override { return input_.get(); }
GetRawBinder()83   void* GetRawBinder() override { return nullptr; }
84 
85  private:
86   binder_transport_fuzzer::IncomingParcels incoming_parcels_;
87   std::unique_ptr<WritableParcel> input_;
88 };
89 
90 // ReadableParcel implementation used in fuzzing.
91 //
92 // It consumes a Parcel generated by mutator, and returns the data in the Parcel
93 // upon user's requests.
94 class ReadableParcelForFuzzing : public ReadableParcel {
95  public:
ReadableParcelForFuzzing(const binder_transport_fuzzer::Parcel & p)96   explicit ReadableParcelForFuzzing(const binder_transport_fuzzer::Parcel& p)
97       : parcel_data_size_(p.data_size()), consumed_data_size_(0) {
98     for (const auto& v : p.values()) {
99       values_.push(v);
100     }
101   }
102 
103   // Construct from SetupTransportParcel, which have fixed types of data in it.
ReadableParcelForFuzzing(const binder_transport_fuzzer::SetupTransportParcel & p)104   explicit ReadableParcelForFuzzing(
105       const binder_transport_fuzzer::SetupTransportParcel& p)
106       : parcel_data_size_(p.data_size()), consumed_data_size_(0) {
107     // Creates value for protocol version and put it into the queue
108     binder_transport_fuzzer::Value version_value;
109     version_value.set_i32(p.version());
110     values_.push(version_value);
111 
112     // Creates a binder value and put it into the queue
113     binder_transport_fuzzer::Value binder_value;
114     binder_value.mutable_binder();  // sets one-of field
115     values_.push(binder_value);
116   }
117 
118   int32_t GetDataSize() const override;
119   absl::Status ReadInt32(int32_t* data) override;
120   absl::Status ReadInt64(int64_t* data) override;
121   absl::Status ReadBinder(std::unique_ptr<Binder>* binder) override;
122   absl::Status ReadByteArray(std::string* data) override;
123   absl::Status ReadString(std::string* data) override;
124 
125  private:
126   // Stores data/objects in binder in their order. Since we don't support random
127   // access using a std::queue is enough here.
128   std::queue<binder_transport_fuzzer::Value> values_;
129 
130   const int32_t parcel_data_size_;
131 
132   static constexpr size_t kParcelDataSizeLimit = 1024 * 1024;
133   size_t consumed_data_size_;
134 };
135 
136 void JoinFuzzingThread();
137 
138 // TransactionReceiver implementation used in fuzzing.
139 //
140 // When constructed, start sending fuzzed requests to the client. When all the
141 // bytes are consumed, the reference to WireReader will be released.
142 class TransactionReceiverForFuzzing : public TransactionReceiver {
143  public:
144   TransactionReceiverForFuzzing(
145       binder_transport_fuzzer::IncomingParcels incoming_parcels,
146       grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
147       TransactionReceiver::OnTransactCb cb);
148 
GetRawBinder()149   void* GetRawBinder() override { return nullptr; }
150 };
151 
152 }  // namespace fuzzing
153 }  // namespace grpc_binder
154 
155 #endif  // GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FUZZERS_FUZZER_UTILS_H
156