Line data Source code
1 : #include "fd_instr_harness.h"
2 : #include "fd_solfuzz_private.h"
3 : #include "../fd_executor.h"
4 : #include "../fd_runtime.h"
5 : #include "../fd_system_ids.h"
6 : #include "../../log_collector/fd_log_collector.h"
7 : #include "../program/fd_bpf_loader_serialization.h"
8 : #include "../../../ballet/sbpf/fd_sbpf_loader.h"
9 : #include "../../vm/fd_vm.h"
10 : #include "../../vm/fd_vm_private.h"
11 : #include "generated/vm.pb.h"
12 : #include "generated/vm_serialization.pb.h"
13 : #include "../fd_bank.h"
14 :
15 : static fd_sbpf_syscalls_t *
16 : fd_solfuzz_vm_syscall_lookup_func( fd_sbpf_syscalls_t * syscalls,
17 : const char * syscall_name,
18 7564 : size_t len) {
19 7564 : ulong i;
20 :
21 7564 : if (!syscall_name) return NULL;
22 :
23 301521 : for (i = 0; i < fd_sbpf_syscalls_slot_cnt(); ++i) {
24 301495 : if (!fd_sbpf_syscalls_key_inval(syscalls[i].key) && syscalls[i].name && strlen(syscalls[i].name) == len) {
25 11130 : if (!memcmp(syscalls[i].name, syscall_name, len)) {
26 7538 : return syscalls + i;
27 7538 : }
28 11130 : }
29 301495 : }
30 :
31 26 : return NULL;
32 7564 : }
33 :
34 : static ulong
35 : fd_solfuzz_vm_load_from_input_regions( fd_vm_input_region_t const * input,
36 : uint input_count,
37 : fd_exec_test_input_data_region_t ** output,
38 : uint * output_count,
39 : void * output_buf,
40 7345 : ulong output_bufsz ) {
41 : /* Each region emits a fixed-size record holding a hash of its contents,
42 : so the output size depends on the region count, not their contents. */
43 7345 : ulong output_sz = input_count * sizeof(fd_exec_test_input_data_region_t)
44 7345 : + alignof(fd_exec_test_input_data_region_t);
45 :
46 7345 : if( FD_UNLIKELY( !input_count || output_bufsz < output_sz ) ) {
47 0 : *output = NULL;
48 0 : *output_count = 0;
49 0 : return 0;
50 0 : }
51 :
52 7345 : FD_SCRATCH_ALLOC_INIT( l, output_buf );
53 7345 : *output = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_input_data_region_t),
54 7345 : input_count * sizeof (fd_exec_test_input_data_region_t) );
55 7345 : FD_TEST( *output );
56 7345 : *output_count = input_count;
57 :
58 15522 : for( ulong i=0; i<input_count; i++ ) {
59 8177 : fd_vm_input_region_t const * vm_region = &input[i];
60 8177 : fd_exec_test_input_data_region_t * out_region = &(*output)[i];
61 8177 : out_region->is_writable = vm_region->is_writable;
62 8177 : out_region->offset = vm_region->vaddr_offset;
63 :
64 8177 : out_region->content_hash = fd_solfuzz_hash( (void *)vm_region->haddr, vm_region->region_sz );
65 8177 : }
66 :
67 7345 : ulong end = FD_SCRATCH_ALLOC_FINI( l, 1UL );
68 7345 : return end - (ulong)output_buf; /* return the number of bytes written */
69 7345 : }
70 :
71 :
72 : ulong
73 : fd_solfuzz_pb_syscall_run( fd_solfuzz_runner_t * runner,
74 : void const * input_,
75 : void ** output_,
76 : void * output_buf,
77 7530 : ulong output_bufsz ) {
78 7530 : fd_exec_test_syscall_context_t const * input = fd_type_pun_const( input_ );
79 7530 : fd_exec_test_syscall_effects_t ** output = fd_type_pun( output_ );
80 :
81 : /* Create execution context */
82 7530 : const fd_exec_test_instr_context_t * input_instr_ctx = &input->instr_ctx;
83 7530 : fd_exec_instr_ctx_t ctx[1];
84 7530 : fd_solfuzz_pb_instr_ctx_create( runner, ctx, input_instr_ctx );
85 7530 : ulong frame_level = ULONG_MAX;
86 :
87 7530 : ctx->txn_out->err.exec_err = 0;
88 7530 : ctx->txn_out->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE;
89 7530 : ctx->bank = runner->bank;
90 :
91 : /* Capture outputs */
92 7530 : ulong output_end = (ulong)output_buf + output_bufsz;
93 7530 : FD_SCRATCH_ALLOC_INIT( l, output_buf );
94 7530 : fd_exec_test_syscall_effects_t * effects =
95 7530 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_syscall_effects_t),
96 7530 : sizeof (fd_exec_test_syscall_effects_t) );
97 7530 : if( FD_UNLIKELY( _l > output_end ) ) {
98 0 : goto error;
99 0 : }
100 :
101 7530 : if( input->vm_ctx.return_data.program_id && input->vm_ctx.return_data.program_id->size == sizeof(fd_pubkey_t) ) {
102 1901 : fd_memcpy( ctx->txn_out->details.return_data.program_id.uc, input->vm_ctx.return_data.program_id->bytes, sizeof(fd_pubkey_t) );
103 1901 : }
104 :
105 7530 : if( input->vm_ctx.return_data.data && input->vm_ctx.return_data.data->size>0U ) {
106 1283 : if( FD_UNLIKELY( input->vm_ctx.return_data.data->size>sizeof(ctx->txn_out->details.return_data.data) ) ) goto error;
107 1283 : ctx->txn_out->details.return_data.len = input->vm_ctx.return_data.data->size;
108 1283 : fd_memcpy( ctx->txn_out->details.return_data.data, input->vm_ctx.return_data.data->bytes, ctx->txn_out->details.return_data.len );
109 1283 : }
110 :
111 7530 : *effects = (fd_exec_test_syscall_effects_t){0};
112 :
113 : /* Set up the VM instance */
114 7530 : fd_spad_t * spad = runner->spad;
115 7530 : fd_sha256_t _sha[1];
116 7530 : fd_sha256_t * sha = fd_sha256_join( fd_sha256_new( _sha ) );
117 7530 : fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_spad_alloc_check( spad, fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() ) );
118 7530 : fd_vm_syscall_register_all( syscalls, 0 );
119 :
120 : /* Pull out the memory regions */
121 7530 : if( !input->has_vm_ctx ) {
122 0 : goto error;
123 0 : }
124 :
125 7530 : ulong rodata_sz = input->vm_ctx.rodata ? input->vm_ctx.rodata->size : 0UL;
126 7530 : uchar * rodata = fd_spad_alloc_check( spad, 8UL, rodata_sz );
127 7530 : if ( input->vm_ctx.rodata != NULL ) {
128 4074 : fd_memcpy( rodata, input->vm_ctx.rodata->bytes, rodata_sz );
129 4074 : }
130 :
131 7530 : if( input->vm_ctx.heap_max > FD_VM_HEAP_MAX ) {
132 0 : goto error;
133 0 : }
134 :
135 7530 : FD_TEST( input->vm_ctx.sbpf_version<=FD_SBPF_V3 );
136 :
137 7530 : fd_vm_t * vm = fd_vm_join( fd_vm_new( fd_spad_alloc_check( spad, fd_vm_align(), fd_vm_footprint() ) ) );
138 7530 : if ( !vm ) {
139 0 : goto error;
140 0 : }
141 :
142 : /* If the program ID account owner is the v1 BPF loader, then alignment is disabled (controlled by
143 : the `is_deprecated` flag) */
144 :
145 7530 : ulong input_sz = 0UL;
146 7530 : ulong pre_lens[256] = {0};
147 7530 : fd_vm_input_region_t input_mem_regions[1000] = {0}; /* We can have a max of (3 * num accounts + 1) regions */
148 7530 : fd_vm_acc_region_meta_t acc_region_metas[256] = {0}; /* instr acc idx to idx */
149 7530 : uint input_mem_regions_cnt = 0U;
150 7530 : int direct_mapping = FD_FEATURE_ACTIVE_BANK( ctx->bank, account_data_direct_mapping );
151 7530 : int syscall_parameter_address_restrictions = FD_FEATURE_ACTIVE_BANK( ctx->bank, syscall_parameter_address_restrictions );
152 7530 : int virtual_address_space_adjustments = FD_FEATURE_ACTIVE_BANK( ctx->bank, virtual_address_space_adjustments );
153 7530 : int direct_account_pointers_in_program_input = FD_FEATURE_ACTIVE_BANK( ctx->bank, direct_account_pointers_in_program_input );
154 :
155 7530 : uchar program_id_idx = ctx->instr->program_id;
156 7530 : fd_acc_t * program_acc = ctx->txn_out->accounts.account[program_id_idx];
157 7530 : uchar is_deprecated = ( program_id_idx < ctx->txn_out->accounts.cnt ) &&
158 7569 : ( !memcmp( program_acc->owner, fd_solana_bpf_loader_deprecated_program_id.key, sizeof(fd_pubkey_t) ) );
159 :
160 : /* Push the instruction onto the stack. This may also modify the sysvar instructions account, if its present. */
161 7530 : int stack_push_err = fd_instr_stack_push( ctx->runtime, ctx->txn_in, ctx->txn_out, (fd_instr_info_t *)ctx->instr );
162 7530 : if( FD_UNLIKELY( stack_push_err ) ) {
163 0 : FD_LOG_WARNING(( "instr stack push err" ));
164 0 : goto error;
165 0 : }
166 7530 : frame_level = ctx->runtime->instr.stack_sz-1UL;
167 7530 : ctx->runtime->bpf_loader_serialization.frame[ frame_level ] = fd_bpf_frames_acquire( ctx->runtime->bpf_frames, 0 );
168 :
169 7530 : ulong instr_data_offset = 0UL;
170 7530 : int err = fd_bpf_loader_input_serialize_parameters( ctx,
171 7530 : pre_lens,
172 7530 : input_mem_regions,
173 7530 : &input_mem_regions_cnt,
174 7530 : acc_region_metas,
175 7530 : virtual_address_space_adjustments,
176 7530 : direct_mapping,
177 7530 : direct_account_pointers_in_program_input,
178 7530 : is_deprecated,
179 7530 : &instr_data_offset,
180 7530 : &input_sz );
181 7530 : if( FD_UNLIKELY( err ) ) {
182 0 : FD_LOG_WARNING(( "bpf loader input serialize parameters err" ));
183 0 : goto error;
184 0 : }
185 :
186 7530 : fd_vm_init( vm,
187 7530 : ctx,
188 7530 : input->vm_ctx.heap_max,
189 7530 : ctx->txn_out->details.compute_budget.compute_meter,
190 7530 : rodata,
191 7530 : rodata_sz,
192 7530 : NULL, // TODO
193 7530 : 0, // TODO
194 7530 : 0, // TODO
195 7530 : 0, // TODO, text_sz
196 7530 : 0, // TODO
197 7530 : NULL, // TODO
198 7530 : input->vm_ctx.sbpf_version,
199 7530 : syscalls,
200 7530 : NULL, // TODO
201 7530 : sha,
202 7530 : input_mem_regions,
203 7530 : input_mem_regions_cnt,
204 7530 : acc_region_metas,
205 7530 : is_deprecated,
206 7530 : direct_mapping,
207 7530 : syscall_parameter_address_restrictions,
208 7530 : virtual_address_space_adjustments,
209 7530 : 0 /* dump_syscall_to_pb */,
210 7530 : 0UL /* r2 is set by the fuzzer below */ );
211 :
212 : // Override some execution state values from the syscall fuzzer input
213 : // This is so we can test if the syscall mutates any of these erroneously
214 7530 : vm->reg[0] = input->vm_ctx.r0;
215 7530 : vm->reg[1] = input->vm_ctx.r1;
216 7530 : vm->reg[2] = input->vm_ctx.r2;
217 7530 : vm->reg[3] = input->vm_ctx.r3;
218 7530 : vm->reg[4] = input->vm_ctx.r4;
219 7530 : vm->reg[5] = input->vm_ctx.r5;
220 7530 : vm->reg[6] = input->vm_ctx.r6;
221 7530 : vm->reg[7] = input->vm_ctx.r7;
222 7530 : vm->reg[8] = input->vm_ctx.r8;
223 7530 : vm->reg[9] = input->vm_ctx.r9;
224 7530 : vm->reg[10] = input->vm_ctx.r10;
225 7530 : vm->reg[11] = input->vm_ctx.r11;
226 :
227 7530 : fd_vm_mem_init_full( vm );
228 :
229 : // Override initial part of the heap, if specified the syscall fuzzer input
230 7530 : if( input->syscall_invocation.heap_prefix ) {
231 6587 : fd_memcpy( vm->heap, input->syscall_invocation.heap_prefix->bytes,
232 6587 : fd_ulong_min( input->syscall_invocation.heap_prefix->size, vm->heap_max ) );
233 6587 : }
234 :
235 : // Override initial part of the stack, if specified the syscall fuzzer input
236 7530 : if( input->syscall_invocation.stack_prefix ) {
237 3147 : fd_memcpy( vm->stack, input->syscall_invocation.stack_prefix->bytes,
238 3147 : fd_ulong_min( input->syscall_invocation.stack_prefix->size, FD_VM_STACK_MAX ) );
239 3147 : }
240 :
241 : // Look up the syscall to execute
242 7530 : char * syscall_name = (char *)input->syscall_invocation.function_name.bytes;
243 7530 : fd_sbpf_syscalls_t const * syscall = fd_solfuzz_vm_syscall_lookup_func(syscalls, syscall_name, input->syscall_invocation.function_name.size);
244 7530 : if( !syscall ) {
245 0 : goto error;
246 0 : }
247 :
248 : /* There's an instr ctx struct embedded in the txn ctx instr stack. */
249 7530 : fd_exec_instr_ctx_t * instr_ctx = &ctx->runtime->instr.stack[ ctx->runtime->instr.stack_sz - 1 ];
250 7530 : *instr_ctx = (fd_exec_instr_ctx_t) {
251 7530 : .instr = ctx->instr,
252 7530 : .txn_out = ctx->txn_out,
253 7530 : .runtime = ctx->runtime,
254 7530 : };
255 :
256 : /* Actually invoke the syscall */
257 7530 : int syscall_err = syscall->func( vm, vm->reg[1], vm->reg[2], vm->reg[3], vm->reg[4], vm->reg[5] );
258 7530 : int instr_end_err = fd_execute_instr_end( vm->instr_ctx, ctx->instr, syscall_err );
259 7530 : if( instr_end_err ) {
260 1731 : fd_log_collector_program_failure( vm->instr_ctx );
261 1731 : }
262 :
263 : /* Capture the effects */
264 7530 : int exec_err = vm->instr_ctx->txn_out->err.exec_err;
265 7530 : effects->error = 0;
266 7530 : if( instr_end_err ) {
267 1732 : if( exec_err==0 ) {
268 0 : FD_LOG_WARNING(( "TODO: syscall returns error, but exec_err not set. this is probably missing a log." ));
269 0 : effects->error = -1;
270 1732 : } else {
271 1732 : effects->error = (exec_err <= 0) ? -exec_err : -1;
272 :
273 : /* Map error kind, equivalent to:
274 : effects->error_kind = (fd_exec_test_err_kind_t)(vm->instr_ctx->txn_ctx->err.exec_err_kind); */
275 1732 : switch (vm->instr_ctx->txn_out->err.exec_err_kind) {
276 523 : case FD_EXECUTOR_ERR_KIND_EBPF:
277 523 : effects->error_kind = FD_EXEC_TEST_ERR_KIND_EBPF;
278 523 : break;
279 412 : case FD_EXECUTOR_ERR_KIND_SYSCALL:
280 412 : effects->error_kind = FD_EXEC_TEST_ERR_KIND_SYSCALL;
281 412 : break;
282 796 : case FD_EXECUTOR_ERR_KIND_INSTR:
283 796 : effects->error_kind = FD_EXEC_TEST_ERR_KIND_INSTRUCTION;
284 796 : break;
285 0 : default:
286 0 : effects->error_kind = FD_EXEC_TEST_ERR_KIND_UNSPECIFIED;
287 0 : break;
288 1732 : }
289 1732 : }
290 1732 : }
291 7528 : effects->r0 = instr_end_err ? 0 : vm->reg[0]; // Save only on success
292 7528 : effects->cu_avail = (ulong)vm->cu;
293 :
294 7528 : effects->heap_hash = fd_solfuzz_hash( vm->heap, vm->heap_max );
295 7528 : effects->stack_hash = fd_solfuzz_hash( vm->stack, FD_VM_STACK_MAX );
296 7528 : effects->rodata_hash = fd_solfuzz_hash( vm->rodata, vm->rodata_sz ? rodata_sz : 0UL );
297 :
298 7528 : effects->frame_count = vm->frame_cnt;
299 :
300 : /* Capture input regions */
301 7528 : ulong tmp_end = FD_SCRATCH_ALLOC_FINI( l, 1UL );
302 :
303 : /* Don't compare input data regions if execution failed and
304 : virtual_address_space_adjustments is enabled, because
305 : Agave leaks data into the input regions under these circumstances. */
306 7528 : ulong input_regions_size = 0UL;
307 7528 : if( syscall_err && virtual_address_space_adjustments ) {
308 219 : effects->input_data_regions = NULL;
309 219 : effects->input_data_regions_count = 0UL;
310 7309 : } else {
311 7309 : input_regions_size = fd_solfuzz_vm_load_from_input_regions(
312 7309 : vm->input_mem_regions,
313 7309 : vm->input_mem_regions_cnt,
314 7309 : &effects->input_data_regions,
315 7309 : &effects->input_data_regions_count,
316 7309 : (void *)tmp_end,
317 7309 : fd_ulong_sat_sub( output_end, tmp_end )
318 7309 : );
319 :
320 7341 : if( !!vm->input_mem_regions_cnt && !effects->input_data_regions ) {
321 0 : goto error;
322 0 : }
323 7309 : }
324 :
325 : /* Return the effects */
326 7528 : ulong actual_end = tmp_end + input_regions_size;
327 7528 : fd_bpf_frames_release( ctx->runtime->bpf_frames, ctx->runtime->bpf_loader_serialization.frame[ frame_level ] );
328 7528 : fd_solfuzz_pb_instr_ctx_destroy( runner, ctx );
329 :
330 7528 : *output = effects;
331 7528 : return actual_end - (ulong)output_buf;
332 :
333 0 : error:
334 0 : if( frame_level!=ULONG_MAX ) fd_bpf_frames_release( ctx->runtime->bpf_frames, ctx->runtime->bpf_loader_serialization.frame[ frame_level ] );
335 0 : fd_solfuzz_pb_instr_ctx_destroy( runner, ctx );
336 0 : return 0;
337 7528 : }
338 :
339 : ulong
340 : fd_solfuzz_pb_vm_serialize_run( fd_solfuzz_runner_t * runner,
341 : void const * input_,
342 : void ** output_,
343 : void * output_buf,
344 999 : ulong output_bufsz ) {
345 999 : fd_exec_test_instr_context_t const * input = fd_type_pun_const( input_ );
346 999 : fd_exec_test_vm_serialization_effects_t ** output = fd_type_pun( output_ );
347 :
348 : /* Create execution context */
349 999 : fd_exec_instr_ctx_t ctx[1];
350 999 : fd_solfuzz_pb_instr_ctx_create( runner, ctx, input );
351 :
352 999 : ctx->txn_out->err.exec_err = 0;
353 999 : ctx->txn_out->err.exec_err_kind = FD_EXECUTOR_ERR_KIND_NONE;
354 999 : ctx->bank = runner->bank;
355 :
356 : /* Capture outputs */
357 999 : ulong output_end = (ulong)output_buf + output_bufsz;
358 999 : FD_SCRATCH_ALLOC_INIT( l, output_buf );
359 999 : fd_exec_test_vm_serialization_effects_t * effects =
360 999 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_vm_serialization_effects_t),
361 999 : sizeof (fd_exec_test_vm_serialization_effects_t) );
362 999 : FD_TEST( _l <= output_end );
363 999 : *effects = (fd_exec_test_vm_serialization_effects_t){0};
364 :
365 : /* Determine feature flags and is_deprecated */
366 999 : int direct_mapping = FD_FEATURE_ACTIVE_BANK( ctx->bank, account_data_direct_mapping );
367 999 : int virtual_address_space_adjustments = FD_FEATURE_ACTIVE_BANK( ctx->bank, virtual_address_space_adjustments );
368 999 : int direct_account_pointers_in_program_input = FD_FEATURE_ACTIVE_BANK( ctx->bank, direct_account_pointers_in_program_input );
369 :
370 999 : uchar program_id_idx = ctx->instr->program_id;
371 999 : fd_acc_t * program_acc = ctx->txn_out->accounts.account[program_id_idx];
372 999 : uchar is_deprecated = ( program_id_idx < ctx->txn_out->accounts.cnt ) &&
373 999 : ( !memcmp( program_acc->owner, fd_solana_bpf_loader_deprecated_program_id.key, sizeof(fd_pubkey_t) ) );
374 :
375 : /* Push the instruction onto the stack */
376 999 : FD_TEST( !fd_instr_stack_push( ctx->runtime, ctx->txn_in, ctx->txn_out, (fd_instr_info_t *)ctx->instr ) );
377 999 : ulong frame_level = ctx->runtime->instr.stack_sz-1UL;
378 999 : uchar * serialized_buf = fd_bpf_frames_acquire( ctx->runtime->bpf_frames, 0 );
379 999 : ctx->runtime->bpf_loader_serialization.frame[ frame_level ] = serialized_buf;
380 :
381 : /* Call serialize_parameters */
382 999 : ulong input_sz = 0UL;
383 999 : ulong pre_lens[256] = {0};
384 999 : fd_vm_input_region_t input_mem_regions[1000] = {0};
385 999 : fd_vm_acc_region_meta_t acc_region_metas[256] = {0};
386 999 : uint input_mem_regions_cnt = 0U;
387 999 : ulong instr_data_offset = 0UL;
388 :
389 999 : int err = fd_bpf_loader_input_serialize_parameters(
390 999 : ctx,
391 999 : pre_lens,
392 999 : input_mem_regions,
393 999 : &input_mem_regions_cnt,
394 999 : acc_region_metas,
395 999 : virtual_address_space_adjustments,
396 999 : direct_mapping,
397 999 : direct_account_pointers_in_program_input,
398 999 : is_deprecated,
399 999 : &instr_data_offset,
400 999 : &input_sz
401 999 : );
402 :
403 999 : if( FD_UNLIKELY( err ) ) {
404 0 : effects->has_error = true;
405 0 : ulong actual_end = FD_SCRATCH_ALLOC_FINI( l, 1UL );
406 0 : fd_bpf_frames_release( ctx->runtime->bpf_frames, ctx->runtime->bpf_loader_serialization.frame[ frame_level ] );
407 0 : fd_solfuzz_pb_instr_ctx_destroy( runner, ctx );
408 0 : *output = effects;
409 0 : return actual_end - (ulong)output_buf;
410 0 : }
411 :
412 : /* Hash the serialized memory buffer. */
413 999 : effects->serialized_memory_hash = fd_hash( 0UL, serialized_buf, input_sz );
414 :
415 : /* Populate vm_input_memory_regions */
416 999 : effects->vm_input_memory_regions_count = (uint)input_mem_regions_cnt;
417 999 : effects->vm_input_memory_regions =
418 999 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_vm_input_memory_region_t),
419 999 : input_mem_regions_cnt * sizeof(fd_exec_test_vm_input_memory_region_t) );
420 999 : FD_TEST( _l <= output_end );
421 :
422 24655 : for( uint i=0; i<input_mem_regions_cnt; i++ ) {
423 23656 : fd_vm_input_region_t const * region = &input_mem_regions[i];
424 23656 : fd_exec_test_vm_input_memory_region_t * out = &effects->vm_input_memory_regions[i];
425 23656 : out->vm_address = FD_VM_MEM_MAP_INPUT_REGION_START + region->vaddr_offset;
426 23656 : out->region_size = region->region_sz;
427 23656 : out->is_writable = region->is_writable;
428 23656 : }
429 :
430 : /* Populate serialized_account_metadata */
431 999 : ulong num_ix_accounts = ctx->instr->acct_cnt;
432 999 : effects->serialized_account_metadata_count = (uint)num_ix_accounts;
433 999 : effects->serialized_account_metadata =
434 999 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_vm_serialized_account_metadata_t),
435 999 : num_ix_accounts * sizeof(fd_exec_test_vm_serialized_account_metadata_t) );
436 999 : FD_TEST( _l <= output_end );
437 :
438 76105 : for( ulong i=0; i<num_ix_accounts; i++ ) {
439 75106 : fd_vm_acc_region_meta_t const * meta = &acc_region_metas[i];
440 75106 : fd_exec_test_vm_serialized_account_metadata_t * out = &effects->serialized_account_metadata[i];
441 75106 : out->original_data_len = meta->original_data_len;
442 75106 : out->vm_data_addr = meta->vm_data_addr;
443 75106 : out->vm_key_addr = meta->vm_key_addr;
444 75106 : out->vm_lamports_addr = meta->vm_lamports_addr;
445 75106 : out->vm_owner_addr = meta->vm_owner_addr;
446 75106 : }
447 :
448 999 : ulong actual_end = FD_SCRATCH_ALLOC_FINI( l, 1UL );
449 999 : fd_bpf_frames_release( ctx->runtime->bpf_frames, ctx->runtime->bpf_loader_serialization.frame[ frame_level ] );
450 999 : fd_solfuzz_pb_instr_ctx_destroy( runner, ctx );
451 :
452 999 : *output = effects;
453 999 : return actual_end - (ulong)output_buf;
454 999 : }
|