Line data Source code
1 : #include "fd_solfuzz.h"
2 : #include "fd_solfuzz_private.h"
3 : #include "fd_sol_compat.h"
4 : #include "../../capture/fd_solcap_writer.h"
5 : #include "fd_gossip_harness.h"
6 :
7 : #include "generated/block.pb.h"
8 : #include "generated/instr.pb.h"
9 : #include "generated/vm.pb.h"
10 : #include "generated/txn.pb.h"
11 : #include "generated/bundle.pb.h"
12 : #include "generated/cost.pb.h"
13 : #include "generated/elf.pb.h"
14 : #include "generated/vm_serialization.pb.h"
15 : #include "generated/shred.pb.h"
16 :
17 : #include <errno.h>
18 : #include <fcntl.h>
19 : #include <stdlib.h>
20 : #include <unistd.h>
21 :
22 : static fd_wksp_t * wksp = NULL;
23 : static fd_solfuzz_runner_t * runner = NULL;
24 :
25 : static fd_solfuzz_runner_t *
26 0 : sol_compat_setup_runner( fd_solfuzz_runner_options_t const * options ) {
27 0 : runner = fd_solfuzz_runner_new( wksp, 3UL, options );
28 0 : if( FD_UNLIKELY( !runner ) ) {
29 0 : FD_LOG_ERR(( "fd_solfuzz_runner_new() failed" ));
30 0 : return NULL;
31 0 : }
32 :
33 0 : char const * solcap_path = getenv( "FD_SOLCAP" );
34 0 : if( solcap_path ) {
35 0 : int fd = open( solcap_path, O_WRONLY | O_CREAT | O_TRUNC, 0644 );
36 0 : if( FD_UNLIKELY( fd == -1 ) ) {
37 0 : FD_LOG_ERR(( "open($FD_SOLCAP=%s) failed (%i-%s)", solcap_path, errno, fd_io_strerror( errno ) ));
38 0 : }
39 0 : runner->solcap_file = (void *)(ulong)fd;
40 0 : FD_LOG_NOTICE(( "Logging to solcap file %s", solcap_path ));
41 :
42 0 : void * solcap_mem = fd_wksp_alloc_laddr( runner->wksp, fd_solcap_writer_align(), fd_solcap_writer_footprint(), 1UL );
43 0 : runner->solcap = fd_solcap_writer_init( solcap_mem, fd );
44 0 : FD_TEST( runner->solcap );
45 0 : }
46 :
47 0 : return runner;
48 0 : }
49 :
50 : static void
51 0 : sol_compat_cleanup_runner( fd_solfuzz_runner_t * runner ) {
52 : /* Cleanup test runner */
53 0 : if( runner->solcap ) {
54 0 : fd_wksp_free_laddr( ( runner->solcap ) );
55 0 : runner->solcap = NULL;
56 0 : if( runner->solcap_file ) {
57 0 : close( (int)(ulong)runner->solcap_file );
58 0 : runner->solcap_file = NULL;
59 0 : }
60 0 : }
61 0 : fd_solfuzz_runner_delete( runner );
62 0 : }
63 :
64 : void
65 0 : sol_compat_init( int log_level ) {
66 0 : int argc = 1;
67 0 : char * argv[2] = { (char *)"fd_exec_sol_compat", NULL };
68 0 : char ** argv_ = argv;
69 0 : if( !getenv( "FD_LOG_PATH" ) ) {
70 0 : setenv( "FD_LOG_PATH", "", 1 );
71 0 : }
72 :
73 0 : char const * enable_vm_tracing_env = getenv( "ENABLE_VM_TRACING");
74 0 : int enable_vm_tracing = enable_vm_tracing_env!=NULL;
75 0 : fd_solfuzz_runner_options_t options = {
76 0 : .enable_vm_tracing = enable_vm_tracing
77 0 : };
78 :
79 0 : fd_log_enable_unclean_exit();
80 0 : fd_boot( &argc, &argv_ );
81 :
82 0 : if( FD_UNLIKELY( wksp || runner ) ) {
83 0 : FD_LOG_ERR(( "sol_compat_init() called multiple times" ));
84 0 : }
85 :
86 0 : ulong footprint = 22UL<<30;
87 0 : ulong part_max = fd_wksp_part_max_est( footprint, 64UL<<10 );
88 0 : ulong data_max = fd_wksp_data_max_est( footprint, part_max );
89 0 : wksp = fd_wksp_demand_paged_new( "sol_compat", 42U, part_max, data_max );
90 0 : if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "fd_wksp_demand_paged_new() failed" ));
91 :
92 0 : runner = sol_compat_setup_runner( &options );
93 0 : if( FD_UNLIKELY( !runner ) ) FD_LOG_ERR(( "sol_compat_setup_runner() failed" ));
94 :
95 0 : fd_log_level_logfile_set( log_level );
96 0 : fd_log_level_core_set(4); /* abort on FD_LOG_ERR */
97 0 : }
98 :
99 : void
100 0 : sol_compat_fini( void ) {
101 0 : sol_compat_cleanup_runner( runner );
102 0 : fd_wksp_delete_anonymous( wksp );
103 0 : wksp = NULL;
104 0 : runner = NULL;
105 0 : fd_halt();
106 0 : }
107 :
108 : sol_compat_features_t const *
109 0 : sol_compat_get_features_v1( void ) {
110 0 : static sol_compat_features_t features;
111 0 : static ulong hardcoded_features[ FD_FEATURE_ID_CNT ];
112 0 : static ulong supported_features[ FD_FEATURE_ID_CNT ];
113 :
114 0 : FD_ONCE_BEGIN {
115 0 : features.struct_size = sizeof(sol_compat_features_t);
116 0 : features.hardcoded_features = hardcoded_features;
117 0 : features.supported_features = supported_features;
118 0 : for( fd_feature_id_t const * iter = fd_feature_iter_init();
119 0 : !fd_feature_iter_done( iter );
120 0 : iter = fd_feature_iter_next( iter ) ) {
121 0 : if( iter->reverted ) continue; /* skip reverted features */
122 0 : if( !iter->implemented ) continue; /* skip features firedancer does not implement yet */
123 :
124 : /* Pretend that features activated on all clusters are hardcoded */
125 0 : if( iter->hardcode_for_fuzzing ) {
126 0 : hardcoded_features[ features.hardcoded_features_cnt++ ] = iter->id.ul[0];
127 0 : } else {
128 0 : supported_features[ features.supported_feature_cnt++ ] = iter->id.ul[0];
129 0 : }
130 0 : }
131 0 : }
132 0 : FD_ONCE_END;
133 :
134 0 : return &features;
135 0 : }
136 :
137 : /*
138 : * execute_v1
139 : */
140 :
141 : int
142 : sol_compat_instr_execute_v1( uchar * out,
143 : ulong * out_sz,
144 : uchar const * in,
145 0 : ulong in_sz ) {
146 0 : fd_spad_push( runner->spad );
147 0 : fd_exec_test_instr_context_t input[1] = {0};
148 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_instr_context_desc, &input, in, in_sz, runner->spad ) ) ) {
149 0 : fd_spad_pop( runner->spad );
150 0 : return 0;
151 0 : }
152 :
153 0 : int ok = 0;
154 0 : void * output = NULL;
155 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_instr_run );
156 0 : if( output ) {
157 0 : ok = !!fd_pb_encode( &fd_exec_test_instr_effects_desc, output, out, out_sz );
158 0 : }
159 0 : fd_spad_pop( runner->spad );
160 :
161 0 : fd_solfuzz_runner_leak_check( runner );
162 0 : return ok;
163 0 : }
164 :
165 : int
166 : sol_compat_txn_execute_v1( uchar * out,
167 : ulong * out_sz,
168 : uchar const * in,
169 0 : ulong in_sz ) {
170 0 : fd_spad_push( runner->spad );
171 0 : fd_exec_test_txn_context_t input[1] = {0};
172 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_txn_context_desc, &input, in, in_sz, runner->spad ) ) ) {
173 0 : fd_spad_pop( runner->spad );
174 0 : return 0;
175 0 : }
176 :
177 0 : int ok = 0;
178 0 : void * output = NULL;
179 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_txn_run );
180 0 : if( output ) {
181 0 : ok = !!fd_pb_encode( &fd_exec_test_txn_result_desc, output, out, out_sz );
182 0 : }
183 0 : fd_spad_pop( runner->spad );
184 :
185 0 : fd_solfuzz_runner_leak_check( runner );
186 0 : return ok;
187 0 : }
188 :
189 : int
190 : sol_compat_bundle_execute_v1( uchar * out,
191 : ulong * out_sz,
192 : uchar const * in,
193 0 : ulong in_sz ) {
194 0 : fd_spad_push( runner->spad );
195 0 : fd_exec_test_bundle_context_t input[1] = {0};
196 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_bundle_context_desc, &input, in, in_sz, runner->spad ) ) ) {
197 0 : fd_spad_pop( runner->spad );
198 0 : return 0;
199 0 : }
200 :
201 0 : int ok = 0;
202 0 : void * output = NULL;
203 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_bundle_run );
204 0 : if( output ) {
205 0 : ok = !!fd_pb_encode( &fd_exec_test_bundle_effects_desc, output, out, out_sz );
206 0 : }
207 0 : fd_spad_pop( runner->spad );
208 :
209 0 : fd_solfuzz_runner_leak_check( runner );
210 0 : return ok;
211 0 : }
212 :
213 : int
214 : sol_compat_txn_cost_v1( uchar * out,
215 : ulong * out_sz,
216 : uchar const * in,
217 0 : ulong in_sz ) {
218 0 : fd_spad_push( runner->spad );
219 0 : fd_exec_test_cost_context_t input[1] = {0};
220 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_cost_context_desc, &input, in, in_sz, runner->spad ) ) ) {
221 0 : fd_spad_pop( runner->spad );
222 0 : return 0;
223 0 : }
224 :
225 0 : int ok = 0;
226 0 : void * output = NULL;
227 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_cost_run );
228 0 : if( output ) {
229 0 : ok = !!fd_pb_encode( &fd_exec_test_cost_result_desc, output, out, out_sz );
230 0 : }
231 0 : fd_spad_pop( runner->spad );
232 :
233 0 : fd_solfuzz_runner_leak_check( runner );
234 0 : return ok;
235 0 : }
236 :
237 : int
238 : sol_compat_block_execute_v1( uchar * out,
239 : ulong * out_sz,
240 : uchar const * in,
241 0 : ulong in_sz ) {
242 0 : fd_spad_push( runner->spad );
243 0 : fd_exec_test_block_context_t input[1] = {0};
244 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_block_context_desc, &input, in, in_sz, runner->spad ) ) ) {
245 0 : fd_spad_pop( runner->spad );
246 0 : return 0;
247 0 : }
248 :
249 0 : int ok = 0;
250 0 : void * output = NULL;
251 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_block_run );
252 0 : if( output ) {
253 0 : ok = !!fd_pb_encode( &fd_exec_test_block_effects_desc, output, out, out_sz );
254 0 : }
255 0 : fd_spad_pop( runner->spad );
256 :
257 0 : fd_solfuzz_runner_leak_check( runner );
258 0 : return ok;
259 0 : }
260 :
261 : int
262 : sol_compat_vm_syscall_execute_v1( uchar * out,
263 : ulong * out_sz,
264 : uchar const * in,
265 0 : ulong in_sz ) {
266 0 : fd_spad_push( runner->spad );
267 0 : fd_exec_test_syscall_context_t input[1] = {0};
268 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_syscall_context_desc, &input, in, in_sz, runner->spad ) ) ) {
269 0 : fd_spad_pop( runner->spad );
270 0 : return 0;
271 0 : }
272 :
273 0 : int ok = 0;
274 0 : void * output = NULL;
275 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_syscall_run );
276 0 : if( output ) {
277 0 : ok = !!fd_pb_encode( &fd_exec_test_syscall_effects_desc, output, out, out_sz );
278 0 : }
279 0 : fd_spad_pop( runner->spad );
280 :
281 0 : fd_solfuzz_runner_leak_check( runner );
282 0 : return ok;
283 0 : }
284 :
285 : int
286 : sol_compat_gossip_decode_v1( uchar * out,
287 : ulong * out_sz,
288 : uchar const * in,
289 0 : ulong in_sz ) {
290 0 : fd_spad_push( runner->spad );
291 0 : int ok = fd_solfuzz_gossip_decode( runner, out, out_sz, in, in_sz );
292 0 : fd_spad_pop( runner->spad );
293 0 : fd_solfuzz_runner_leak_check( runner );
294 0 : return ok;
295 0 : }
296 :
297 : int
298 : sol_compat_elf_loader_v1( uchar * out,
299 : ulong * out_sz,
300 : uchar const * in,
301 0 : ulong in_sz ) {
302 0 : fd_spad_push( runner->spad );
303 0 : fd_exec_test_elf_loader_ctx_t input[1] = {0};
304 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_elf_loader_ctx_desc, &input, in, in_sz, runner->spad ) ) ) {
305 0 : fd_spad_pop( runner->spad );
306 0 : return 0;
307 0 : }
308 :
309 0 : int ok = 0;
310 0 : void * output = NULL;
311 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_elf_loader_run );
312 0 : if( output ) {
313 0 : ok = !!fd_pb_encode( &fd_exec_test_elf_loader_effects_desc, output, out, out_sz );
314 0 : }
315 0 : fd_spad_pop( runner->spad );
316 :
317 0 : fd_solfuzz_runner_leak_check( runner );
318 0 : return ok;
319 0 : }
320 :
321 : int
322 : sol_compat_vm_serialize_execute_v1( uchar * out,
323 : ulong * out_sz,
324 : uchar const * in,
325 0 : ulong in_sz ) {
326 0 : fd_spad_push( runner->spad );
327 0 : fd_exec_test_instr_context_t input[1] = {0};
328 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_instr_context_desc, &input, in, in_sz, runner->spad ) ) ) {
329 0 : fd_spad_pop( runner->spad );
330 0 : return 0;
331 0 : }
332 :
333 0 : int ok = 0;
334 0 : void * output = NULL;
335 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_vm_serialize_run );
336 0 : if( output ) {
337 0 : ok = !!fd_pb_encode( &fd_exec_test_vm_serialization_effects_desc, output, out, out_sz );
338 0 : }
339 0 : fd_spad_pop( runner->spad );
340 :
341 0 : fd_solfuzz_runner_leak_check( runner );
342 0 : return ok;
343 0 : }
344 :
345 : int
346 : sol_compat_shred_parse_v1( uchar * out,
347 : ulong * out_sz,
348 : uchar const * in,
349 0 : ulong in_sz ) {
350 0 : fd_spad_push( runner->spad );
351 0 : fd_exec_test_shred_parse_context_t input[1] = {0};
352 0 : if( FD_UNLIKELY( !fd_pb_decode( &fd_exec_test_shred_parse_context_desc, &input, in, in_sz, runner->spad ) ) ) {
353 0 : fd_spad_pop( runner->spad );
354 0 : return 0;
355 0 : }
356 :
357 0 : int ok = 0;
358 0 : void * output = NULL;
359 0 : fd_solfuzz_pb_execute_wrapper( runner, input, &output, fd_solfuzz_pb_shred_run );
360 0 : if( output ) {
361 0 : ok = !!fd_pb_encode( &fd_exec_test_shred_parse_effects_desc, output, out, out_sz );
362 0 : }
363 0 : fd_spad_pop( runner->spad );
364 :
365 0 : fd_solfuzz_runner_leak_check( runner );
366 0 : return ok;
367 0 : }
|