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