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