Coverage Report

Created: 2026-10-28 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl_fuzzer/nghttp2_contract_shim.cc
Line
Count
Source
1
/*
2
 * Copyright (C) Max Dymond, <cmeister2@gmail.com>, et al.
3
 *
4
 * SPDX-License-Identifier: curl
5
 */
6
7
#include <nghttp2/nghttp2.h>
8
9
#include <array>
10
#include <atomic>
11
#include <cstdio>
12
#include <cstdlib>
13
#include <mutex>
14
#include <type_traits>
15
16
namespace {
17
18
// Fatal nghttp2 errors invalidate a session. Keep this assertion state out of
19
// the heap so allocation-failure fuzzing cannot disable or perturb the check.
20
struct PoisonedSession {
21
  nghttp2_session *session = nullptr;
22
  const char *fatal_api = nullptr;
23
  long long fatal_result = 0;
24
};
25
26
constexpr std::size_t kMaximumPoisonedSessions = 256;
27
std::array<PoisonedSession, kMaximumPoisonedSessions> poisoned_sessions{};
28
std::mutex poisoned_sessions_mutex;
29
std::atomic<std::size_t> poisoned_session_count{0};
30
31
[[noreturn]] void AbortContractViolation(const char *attempted_api,
32
0
                                         const PoisonedSession &poisoned) {
33
0
  std::fprintf(
34
0
      stderr,
35
0
      "nghttp2 contract assertion failed: %s called on session %p after "
36
0
      "%s returned %lld (< NGHTTP2_ERR_FATAL); only "
37
0
      "nghttp2_session_del is allowed\n",
38
0
      attempted_api, static_cast<void *>(poisoned.session), poisoned.fatal_api,
39
0
      poisoned.fatal_result);
40
0
  std::fflush(stderr);
41
0
  std::abort();
42
0
}
43
44
[[noreturn]] void AbortTrackingOverflow(nghttp2_session *session,
45
                                        const char *fatal_api,
46
0
                                        long long fatal_result) {
47
0
  std::fprintf(stderr,
48
0
               "nghttp2 contract assertion failed: cannot track session %p "
49
0
               "after %s returned %lld; poisoned-session table is full\n",
50
0
               static_cast<void *>(session), fatal_api, fatal_result);
51
0
  std::fflush(stderr);
52
0
  std::abort();
53
0
}
54
55
6.85M
void CheckUsable(nghttp2_session *session, const char *attempted_api) {
56
6.85M
  if (session == nullptr ||
57
6.85M
      poisoned_session_count.load(std::memory_order_acquire) == 0) {
58
6.82M
    return;
59
6.82M
  }
60
61
29.5k
  PoisonedSession poisoned;
62
29.5k
  {
63
29.5k
    std::lock_guard<std::mutex> lock(poisoned_sessions_mutex);
64
7.55M
    for (const PoisonedSession &entry : poisoned_sessions) {
65
7.55M
      if (entry.session == session) {
66
0
        poisoned = entry;
67
0
        break;
68
0
      }
69
7.55M
    }
70
29.5k
  }
71
29.5k
  if (poisoned.session != nullptr) {
72
0
    AbortContractViolation(attempted_api, poisoned);
73
0
  }
74
29.5k
}
75
76
168k
void ForgetSession(nghttp2_session *session) {
77
168k
  if (session == nullptr ||
78
168k
      poisoned_session_count.load(std::memory_order_acquire) == 0) {
79
167k
    return;
80
167k
  }
81
82
1.67k
  std::lock_guard<std::mutex> lock(poisoned_sessions_mutex);
83
25.6k
  for (PoisonedSession &entry : poisoned_sessions) {
84
25.6k
    if (entry.session == session) {
85
1.57k
      entry = PoisonedSession{};
86
1.57k
      poisoned_session_count.fetch_sub(1, std::memory_order_release);
87
1.57k
      return;
88
1.57k
    }
89
25.6k
  }
90
1.67k
}
91
92
1.66M
void RecordResult(nghttp2_session *session, const char *api, long long result) {
93
1.66M
  if (session == nullptr || result >= NGHTTP2_ERR_FATAL) {
94
1.66M
    return;
95
1.66M
  }
96
97
1.59k
  bool table_full = false;
98
1.59k
  {
99
1.59k
    std::lock_guard<std::mutex> lock(poisoned_sessions_mutex);
100
1.59k
    PoisonedSession *empty_entry = nullptr;
101
403k
    for (PoisonedSession &entry : poisoned_sessions) {
102
403k
      if (entry.session == session) {
103
        // Preserve the first fatal result; it is the point at which the
104
        // application was required to stop using this session.
105
17
        return;
106
17
      }
107
403k
      if (entry.session == nullptr && empty_entry == nullptr) {
108
1.57k
        empty_entry = &entry;
109
1.57k
      }
110
403k
    }
111
1.57k
    if (empty_entry != nullptr) {
112
1.57k
      empty_entry->session = session;
113
1.57k
      empty_entry->fatal_api = api;
114
1.57k
      empty_entry->fatal_result = result;
115
1.57k
      poisoned_session_count.fetch_add(1, std::memory_order_release);
116
1.57k
    } else {
117
0
      table_full = true;
118
0
    }
119
1.57k
  }
120
1.57k
  if (table_full) {
121
0
    AbortTrackingOverflow(session, api, result);
122
0
  }
123
1.57k
}
124
125
} // namespace
126
127
// GNU ld and lld provide each __real_* symbol when the final link uses the
128
// matching --wrap option. decltype keeps these declarations tied to the
129
// installed nghttp2 headers and makes signature drift a compile-time failure.
130
extern "C" decltype(nghttp2_session_client_new3)
131
    __real_nghttp2_session_client_new3;
