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