memory_quota_fuzzer.cc
Go to the documentation of this file.
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 <stdint.h>
16 #include <sys/types.h>
17 
18 #include <functional>
19 #include <limits>
20 #include <map>
21 #include <memory>
22 #include <utility>
23 
24 #include "absl/strings/str_cat.h"
25 #include "absl/types/optional.h"
26 
29 #include <grpc/support/log.h>
30 
38 #include "src/libfuzzer/libfuzzer_macro.h"
40 #include "test/core/resource_quota/memory_quota_fuzzer.pb.h"
41 
42 bool squelch = true;
43 bool leak_check = true;
44 
45 namespace grpc_core {
46 namespace testing {
47 namespace {
48 ReclamationPass MapReclamationPass(memory_quota_fuzzer::Reclaimer::Pass pass) {
49  switch (pass) {
50  case memory_quota_fuzzer::Reclaimer::BENIGN:
52  case memory_quota_fuzzer::Reclaimer::IDLE:
54  case memory_quota_fuzzer::Reclaimer::DESTRUCTIVE:
56  default:
58  }
59 }
60 
61 class Fuzzer {
62  public:
63  void Run(const memory_quota_fuzzer::Msg& msg) {
64  ExecCtx exec_ctx;
65  RunMsg(msg);
66  do {
67  memory_quotas_.clear();
68  memory_allocators_.clear();
69  allocations_.clear();
70  exec_ctx.Flush();
71  } while (!memory_quotas_.empty() || !memory_allocators_.empty() ||
72  !allocations_.empty());
73  }
74 
75  private:
76  void RunMsg(const memory_quota_fuzzer::Msg& msg) {
77  for (int i = 0; i < msg.actions_size(); ++i) {
78  const auto& action = msg.actions(i);
79  switch (action.action_type_case()) {
80  case memory_quota_fuzzer::Action::kFlushExecCtx:
81  ExecCtx::Get()->Flush();
82  break;
83  case memory_quota_fuzzer::Action::kCreateQuota:
84  memory_quotas_.emplace(action.quota(),
85  MemoryQuota(absl::StrCat("quota-step-", i)));
86  break;
87  case memory_quota_fuzzer::Action::kDeleteQuota:
88  memory_quotas_.erase(action.quota());
89  break;
90  case memory_quota_fuzzer::Action::kCreateAllocator:
91  WithQuota(action.quota(), [this, action, i](MemoryQuota* q) {
92  memory_allocators_.emplace(
93  action.allocator(),
94  q->CreateMemoryOwner(absl::StrCat("allocator-step-", i)));
95  });
96  break;
97  case memory_quota_fuzzer::Action::kDeleteAllocator:
98  memory_allocators_.erase(action.allocator());
99  break;
100  case memory_quota_fuzzer::Action::kSetQuotaSize:
101  WithQuota(action.quota(), [action](MemoryQuota* q) {
102  q->SetSize(Clamp(action.set_quota_size(), uint64_t{0},
103  uint64_t{std::numeric_limits<ssize_t>::max()}));
104  });
105  break;
106  case memory_quota_fuzzer::Action::kCreateAllocation: {
107  auto min = action.create_allocation().min();
108  auto max = action.create_allocation().max();
109  if (min > max) break;
110  if (max > MemoryRequest::max_allowed_size()) break;
111  MemoryRequest req(min, max);
112  WithAllocator(
113  action.allocator(), [this, action, req](MemoryOwner* a) {
114  auto alloc = a->MakeReservation(req);
115  allocations_.emplace(action.allocation(), std::move(alloc));
116  });
117  } break;
118  case memory_quota_fuzzer::Action::kDeleteAllocation:
119  allocations_.erase(action.allocation());
120  break;
121  case memory_quota_fuzzer::Action::kPostReclaimer: {
123  auto cfg = action.post_reclaimer();
124  if (cfg.synchronous()) {
125  reclaimer = [this, cfg](absl::optional<ReclamationSweep>) {
126  RunMsg(cfg.msg());
127  };
128  } else {
129  reclaimer = [cfg, this](absl::optional<ReclamationSweep> sweep) {
130  struct Args {
132  memory_quota_fuzzer::Msg msg;
133  Fuzzer* fuzzer;
134  };
135  auto* args = new Args{std::move(sweep), cfg.msg(), this};
137  [](void* arg, grpc_error_handle) {
138  auto* args = static_cast<Args*>(arg);
139  args->fuzzer->RunMsg(args->msg);
140  delete args;
141  },
142  args, nullptr);
144  };
145  auto pass = MapReclamationPass(cfg.pass());
146  WithAllocator(
147  action.allocator(), [pass, reclaimer](MemoryOwner* a) {
148  // ensure called exactly once
149  auto call_checker = CallChecker::MakeOptional();
150  a->PostReclaimer(pass,
151  [reclaimer, call_checker](
152  absl::optional<ReclamationSweep> sweep) {
153  call_checker->Called();
154  reclaimer(std::move(sweep));
155  });
156  });
157  }
158  } break;
159  case memory_quota_fuzzer::Action::ACTION_TYPE_NOT_SET:
160  break;
161  }
162  }
163  }
164 
165  template <typename F>
166  void WithQuota(int quota, F f) {
167  auto it = memory_quotas_.find(quota);
168  if (it == memory_quotas_.end()) return;
169  f(&it->second);
170  }
171 
172  template <typename F>
173  void WithAllocator(int allocator, F f) {
174  auto it = memory_allocators_.find(allocator);
175  if (it == memory_allocators_.end()) return;
176  f(&it->second);
177  }
178 
179  std::map<int, MemoryQuota> memory_quotas_;
180  std::map<int, MemoryOwner> memory_allocators_;
181  std::map<int, MemoryAllocator::Reservation> allocations_;
182 };
183 
184 } // namespace
185 } // namespace testing
186 } // namespace grpc_core
187 
188 static void dont_log(gpr_log_func_args* /*args*/) {}
189 
190 DEFINE_PROTO_FUZZER(const memory_quota_fuzzer::Msg& msg) {
194  grpc_core::testing::Fuzzer().Run(msg);
195 }
trace.h
testing
Definition: aws_request_signer_test.cc:25
regen-readme.it
it
Definition: regen-readme.py:15
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
log.h
gpr_log_verbosity_init
GPRAPI void gpr_log_verbosity_init(void)
Definition: log.cc:115
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
grpc_core::ReclamationPass::kIdle
@ kIdle
grpc_event_engine::experimental::MemoryRequest::max_allowed_size
static constexpr size_t max_allowed_size()
Maximum allowable request size - hard coded to 1GB.
Definition: memory_request.h:38
fuzzer
Fuzzer * fuzzer
Definition: promise_fuzzer.cc:124
grpc_core
Definition: call_metric_recorder.h:31
useful.h
call_checker.h
closure.h
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
GRPC_CLOSURE_CREATE
#define GRPC_CLOSURE_CREATE(cb, cb_arg, scheduler)
Definition: closure.h:160
grpc_tracer_init
void grpc_tracer_init(const char *env_var_name)
Definition: debug/trace.cc:141
gpr_log_func_args
Definition: include/grpc/impl/codegen/log.h:77
DEBUG_LOCATION
#define DEBUG_LOCATION
Definition: debug_location.h:41
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
hpack_encoder_fixtures::Args
Args({0, 16384})
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
grpc_core::ExecCtx::Flush
bool Flush()
Definition: exec_ctx.cc:69
req
static uv_connect_t req
Definition: test-connection-fail.c:30
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::optional
Definition: abseil-cpp/absl/types/internal/optional.h:61
arg
Definition: cmdline.cc:40
DEFINE_PROTO_FUZZER
DEFINE_PROTO_FUZZER(const memory_quota_fuzzer::Msg &msg)
Definition: memory_quota_fuzzer.cc:190
error.h
memory_request.h
min
#define min(a, b)
Definition: qsort.h:83
F
#define F(b, c, d)
Definition: md4.c:112
stdint.h
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
debug_location.h
grpc_core::ReclamationPass::kBenign
@ kBenign
client.action
action
Definition: examples/python/xds/client.py:49
exec_ctx
grpc_core::ExecCtx exec_ctx
Definition: end2end_binder_transport_test.cc:75
allocations_
std::map< int, MemoryAllocator::Reservation > allocations_
Definition: memory_quota_fuzzer.cc:181
arg
struct arg arg
exec_ctx.h
closure
Definition: proxy.cc:59
grpc_core::ExecCtx::Run
static void Run(const DebugLocation &location, grpc_closure *closure, grpc_error_handle error)
Definition: exec_ctx.cc:98
memory_quota.h
grpc_core::ReclamationPass
ReclamationPass
Definition: memory_quota.h:62
leak_check
bool leak_check
Definition: memory_quota_fuzzer.cc:43
memory_allocator.h
googletest-break-on-failure-unittest.Run
def Run(command)
Definition: bloaty/third_party/googletest/googletest/test/googletest-break-on-failure-unittest.py:76
gpr_set_log_function
GPRAPI void gpr_set_log_function(gpr_log_func func)
Definition: log.cc:143
grpc_error
Definition: error_internal.h:42
function
std::function< bool(GrpcTool *, int, const char **, const CliCredentials &, GrpcToolOutputCallback)> function
Definition: grpc_tool.cc:250
squelch
bool squelch
Definition: memory_quota_fuzzer.cc:42
dont_log
static void dont_log(gpr_log_func_args *)
Definition: memory_quota_fuzzer.cc:188
memory_allocators_
std::map< int, MemoryOwner > memory_allocators_
Definition: memory_quota_fuzzer.cc:180
memory_quotas_
std::map< int, MemoryQuota > memory_quotas_
Definition: memory_quota_fuzzer.cc:179
grpc_core::ExecCtx::Get
static ExecCtx * Get()
Definition: exec_ctx.h:205
grpc_core::ReclamationPass::kDestructive
@ kDestructive
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:23