132
extern "C" decltype(nghttp2_session_del) __real_nghttp2_session_del;
133
extern "C" decltype(nghttp2_session_check_request_allowed)
134
    __real_nghttp2_session_check_request_allowed;
135
extern "C" decltype(nghttp2_session_consume) __real_nghttp2_session_consume;
136
extern "C" decltype(nghttp2_session_get_local_window_size)
137
    __real_nghttp2_session_get_local_window_size;
138
extern "C" decltype(nghttp2_session_get_remote_settings)
139
    __real_nghttp2_session_get_remote_settings;
140
extern "C" decltype(nghttp2_session_get_remote_window_size)
141
    __real_nghttp2_session_get_remote_window_size;
142
extern "C" decltype(nghttp2_session_get_stream_effective_local_window_size)
143
    __real_nghttp2_session_get_stream_effective_local_window_size;
144
extern "C" decltype(nghttp2_session_get_stream_effective_recv_data_length)
145
    __real_nghttp2_session_get_stream_effective_recv_data_length;
146
extern "C" decltype(nghttp2_session_get_stream_remote_window_size)
147
    __real_nghttp2_session_get_stream_remote_window_size;
148
extern "C" decltype(nghttp2_session_get_stream_user_data)
149
    __real_nghttp2_session_get_stream_user_data;
150
extern "C" decltype(nghttp2_session_mem_recv) __real_nghttp2_session_mem_recv;
151
extern "C" decltype(nghttp2_session_resume_data)
152
    __real_nghttp2_session_resume_data;
153
extern "C" decltype(nghttp2_session_send) __real_nghttp2_session_send;
154
extern "C" decltype(nghttp2_session_set_local_window_size)
155
    __real_nghttp2_session_set_local_window_size;
156
extern "C" decltype(nghttp2_session_set_stream_user_data)
157
    __real_nghttp2_session_set_stream_user_data;
158
extern "C" decltype(nghttp2_session_upgrade2) __real_nghttp2_session_upgrade2;
159
extern "C" decltype(nghttp2_session_want_read) __real_nghttp2_session_want_read;
160
extern "C" decltype(nghttp2_session_want_write)
161
    __real_nghttp2_session_want_write;
