xref: /aosp_15_r20/external/grpc-grpc/test/core/transport/binder/end2end/fuzzers/fuzzer_utils.cc (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 #include "test/core/transport/binder/end2end/fuzzers/fuzzer_utils.h"
16 
17 namespace grpc_binder {
18 namespace fuzzing {
19 
20 namespace {
21 
22 std::thread* g_fuzzing_thread = nullptr;
23 
24 template <typename... Args>
CreateFuzzingThread(Args &&...args)25 void CreateFuzzingThread(Args&&... args) {
26   GPR_ASSERT(g_fuzzing_thread == nullptr);
27   g_fuzzing_thread = new std::thread(std::forward<Args>(args)...);
28 }
29 
30 }  // namespace
31 
JoinFuzzingThread()32 void JoinFuzzingThread() {
33   if (g_fuzzing_thread) {
34     g_fuzzing_thread->join();
35     delete g_fuzzing_thread;
36     g_fuzzing_thread = nullptr;
37   }
38 }
39 
GetDataSize() const40 int32_t ReadableParcelForFuzzing::GetDataSize() const {
41   return parcel_data_size_;
42 }
43 
ReadInt32(int32_t * data)44 absl::Status ReadableParcelForFuzzing::ReadInt32(int32_t* data) {
45   if (consumed_data_size_ >= kParcelDataSizeLimit) {
46     return absl::InternalError("Parcel size limit exceeds");
47   }
48   if (values_.empty() || !values_.front().has_i32()) {
49     return absl::InternalError("error");
50   }
51   *data = values_.front().i32();
52   values_.pop();
53   consumed_data_size_ += sizeof(int32_t);
54   return absl::OkStatus();
55 }
56 
ReadInt64(int64_t * data)57 absl::Status ReadableParcelForFuzzing::ReadInt64(int64_t* data) {
58   if (consumed_data_size_ >= kParcelDataSizeLimit) {
59     return absl::InternalError("Parcel size limit exceeds");
60   }
61   if (values_.empty() || !values_.front().has_i64()) {
62     return absl::InternalError("error");
63   }
64   *data = values_.front().i64();
65   values_.pop();
66   consumed_data_size_ += sizeof(int64_t);
67   return absl::OkStatus();
68 }
69 
ReadBinder(std::unique_ptr<Binder> * binder)70 absl::Status ReadableParcelForFuzzing::ReadBinder(
71     std::unique_ptr<Binder>* binder) {
72   if (consumed_data_size_ >= kParcelDataSizeLimit) {
73     return absl::InternalError("Parcel size limit exceeds");
74   }
75   if (values_.empty() || !values_.front().has_binder()) {
76     return absl::InternalError("error");
77   }
78   *binder = std::make_unique<BinderForFuzzing>();
79   values_.pop();
80   consumed_data_size_ += sizeof(void*);
81   return absl::OkStatus();
82 }
83 
ReadByteArray(std::string * data)84 absl::Status ReadableParcelForFuzzing::ReadByteArray(std::string* data) {
85   if (consumed_data_size_ >= kParcelDataSizeLimit) {
86     return absl::InternalError("Parcel size limit exceeds");
87   }
88   if (values_.empty() || !values_.front().has_byte_array()) {
89     return absl::InternalError("error");
90   }
91   *data = values_.front().byte_array();
92   values_.pop();
93   consumed_data_size_ += data->size();
94   return absl::OkStatus();
95 }
96 
ReadString(std::string * data)97 absl::Status ReadableParcelForFuzzing::ReadString(std::string* data) {
98   if (consumed_data_size_ >= kParcelDataSizeLimit) {
99     return absl::InternalError("Parcel size limit exceeds");
100   }
101   if (values_.empty() || !values_.front().has_str()) {
102     return absl::InternalError("error");
103   }
104   *data = values_.front().str();
105   values_.pop();
106   consumed_data_size_ += data->size();
107   return absl::OkStatus();
108 }
109 
FuzzingLoop(binder_transport_fuzzer::IncomingParcels incoming_parcels,grpc_core::RefCountedPtr<grpc_binder::WireReader> wire_reader_ref,grpc_binder::TransactionReceiver::OnTransactCb callback)110 void FuzzingLoop(
111     binder_transport_fuzzer::IncomingParcels incoming_parcels,
112     grpc_core::RefCountedPtr<grpc_binder::WireReader> wire_reader_ref,
113     grpc_binder::TransactionReceiver::OnTransactCb callback) {
114   {
115     // Send SETUP_TRANSPORT request.
116     std::unique_ptr<grpc_binder::ReadableParcel> parcel =
117         std::make_unique<ReadableParcelForFuzzing>(
118             incoming_parcels.setup_transport_transaction().parcel());
119     callback(static_cast<transaction_code_t>(
120                  grpc_binder::BinderTransportTxCode::SETUP_TRANSPORT),
121              parcel.get(),
122              /*uid=*/incoming_parcels.setup_transport_transaction().uid())
123         .IgnoreError();
124   }
125   for (const auto& tx_iter : incoming_parcels.transactions()) {
126     transaction_code_t tx_code = tx_iter.code();
127     std::unique_ptr<grpc_binder::ReadableParcel> parcel =
128         std::make_unique<ReadableParcelForFuzzing>(tx_iter.parcel());
129     callback(tx_code, parcel.get(),
130              /*uid=*/tx_iter.uid())
131         .IgnoreError();
132   }
133   wire_reader_ref = nullptr;
134 }
135 
TransactionReceiverForFuzzing(binder_transport_fuzzer::IncomingParcels incoming_parcels,grpc_core::RefCountedPtr<WireReader> wire_reader_ref,TransactionReceiver::OnTransactCb cb)136 TransactionReceiverForFuzzing::TransactionReceiverForFuzzing(
137     binder_transport_fuzzer::IncomingParcels incoming_parcels,
138     grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
139     TransactionReceiver::OnTransactCb cb) {
140   gpr_log(GPR_INFO, "Construct TransactionReceiverForFuzzing");
141   CreateFuzzingThread(FuzzingLoop, std::move(incoming_parcels),
142                       std::move(wire_reader_ref), std::move(cb));
143 }
144 
ConstructTxReceiver(grpc_core::RefCountedPtr<WireReader> wire_reader_ref,TransactionReceiver::OnTransactCb cb) const145 std::unique_ptr<TransactionReceiver> BinderForFuzzing::ConstructTxReceiver(
146     grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
147     TransactionReceiver::OnTransactCb cb) const {
148   auto tx_receiver = std::make_unique<TransactionReceiverForFuzzing>(
149       incoming_parcels_, wire_reader_ref, cb);
150   return tx_receiver;
151 }
152 
153 }  // namespace fuzzing
154 }  // namespace grpc_binder
155