Line data Source code
1 : #undef FD_SPAD_USE_HANDHOLDING
2 : #define FD_SPAD_USE_HANDHOLDING 1
3 :
4 : #include "fd_solfuzz_private.h"
5 : #include "fd_gossip_harness.h"
6 : #include "../../gossip/fd_gossip_message.h"
7 : #include "../../../ballet/txn/fd_compact_u16.h"
8 : #include "generated/gossip.pb.h"
9 :
10 : /* alloc_bytes allocates a pb_bytes_array_t on the spad and copies
11 : src[0..len) into it. */
12 :
13 : static pb_bytes_array_t *
14 : alloc_bytes( fd_spad_t * spad,
15 : uchar const * src,
16 0 : ulong len ) {
17 0 : pb_bytes_array_t * arr = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( len ) );
18 0 : arr->size = (pb_size_t)len;
19 0 : if( FD_LIKELY( len ) ) memcpy( arr->bytes, src, len );
20 0 : return arr;
21 0 : }
22 :
23 : /* Re-parse helpers that walk raw wire bytes to extract fields the
24 : main deserializer does not retain (addrs, sockets, extensions,
25 : compressed slots). */
26 :
27 0 : #define FD_VARINT_U64_MAX_BYTES (10UL) /* ceil(64/7) */
28 :
29 : static inline int
30 : skip_varint_u16( uchar const ** p,
31 0 : ulong * sz ) {
32 0 : ulong n = fd_cu16_dec_sz( *p, *sz );
33 0 : if( FD_UNLIKELY( !n ) ) return 0;
34 0 : *p += n;
35 0 : *sz -= n;
36 0 : return 1;
37 0 : }
38 :
39 : static inline int
40 : read_varint_u16( ushort * dst,
41 : uchar const ** p,
42 0 : ulong * sz ) {
43 0 : ulong n = fd_cu16_dec_sz( *p, *sz );
44 0 : if( FD_UNLIKELY( !n ) ) return 0;
45 0 : *dst = fd_cu16_dec_fixed( *p, n );
46 0 : *p += n;
47 0 : *sz -= n;
48 0 : return 1;
49 0 : }
50 :
51 : static inline int
52 : skip_varint_u64( uchar const ** p,
53 0 : ulong * sz ) {
54 0 : for( ulong i=0UL; i<FD_VARINT_U64_MAX_BYTES; i++ ) {
55 0 : if( FD_UNLIKELY( !*sz ) ) return 0;
56 0 : uchar byte = **p;
57 0 : (*p)++; (*sz)--;
58 0 : if( FD_LIKELY( !(byte & 0x80) ) ) return 1;
59 0 : }
60 0 : return 0;
61 0 : }
62 :
63 0 : #define NEED(n) do { if( FD_UNLIKELY( sz < (n) ) ) return; } while(0)
64 0 : #define SKIP(n) do { NEED(n); p += (n); sz -= (n); } while(0)
65 :
66 : static void
67 : reparse_contact_info_extra( fd_spad_t * spad,
68 : uchar const * value_start,
69 : ulong value_len,
70 0 : fd_exec_test_gossip_contact_info_t * ci ) {
71 0 : uchar const * p = value_start;
72 0 : ulong sz = value_len;
73 :
74 0 : SKIP( 68UL ); /* signature(64) + tag(4) */
75 0 : SKIP( 32UL ); /* origin(32) */
76 0 : if( FD_UNLIKELY( !skip_varint_u64( &p, &sz ) ) ) return; /* wallclock */
77 0 : SKIP( 10UL ); /* outset(8) + shred_version(2) */
78 :
79 0 : if( FD_UNLIKELY( !skip_varint_u16( &p, &sz ) ) ) return; /* major */
80 0 : if( FD_UNLIKELY( !skip_varint_u16( &p, &sz ) ) ) return; /* minor */
81 0 : if( FD_UNLIKELY( !skip_varint_u16( &p, &sz ) ) ) return; /* patch */
82 0 : SKIP( 4UL ); /* commit (u32) */
83 0 : SKIP( 4UL ); /* feature_set (u32) */
84 0 : if( FD_UNLIKELY( !skip_varint_u16( &p, &sz ) ) ) return; /* client */
85 :
86 : /* Addrs */
87 0 : ushort addrs_len = 0;
88 0 : if( FD_UNLIKELY( !read_varint_u16( &addrs_len, &p, &sz ) ) ) return;
89 0 : ci->addrs_count = (pb_size_t)addrs_len;
90 0 : if( addrs_len ) {
91 0 : ci->addrs = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_ip_addr_t),
92 0 : addrs_len * sizeof(fd_exec_test_gossip_ip_addr_t) );
93 0 : for( ushort i=0; i<addrs_len; i++ ) {
94 0 : NEED( 4UL );
95 0 : uint is_ip6 = FD_LOAD( uint, p );
96 0 : p += 4UL; sz -= 4UL;
97 0 : if( !is_ip6 ) {
98 0 : NEED( 4UL );
99 0 : ci->addrs[i].which_addr = FD_EXEC_TEST_GOSSIP_IP_ADDR_IPV4_TAG;
100 0 : ci->addrs[i].addr.ipv4 = fd_uint_bswap( FD_LOAD( uint, p ) );
101 0 : p += 4UL; sz -= 4UL;
102 0 : } else {
103 0 : NEED( 16UL );
104 0 : ci->addrs[i].which_addr = FD_EXEC_TEST_GOSSIP_IP_ADDR_IPV6_TAG;
105 0 : ci->addrs[i].addr.ipv6.hi = fd_ulong_bswap( FD_LOAD( ulong, p ) );
106 0 : ci->addrs[i].addr.ipv6.lo = fd_ulong_bswap( FD_LOAD( ulong, p+8UL ) );
107 0 : p += 16UL; sz -= 16UL;
108 0 : }
109 0 : }
110 0 : }
111 :
112 : /* Sockets */
113 0 : ushort sockets_len = 0;
114 0 : if( FD_UNLIKELY( !read_varint_u16( &sockets_len, &p, &sz ) ) ) return;
115 0 : ci->sockets_count = (pb_size_t)sockets_len;
116 0 : if( sockets_len ) {
117 0 : ci->sockets = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_socket_entry_t),
118 0 : sockets_len * sizeof(fd_exec_test_gossip_socket_entry_t) );
119 0 : for( ushort i=0; i<sockets_len; i++ ) {
120 0 : NEED( 2UL );
121 0 : ci->sockets[i].key = *p; p++; sz--;
122 0 : ci->sockets[i].index = *p; p++; sz--;
123 0 : ushort offset = 0;
124 0 : if( FD_UNLIKELY( !read_varint_u16( &offset, &p, &sz ) ) ) return;
125 0 : ci->sockets[i].offset = offset;
126 0 : }
127 0 : }
128 :
129 : /* Extensions (Agave always sends empty) */
130 0 : ci->extensions = NULL;
131 0 : }
132 :
133 : static void
134 : reparse_epoch_slots_extra( fd_spad_t * spad,
135 : uchar const * value_start,
136 : ulong value_len,
137 0 : fd_exec_test_gossip_epoch_slots_t * es ) {
138 0 : uchar const * p = value_start;
139 0 : ulong sz = value_len;
140 :
141 0 : SKIP( 68UL ); /* signature(64) + tag(4) */
142 0 : SKIP( 33UL ); /* index(1) + origin(32) */
143 :
144 : /* slots_len (u64) */
145 0 : NEED( 8UL );
146 0 : ulong slots_len = FD_LOAD( ulong, p );
147 0 : p += 8UL; sz -= 8UL;
148 :
149 0 : es->slots_count = (pb_size_t)slots_len;
150 0 : if( !slots_len ) {
151 0 : es->slots = NULL;
152 0 : return;
153 0 : }
154 :
155 0 : es->slots = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_compressed_slots_t),
156 0 : slots_len * sizeof(fd_exec_test_gossip_compressed_slots_t) );
157 :
158 0 : for( ulong i=0UL; i<slots_len; i++ ) {
159 0 : fd_exec_test_gossip_compressed_slots_t * slot = &es->slots[i];
160 :
161 0 : NEED( 4UL );
162 0 : uint is_uncompressed = FD_LOAD( uint, p );
163 0 : p += 4UL; sz -= 4UL;
164 :
165 0 : NEED( 8UL );
166 0 : slot->first_slot = FD_LOAD( ulong, p );
167 0 : p += 8UL; sz -= 8UL;
168 :
169 0 : NEED( 8UL );
170 0 : slot->num = FD_LOAD( ulong, p );
171 0 : p += 8UL; sz -= 8UL;
172 :
173 0 : if( is_uncompressed ) {
174 0 : slot->which_data = FD_EXEC_TEST_GOSSIP_COMPRESSED_SLOTS_UNCOMPRESSED_TAG;
175 0 : NEED( 1UL );
176 0 : uchar has_bits = *p; p++; sz--;
177 :
178 0 : if( has_bits ) {
179 0 : NEED( 8UL );
180 0 : ulong bits_cap = FD_LOAD( ulong, p );
181 0 : p += 8UL; sz -= 8UL;
182 0 : NEED( bits_cap );
183 0 : slot->data.uncompressed = alloc_bytes( spad, p, bits_cap );
184 0 : p += bits_cap; sz -= bits_cap;
185 0 : SKIP( 8UL ); /* bits_cnt */
186 0 : } else {
187 0 : slot->data.uncompressed = alloc_bytes( spad, NULL, 0UL );
188 0 : SKIP( 8UL ); /* bits_cnt */
189 0 : }
190 0 : } else {
191 0 : slot->which_data = FD_EXEC_TEST_GOSSIP_COMPRESSED_SLOTS_FLATE2_TAG;
192 0 : NEED( 8UL );
193 0 : ulong compressed_len = FD_LOAD( ulong, p );
194 0 : p += 8UL; sz -= 8UL;
195 0 : NEED( compressed_len );
196 0 : slot->data.flate2 = alloc_bytes( spad, p, compressed_len );
197 0 : p += compressed_len; sz -= compressed_len;
198 0 : }
199 0 : }
200 0 : }
201 :
202 : #undef SKIP
203 : #undef NEED
204 :
205 : static void
206 : convert_crds_data( fd_spad_t * spad,
207 : fd_gossip_value_t const * val,
208 : uchar const * raw_in,
209 0 : fd_exec_test_gossip_crds_data_t * out ) {
210 0 : switch( val->tag ) {
211 0 : case FD_GOSSIP_VALUE_CONTACT_INFO: {
212 0 : out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_CONTACT_INFO_TAG;
213 0 : fd_exec_test_gossip_contact_info_t * ci = &out->data.contact_info;
214 0 : ci->pubkey = alloc_bytes( spad, val->origin, sizeof(val->origin) );
215 0 : ci->wallclock = val->wallclock;
216 0 : ci->outset = val->contact_info->outset;
217 0 : ci->shred_version = val->contact_info->shred_version;
218 0 : ci->version_major = val->contact_info->version.major;
219 0 : ushort packed_minor = val->contact_info->version.minor;
220 0 : ushort prerelease_bits = (ushort)((packed_minor >> 14U) & 0x3U);
221 0 : ci->version_minor = (uint)(packed_minor & 0x3FFFU);
222 0 : ci->version_patch = prerelease_bits ? 0U : (uint)val->contact_info->version.patch;
223 0 : ci->version_commit = val->contact_info->version.commit;
224 0 : ci->version_feature_set = val->contact_info->version.feature_set;
225 0 : ci->version_client = val->contact_info->version.client;
226 0 : reparse_contact_info_extra( spad, raw_in + val->offset, val->length, ci );
227 0 : break;
228 0 : }
229 0 : case FD_GOSSIP_VALUE_VOTE:
230 0 : out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_VOTE_TAG;
231 0 : out->data.vote.index = val->vote->index;
232 0 : out->data.vote.from = alloc_bytes( spad, val->origin, sizeof(val->origin) );
233 0 : out->data.vote.wallclock = val->wallclock;
234 0 : out->data.vote.transaction = alloc_bytes( spad, val->vote->transaction, val->vote->transaction_len );
235 0 : break;
236 0 : case FD_GOSSIP_VALUE_LOWEST_SLOT:
237 0 : out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_LOWEST_SLOT_TAG;
238 0 : out->data.lowest_slot.index = 0;
239 0 : out->data.lowest_slot.from = alloc_bytes( spad, val->origin, sizeof(val->origin) );
240 0 : out->data.lowest_slot.lowest = val->lowest_slot->lowest;
241 0 : out->data.lowest_slot.wallclock = val->wallclock;
242 0 : break;
243 0 : case FD_GOSSIP_VALUE_EPOCH_SLOTS: {
244 0 : out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_EPOCH_SLOTS_TAG;
245 0 : fd_exec_test_gossip_epoch_slots_t * es = &out->data.epoch_slots;
246 0 : es->index = val->epoch_slots->index;
247 0 : es->from = alloc_bytes( spad, val->origin, sizeof(val->origin) );
248 0 : es->wallclock = val->wallclock;
249 0 : reparse_epoch_slots_extra( spad, raw_in + val->offset, val->length, es );
250 0 : break;
251 0 : }
252 0 : case FD_GOSSIP_VALUE_SNAPSHOT_HASHES: {
253 0 : out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_SNAPSHOT_HASHES_TAG;
254 0 : fd_exec_test_gossip_snapshot_hashes_t * sh = &out->data.snapshot_hashes;
255 0 : sh->from = alloc_bytes( spad, val->origin, sizeof(val->origin) );
256 0 : sh->full_slot = val->snapshot_hashes->full_slot;
257 0 : sh->full_hash = alloc_bytes( spad, val->snapshot_hashes->full_hash, sizeof(val->snapshot_hashes->full_hash) );
258 0 : sh->wallclock = val->wallclock;
259 0 : sh->incremental_count = (pb_size_t)val->snapshot_hashes->incremental_len;
260 0 : if( sh->incremental_count ) {
261 0 : sh->incremental = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_incremental_hash_t),
262 0 : sh->incremental_count * sizeof(fd_exec_test_gossip_incremental_hash_t) );
263 0 : for( ulong i=0UL; i<sh->incremental_count; i++ ) {
264 0 : sh->incremental[i].slot = val->snapshot_hashes->incremental[i].slot;
265 0 : sh->incremental[i].hash = alloc_bytes( spad, val->snapshot_hashes->incremental[i].hash,
266 0 : sizeof(val->snapshot_hashes->incremental[i].hash) );
267 0 : }
268 0 : }
269 0 : break;
270 0 : }
271 0 : case FD_GOSSIP_VALUE_DUPLICATE_SHRED:
272 0 : out->which_data = FD_EXEC_TEST_GOSSIP_CRDS_DATA_DUPLICATE_SHRED_TAG;
273 0 : out->data.duplicate_shred.index = val->duplicate_shred->index;
274 0 : out->data.duplicate_shred.from = alloc_bytes( spad, val->origin, sizeof(val->origin) );
275 0 : out->data.duplicate_shred.wallclock = val->wallclock;
276 0 : out->data.duplicate_shred.slot = val->duplicate_shred->slot;
277 0 : out->data.duplicate_shred.shred_index = 0;
278 0 : out->data.duplicate_shred.shred_type = 0;
279 0 : out->data.duplicate_shred.num_chunks = val->duplicate_shred->num_chunks;
280 0 : out->data.duplicate_shred.chunk_index = val->duplicate_shred->chunk_index;
281 0 : out->data.duplicate_shred.chunk = val->duplicate_shred->chunk_len
282 0 : ? alloc_bytes( spad, val->duplicate_shred->chunk,
283 0 : val->duplicate_shred->chunk_len )
284 0 : : NULL;
285 0 : break;
286 0 : default:
287 0 : out->which_data = 0;
288 0 : break;
289 0 : }
290 0 : }
291 :
292 : static void
293 : convert_crds_value( fd_spad_t * spad,
294 : fd_gossip_value_t const * val,
295 : uchar const * raw_in,
296 0 : fd_exec_test_gossip_crds_value_t * out ) {
297 0 : out->signature = alloc_bytes( spad, val->signature, sizeof(val->signature) );
298 0 : out->has_data = true;
299 0 : convert_crds_data( spad, val, raw_in, &out->data );
300 0 : }
301 :
302 : static void
303 : convert_crds_values( fd_spad_t * spad,
304 : fd_gossip_value_t const * vals,
305 : ulong vals_len,
306 : uchar const * raw_in,
307 : fd_exec_test_gossip_crds_value_t ** out_vals,
308 0 : pb_size_t * out_count ) {
309 0 : *out_count = (pb_size_t)vals_len;
310 0 : if( !vals_len ) {
311 0 : *out_vals = NULL;
312 0 : return;
313 0 : }
314 0 : *out_vals = fd_spad_alloc( spad, alignof(fd_exec_test_gossip_crds_value_t),
315 0 : vals_len * sizeof(fd_exec_test_gossip_crds_value_t) );
316 0 : for( ulong i=0UL; i<vals_len; i++ ) {
317 0 : convert_crds_value( spad, &vals[i], raw_in, &(*out_vals)[i] );
318 0 : }
319 0 : }
320 :
321 : static void
322 : convert_bloom( fd_spad_t * spad,
323 : fd_gossip_bloom_t const * bloom,
324 0 : fd_exec_test_gossip_bloom_t * out ) {
325 0 : out->keys_count = (pb_size_t)bloom->keys_len;
326 0 : if( bloom->keys_len ) {
327 0 : out->keys = fd_spad_alloc( spad, alignof(uint64_t), bloom->keys_len * sizeof(uint64_t) );
328 0 : memcpy( out->keys, bloom->keys, bloom->keys_len * sizeof(uint64_t) );
329 0 : }
330 : /* Copy only block_len() worth of u64 blocks, not bits_cap.
331 : https://github.com/tov/bv-rs/blob/0.11.1/src/bit_vec/mod.rs#L243-L245 */
332 0 : ulong bits_blocks = (bloom->bits_len + 63UL) / 64UL;
333 0 : ulong bits_byte_len = bits_blocks * sizeof(bloom->bits[0]);
334 0 : out->bits = alloc_bytes( spad, (uchar const *)bloom->bits, bits_byte_len );
335 : /* Mask trailing bits beyond bits_len in the last block of the
336 : protobuf copy. bv::BitVec::get_block() returns get_masked_block()
337 : which zeros bits past bit_len() in the last block.
338 : https://github.com/tov/bv-rs/blob/0.11.1/src/bit_vec/impls.rs#L30-L32
339 : https://github.com/tov/bv-rs/blob/0.11.1/src/traits/bits.rs#L134-L137 */
340 0 : if( bloom->bits_len & 63UL ) {
341 0 : ulong last = bits_blocks - 1UL;
342 0 : ulong mask = ( 2UL << ((bloom->bits_len - 1UL) & 63UL) ) - 1UL;
343 0 : ((ulong *)out->bits->bytes)[ last ] &= mask;
344 0 : }
345 0 : out->num_bits_set = bloom->num_bits_set;
346 0 : }
347 :
348 : static void
349 : convert_gossip_msg( fd_spad_t * spad,
350 : fd_gossip_message_t const * msg,
351 : uchar const * raw_in,
352 0 : fd_exec_test_gossip_msg_t * out ) {
353 0 : switch( msg->tag ) {
354 0 : case FD_GOSSIP_MESSAGE_PING:
355 0 : out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PING_TAG;
356 0 : out->msg.ping.from = alloc_bytes( spad, msg->ping->from, sizeof(msg->ping->from) );
357 0 : out->msg.ping.token = alloc_bytes( spad, msg->ping->token, sizeof(msg->ping->token) );
358 0 : out->msg.ping.signature = alloc_bytes( spad, msg->ping->signature, sizeof(msg->ping->signature) );
359 0 : break;
360 0 : case FD_GOSSIP_MESSAGE_PONG:
361 0 : out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PONG_TAG;
362 0 : out->msg.pong.from = alloc_bytes( spad, msg->pong->from, sizeof(msg->pong->from) );
363 0 : out->msg.pong.hash = alloc_bytes( spad, msg->pong->hash, sizeof(msg->pong->hash) );
364 0 : out->msg.pong.signature = alloc_bytes( spad, msg->pong->signature, sizeof(msg->pong->signature) );
365 0 : break;
366 0 : case FD_GOSSIP_MESSAGE_PULL_REQUEST: {
367 0 : out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PULL_REQUEST_TAG;
368 0 : fd_exec_test_gossip_pull_request_t * pr = &out->msg.pull_request;
369 0 : pr->has_filter = true;
370 0 : pr->filter.has_filter = true;
371 0 : convert_bloom( spad, msg->pull_request->crds_filter->filter, &pr->filter.filter );
372 0 : pr->filter.mask_bits = msg->pull_request->crds_filter->mask_bits;
373 : /* Agave canonicalizes the mask by setting all (64-mask_bits) low bits to 1.
374 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.6/gossip/src/crds_gossip_pull.rs#L152-L155 */
375 0 : ulong lsb_mask = (pr->filter.mask_bits>=64U) ? 0UL : (ULONG_MAX >> pr->filter.mask_bits);
376 0 : pr->filter.mask = msg->pull_request->crds_filter->mask | lsb_mask;
377 0 : pr->has_value = true;
378 0 : convert_crds_value( spad, msg->pull_request->contact_info, raw_in, &pr->value );
379 0 : break;
380 0 : }
381 0 : case FD_GOSSIP_MESSAGE_PULL_RESPONSE: {
382 0 : out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PULL_RESPONSE_TAG;
383 0 : fd_exec_test_gossip_pull_response_t * pr = &out->msg.pull_response;
384 0 : pr->pubkey = alloc_bytes( spad, msg->pull_response->from, sizeof(msg->pull_response->from) );
385 0 : convert_crds_values( spad, msg->pull_response->values,
386 0 : msg->pull_response->values_len,
387 0 : raw_in,
388 0 : &pr->values, &pr->values_count );
389 0 : break;
390 0 : }
391 0 : case FD_GOSSIP_MESSAGE_PUSH: {
392 0 : out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PUSH_MESSAGE_TAG;
393 0 : fd_exec_test_gossip_push_message_t * pm = &out->msg.push_message;
394 0 : pm->pubkey = alloc_bytes( spad, msg->push->from, sizeof(msg->push->from) );
395 0 : convert_crds_values( spad, msg->push->values,
396 0 : msg->push->values_len,
397 0 : raw_in,
398 0 : &pm->values, &pm->values_count );
399 0 : break;
400 0 : }
401 0 : case FD_GOSSIP_MESSAGE_PRUNE: {
402 0 : out->which_msg = FD_EXEC_TEST_GOSSIP_MSG_PRUNE_MESSAGE_TAG;
403 0 : fd_exec_test_gossip_prune_message_t * pm = &out->msg.prune_message;
404 0 : pm->pubkey = alloc_bytes( spad, msg->prune->sender, sizeof(msg->prune->sender) );
405 0 : pm->has_data = true;
406 0 : pm->data.pubkey = alloc_bytes( spad, msg->prune->pubkey, sizeof(msg->prune->pubkey) );
407 0 : pm->data.signature = alloc_bytes( spad, msg->prune->signature, sizeof(msg->prune->signature) );
408 0 : pm->data.destination = alloc_bytes( spad, msg->prune->destination, sizeof(msg->prune->destination) );
409 0 : pm->data.wallclock = msg->prune->wallclock;
410 0 : pm->data.prunes_count = (pb_size_t)msg->prune->prunes_len;
411 0 : if( msg->prune->prunes_len ) {
412 0 : pm->data.prunes = fd_spad_alloc( spad, alignof(pb_bytes_array_t *),
413 0 : msg->prune->prunes_len * sizeof(pb_bytes_array_t *) );
414 0 : for( ulong i=0UL; i<msg->prune->prunes_len; i++ ) {
415 0 : pm->data.prunes[i] = alloc_bytes( spad, msg->prune->prunes[i], sizeof(msg->prune->prunes[i]) );
416 0 : }
417 0 : }
418 0 : break;
419 0 : }
420 0 : default:
421 0 : out->which_msg = 0;
422 0 : break;
423 0 : }
424 0 : }
425 :
426 : int
427 : fd_solfuzz_gossip_decode( fd_solfuzz_runner_t * runner,
428 : uchar * out,
429 : ulong * out_sz,
430 : uchar const * in,
431 0 : ulong in_sz ) {
432 0 : if( FD_UNLIKELY( in_sz>FD_TPU_MTU ) ) FD_LOG_CRIT(( "invariant violation: gossip input %lu bytes exceeds MTU %lu, check fuzzer configuration", in_sz, FD_TPU_MTU ));
433 :
434 0 : fd_gossip_message_t * msg = fd_spad_alloc( runner->spad, alignof(fd_gossip_message_t), sizeof(fd_gossip_message_t) );
435 0 : fd_memset( msg, 0, sizeof(fd_gossip_message_t) );
436 0 : fd_exec_test_gossip_effects_t effects = FD_EXEC_TEST_GOSSIP_EFFECTS_INIT_ZERO;
437 :
438 0 : int ok = fd_gossip_message_deserialize( msg, in, in_sz );
439 0 : if( ok ) {
440 0 : effects.valid = true;
441 0 : effects.has_msg = true;
442 0 : convert_gossip_msg( runner->spad, msg, in, &effects.msg );
443 0 : } else {
444 0 : effects.valid = false;
445 0 : effects.has_msg = false;
446 0 : }
447 :
448 0 : return !!sol_compat_encode( out, out_sz, &effects, &fd_exec_test_gossip_effects_t_msg );
449 0 : }
|