162
extern "C" decltype(nghttp2_submit_goaway) __real_nghttp2_submit_goaway;
163
extern "C" decltype(nghttp2_submit_ping) __real_nghttp2_submit_ping;
164
extern "C" decltype(nghttp2_submit_priority) __real_nghttp2_submit_priority;
165
extern "C" decltype(nghttp2_submit_request) __real_nghttp2_submit_request;
166
extern "C" decltype(nghttp2_submit_rst_stream) __real_nghttp2_submit_rst_stream;
167
extern "C" decltype(nghttp2_submit_settings) __real_nghttp2_submit_settings;
168
extern "C" decltype(nghttp2_submit_window_update)
169
    __real_nghttp2_submit_window_update;
170
171
extern "C" int __wrap_nghttp2_session_client_new3(
172
    nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks,
173
84.5k
    void *user_data, const nghttp2_option *option, nghttp2_mem *mem) {
174
84.5k
  const int result = __real_nghttp2_session_client_new3(session_ptr, callbacks,
175
84.5k
                                                        user_data, option, mem);
176
84.5k
  if (result == 0 && session_ptr != nullptr) {
177
    // A custom allocator may deliberately reuse a recently deleted address.
178
84.4k
    ForgetSession(*session_ptr);
179
84.4k
  }
180
84.5k
  return result;
181
84.5k
}
182
static_assert(std::is_same<decltype(nghttp2_session_client_new3),
183
                           decltype(__wrap_nghttp2_session_client_new3)>::value,
184
              "nghttp2_session_client_new3 signature changed");
185
186
84.4k
extern "C" void __wrap_nghttp2_session_del(nghttp2_session *session) {
187
  // Deallocation is the sole operation permitted after a fatal return.
188
84.4k
  ForgetSession(session);
189
84.4k
  __real_nghttp2_session_del(session);
190
84.4k
}
191
static_assert(std::is_same<decltype(nghttp2_session_del),
192
                           decltype(__wrap_nghttp2_session_del)>::value,
193
              "nghttp2_session_del signature changed");
194
195
#define DEFINE_CHECKED_WRAPPER(name, parameters, arguments)                    \
196
  extern "C" auto __wrap_##name parameters                                     \
197
5.18M
      ->decltype(__real_##name arguments) {                                    \
198
5.18M
    CheckUsable(session, #name);                                               \
199
5.18M
    return __real_##name arguments;                                            \
200
5.18M
  }                                                                            \
__wrap_nghttp2_session_check_request_allowed
Line
Count
Source
197
326k
      ->decltype(__real_##name arguments) {                                    \
198
326k
    CheckUsable(session, #name);                                               \
199
326k
    return __real_##name arguments;                                            \
200
326k
  }                                                                            \
__wrap_nghttp2_session_get_local_window_size
Line
Count
Source
197
51.9k
      ->decltype(__real_##name arguments) {                                    \
198
51.9k
    CheckUsable(session, #name);                                               \
199
51.9k
    return __real_##name arguments;                                            \
200
51.9k
  }                                                                            \
__wrap_nghttp2_session_get_remote_settings
Line
Count
Source
197
167k
      ->decltype(__real_##name arguments) {                                    \
198
167k
    CheckUsable(session, #name);                                               \
199
167k
    return __real_##name arguments;                                            \
200
167k
  }                                                                            \
__wrap_nghttp2_session_get_remote_window_size
Line
Count
Source
197
230k
      ->decltype(__real_##name arguments) {                                    \
198
230k
    CheckUsable(session, #name);                                               \
199
230k
    return __real_##name arguments;                                            \
200
230k
  }                                                                            \
__wrap_nghttp2_session_get_stream_effective_local_window_size
Line
Count
Source
197
144k
      ->decltype(__real_##name arguments) {                                    \
198
144k
    CheckUsable(session, #name);                                               \
199
144k
    return __real_##name arguments;                                            \
200
144k
  }                                                                            \
__wrap_nghttp2_session_get_stream_effective_recv_data_length
Line
Count
Source
197
52.4k
      ->decltype(__real_##name arguments) {                                    \
198
52.4k
    CheckUsable(session, #name);                                               \
199
52.4k
    return __real_##name arguments;                                            \
200
52.4k
  }                                                                            \
__wrap_nghttp2_session_get_stream_remote_window_size
Line
Count
Source
197
230k
      ->decltype(__real_##name arguments) {                                    \
198
230k
    CheckUsable(session, #name);                                               \
199
230k
    return __real_##name arguments;                                            \
200
230k
  }                                                                            \
__wrap_nghttp2_session_get_stream_user_data
Line
Count
Source
197
1.09M
      ->decltype(__real_##name arguments) {                                    \
198
1.09M
    CheckUsable(session, #name);                                               \
199
1.09M
    return __real_##name arguments;                                            \
200
1.09M
  }                                                                            \
__wrap_nghttp2_session_want_read
Line
Count
Source
197
1.07M
      ->decltype(__real_##name arguments) {                                    \
198
1.07M
    CheckUsable(session, #name);                                               \
199
1.07M
    return __real_##name arguments;                                            \
200
1.07M
  }                                                                            \
__wrap_nghttp2_session_want_write
Line
Count
Source
197
1.81M
      ->decltype(__real_##name arguments) {                                    \
198
1.81M
    CheckUsable(session, #name);                                               \
199
1.81M
    return __real_##name arguments;                                            \
200
1.81M
  }                                                                            \
201
  static_assert(std::is_same<decltype(name), decltype(__wrap_##name)>::value,  \
202
                #name " signature changed");
203
204
#define DEFINE_RESULT_WRAPPER(name, parameters, arguments)                     \
205
  extern "C" auto __wrap_##name parameters                                     \
206
1.66M
      ->decltype(__real_##name arguments) {                                    \
207
1.66M
    CheckUsable(session, #name);                                               \
208
1.66M
    const auto result = __real_##name arguments;                               \
209
1.66M
    RecordResult(session, #name, static_cast<long long>(result));              \
210
1.66M
    return result;                                                             \
211
1.66M
  }                                                                            \
__wrap_nghttp2_session_consume
Line
Count
Source
206
6.44k
      ->decltype(__real_##name arguments) {                                    \
207
6.44k
    CheckUsable(session, #name);                                               \
208
6.44k
    const auto result = __real_##name arguments;                               \
209
6.44k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
6.44k
    return result;                                                             \
211
6.44k
  }                                                                            \
__wrap_nghttp2_session_mem_recv
Line
Count
Source
206
218k
      ->decltype(__real_##name arguments) {                                    \
207
218k
    CheckUsable(session, #name);                                               \
208
218k
    const auto result = __real_##name arguments;                               \
209
218k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
218k
    return result;                                                             \
211
218k
  }                                                                            \
__wrap_nghttp2_session_resume_data
Line
Count
Source
206
225k
      ->decltype(__real_##name arguments) {                                    \
207
225k
    CheckUsable(session, #name);                                               \
208
225k
    const auto result = __real_##name arguments;                               \
209
225k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
225k
    return result;                                                             \
211
225k
  }                                                                            \
__wrap_nghttp2_session_send
Line
Count
Source
206
500k
      ->decltype(__real_##name arguments) {                                    \
207
500k
    CheckUsable(session, #name);                                               \
208
500k
    const auto result = __real_##name arguments;                               \
209
500k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
500k
    return result;                                                             \
211
500k
  }                                                                            \
__wrap_nghttp2_session_set_local_window_size
Line
Count
Source
206
176k
      ->decltype(__real_##name arguments) {                                    \
207
176k
    CheckUsable(session, #name);                                               \
208
176k
    const auto result = __real_##name arguments;                               \
209
176k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
176k
    return result;                                                             \
211
176k
  }                                                                            \
__wrap_nghttp2_session_set_stream_user_data
Line
Count
Source
206
142k
      ->decltype(__real_##name arguments) {                                    \
207
142k
    CheckUsable(session, #name);                                               \
208
142k
    const auto result = __real_##name arguments;                               \
209
142k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
142k
    return result;                                                             \
211
142k
  }                                                                            \
__wrap_nghttp2_session_upgrade2
Line
Count
Source
206
10.5k
      ->decltype(__real_##name arguments) {                                    \
207
10.5k
    CheckUsable(session, #name);                                               \
208
10.5k
    const auto result = __real_##name arguments;                               \
209
10.5k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
10.5k
    return result;                                                             \
211
10.5k
  }                                                                            \
__wrap_nghttp2_submit_goaway
Line
Count
Source
206
34.9k
      ->decltype(__real_##name arguments) {                                    \
207
34.9k
    CheckUsable(session, #name);                                               \
208
34.9k
    const auto result = __real_##name arguments;                               \
209
34.9k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
34.9k
    return result;                                                             \
211
34.9k
  }                                                                            \
__wrap_nghttp2_submit_ping
Line
Count
Source
206
17.1k
      ->decltype(__real_##name arguments) {                                    \
207
17.1k
    CheckUsable(session, #name);                                               \
208
17.1k
    const auto result = __real_##name arguments;                               \
209
17.1k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
17.1k
    return result;                                                             \
211
17.1k
  }                                                                            \
__wrap_nghttp2_submit_priority
Line
Count
Source
206
1.43k
      ->decltype(__real_##name arguments) {                                    \
207
1.43k
    CheckUsable(session, #name);                                               \
208
1.43k
    const auto result = __real_##name arguments;                               \
209
1.43k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
1.43k
    return result;                                                             \
211
1.43k
  }                                                                            \
__wrap_nghttp2_submit_request
Line
Count
Source
206
86.6k
      ->decltype(__real_##name arguments) {                                    \
207
86.6k
    CheckUsable(session, #name);                                               \
208
86.6k
    const auto result = __real_##name arguments;                               \
209
86.6k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
86.6k
    return result;                                                             \
211
86.6k
  }                                                                            \
__wrap_nghttp2_submit_rst_stream
Line
Count
Source
206
70.9k
      ->decltype(__real_##name arguments) {                                    \
207
70.9k
    CheckUsable(session, #name);                                               \
208
70.9k
    const auto result = __real_##name arguments;                               \
209
70.9k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
70.9k
    return result;                                                             \
211
70.9k
  }                                                                            \
__wrap_nghttp2_submit_settings
Line
Count
Source
206
86.1k
      ->decltype(__real_##name arguments) {                                    \
207
86.1k
    CheckUsable(session, #name);                                               \
208
86.1k
    const auto result = __real_##name arguments;                               \
209
86.1k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
86.1k
    return result;                                                             \
211
86.1k
  }                                                                            \
__wrap_nghttp2_submit_window_update
Line
Count
Source
206
87.9k
      ->decltype(__real_##name arguments) {                                    \
207
87.9k
    CheckUsable(session, #name);                                               \
208
87.9k
    const auto result = __real_##name arguments;                               \
209
87.9k
    RecordResult(session, #name, static_cast<long long>(result));              \
210
87.9k
    return result;                                                             \
211
87.9k
  }                                                                            \
212
  static_assert(std::is_same<decltype(name), decltype(__wrap_##name)>::value,  \
213
                #name " signature changed");
214
215
DEFINE_CHECKED_WRAPPER(nghttp2_session_check_request_allowed,
216
                       (nghttp2_session * session), (session))
217
DEFINE_RESULT_WRAPPER(nghttp2_session_consume,
218
                      (nghttp2_session * session, int32_t stream_id,
219
                       size_t size),
220
                      (session, stream_id, size))
221
DEFINE_CHECKED_WRAPPER(nghttp2_session_get_local_window_size,
222
                       (nghttp2_session * session), (session))
223
DEFINE_CHECKED_WRAPPER(nghttp2_session_get_remote_settings,
224
                       (nghttp2_session * session, nghttp2_settings_id id),
225
                       (session, id))
226
DEFINE_CHECKED_WRAPPER(nghttp2_session_get_remote_window_size,
227
                       (nghttp2_session * session), (session))
228
DEFINE_CHECKED_WRAPPER(nghttp2_session_get_stream_effective_local_window_size,
229
                       (nghttp2_session * session, int32_t stream_id),
230
                       (session, stream_id))
231
DEFINE_CHECKED_WRAPPER(nghttp2_session_get_stream_effective_recv_data_length,
232
                       (nghttp2_session * session, int32_t stream_id),
233
                       (session, stream_id))
234
DEFINE_CHECKED_WRAPPER(nghttp2_session_get_stream_remote_window_size,
235
                       (nghttp2_session * session, int32_t stream_id),
236
                       (session, stream_id))
237
DEFINE_CHECKED_WRAPPER(nghttp2_session_get_stream_user_data,
238
                       (nghttp2_session * session, int32_t stream_id),
239
                       (session, stream_id))
240
DEFINE_RESULT_WRAPPER(nghttp2_session_mem_recv,
241
                      (nghttp2_session * session, const uint8_t *input,
242
                       size_t input_length),
243
                      (session, input, input_length))
244
DEFINE_RESULT_WRAPPER(nghttp2_session_resume_data,
245
                      (nghttp2_session * session, int32_t stream_id),
246
                      (session, stream_id))
247
DEFINE_RESULT_WRAPPER(nghttp2_session_send, (nghttp2_session * session),
248
                      (session))
249
DEFINE_RESULT_WRAPPER(nghttp2_session_set_local_window_size,
250
                      (nghttp2_session * session, uint8_t flags,
251
                       int32_t stream_id, int32_t window_size),
252
                      (session, flags, stream_id, window_size))
253
DEFINE_RESULT_WRAPPER(nghttp2_session_set_stream_user_data,
254
                      (nghttp2_session * session, int32_t stream_id,
255
                       void *stream_user_data),
256
                      (session, stream_id, stream_user_data))
257
DEFINE_RESULT_WRAPPER(nghttp2_session_upgrade2,
258
                      (nghttp2_session * session,
259
                       const uint8_t *settings_payload,
260
                       size_t settings_payload_length, int head_request,
261
                       void *stream_user_data),
262
                      (session, settings_payload, settings_payload_length,
263
                       head_request, stream_user_data))
264
DEFINE_CHECKED_WRAPPER(nghttp2_session_want_read, (nghttp2_session * session),
265
                       (session))
266
DEFINE_CHECKED_WRAPPER(nghttp2_session_want_write, (nghttp2_session * session),
267
                       (session))
268
DEFINE_RESULT_WRAPPER(nghttp2_submit_goaway,
269
                      (nghttp2_session * session, uint8_t flags,
270
                       int32_t last_stream_id, uint32_t error_code,
271
                       const uint8_t *opaque_data, size_t opaque_data_length),
272
                      (session, flags, last_stream_id, error_code, opaque_data,
273
                       opaque_data_length))
274
DEFINE_RESULT_WRAPPER(nghttp2_submit_ping,
275
                      (nghttp2_session * session, uint8_t flags,
276
                       const uint8_t *opaque_data),
277
                      (session, flags, opaque_data))
278
DEFINE_RESULT_WRAPPER(nghttp2_submit_priority,
279
                      (nghttp2_session * session, uint8_t flags,
280
                       int32_t stream_id,
281
                       const nghttp2_priority_spec *priority_spec),
282
                      (session, flags, stream_id, priority_spec))
283
DEFINE_RESULT_WRAPPER(nghttp2_submit_request,
284
                      (nghttp2_session * session,
285
                       const nghttp2_priority_spec *priority_spec,
286
                       const nghttp2_nv *headers, size_t header_count,
287
                       const nghttp2_data_provider *data_provider,
288
                       void *stream_user_data),
289
                      (session, priority_spec, headers, header_count,
290
                       data_provider, stream_user_data))
291
DEFINE_RESULT_WRAPPER(nghttp2_submit_rst_stream,
292
                      (nghttp2_session * session, uint8_t flags,
293
                       int32_t stream_id, uint32_t error_code),
294
                      (session, flags, stream_id, error_code))
295
DEFINE_RESULT_WRAPPER(nghttp2_submit_settings,
296
                      (nghttp2_session * session, uint8_t flags,
297
                       const nghttp2_settings_entry *settings,
298
                       size_t settings_count),
299
                      (session, flags, settings, settings_count))
300
DEFINE_RESULT_WRAPPER(nghttp2_submit_window_update,
301
                      (nghttp2_session * session, uint8_t flags,
302
                       int32_t stream_id, int32_t window_size_increment),
303
                      (session, flags, stream_id, window_size_increment))
304
305
#undef DEFINE_RESULT_WRAPPER
306
#undef DEFINE_CHECKED_WRAPPER