Line data Source code
1 : #include "fd_solfuzz.h"
2 : #include "fd_solfuzz_private.h"
3 : #define _GNU_SOURCE
4 : #include "fd_sol_compat.h"
5 :
6 : #include "../fd_executor_err.h"
7 : #include "../../capture/fd_solcap_writer.h"
8 : #include "../../../ballet/shred/fd_shred.h"
9 :
10 : #include "generated/block.pb.h"
11 : #include "generated/elf.pb.h"
12 : #include "generated/invoke.pb.h"
13 : #include "generated/shred.pb.h"
14 : #include "generated/vm.pb.h"
15 : #include "generated/txn.pb.h"
16 : #include "generated/type.pb.h"
17 :
18 : #include <assert.h>
19 : #include <errno.h>
20 : #include <stdio.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 : runner->solcap_file = fopen( solcap_path, "w" );
36 0 : if( FD_UNLIKELY( !runner->solcap_file ) ) {
37 0 : FD_LOG_ERR(( "fopen($FD_SOLCAP=%s) failed (%i-%s)", solcap_path, errno, fd_io_strerror( errno ) ));
38 0 : }
39 0 : FD_LOG_NOTICE(( "Logging to solcap file %s", solcap_path ));
40 :
41 0 : void * solcap_mem = fd_wksp_alloc_laddr( runner->wksp, fd_solcap_writer_align(), fd_solcap_writer_footprint(), 1UL );
42 0 : runner->solcap = fd_solcap_writer_new( solcap_mem );
43 0 : FD_TEST( runner->solcap );
44 0 : FD_TEST( fd_solcap_writer_init( solcap_mem, runner->solcap_file ) );
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_solcap_writer_flush( runner->solcap );
55 0 : fd_wksp_free_laddr( fd_solcap_writer_delete( runner->solcap ) );
56 0 : runner->solcap = NULL;
57 0 : fclose( runner->solcap_file );
58 0 : runner->solcap_file = NULL;
59 0 : }
60 0 : fd_solfuzz_runner_delete( runner );
61 0 : }
62 :
63 : void
64 0 : sol_compat_init( int log_level ) {
65 0 : int argc = 1;
66 0 : char * argv[2] = { (char *)"fd_exec_sol_compat", NULL };
67 0 : char ** argv_ = argv;
68 0 : if( !getenv( "FD_LOG_PATH" ) ) {
69 0 : setenv( "FD_LOG_PATH", "", 1 );
70 0 : }
71 :
72 0 : char const * enable_vm_tracing_env = getenv( "ENABLE_VM_TRACING");
73 0 : int enable_vm_tracing = enable_vm_tracing_env!=NULL;
74 0 : fd_solfuzz_runner_options_t options = {
75 0 : .enable_vm_tracing = enable_vm_tracing
76 0 : };
77 :
78 0 : fd_log_enable_unclean_exit();
79 0 : fd_boot( &argc, &argv_ );
80 :
81 0 : if( FD_UNLIKELY( wksp || runner ) ) {
82 0 : FD_LOG_ERR(( "sol_compat_init() called multiple times" ));
83 0 : }
84 :
85 0 : ulong footprint = 7UL<<30;
86 0 : ulong part_max = fd_wksp_part_max_est( footprint, 64UL<<10 );
87 0 : ulong data_max = fd_wksp_data_max_est( footprint, part_max );
88 0 : wksp = fd_wksp_demand_paged_new( "sol_compat", 42U, part_max, data_max );
89 0 : if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "fd_wksp_demand_paged_new() failed" ));
90 :
91 0 : runner = sol_compat_setup_runner( &options );
92 0 : if( FD_UNLIKELY( !runner ) ) FD_LOG_ERR(( "sol_compat_setup_runner() failed" ));
93 :
94 0 : fd_log_level_logfile_set( log_level );
95 0 : fd_log_level_core_set(4); /* abort on FD_LOG_ERR */
96 0 : }
97 :
98 : void
99 0 : sol_compat_fini( void ) {
100 0 : sol_compat_cleanup_runner( runner );
101 0 : fd_wksp_delete_anonymous( wksp );
102 0 : wksp = NULL;
103 0 : runner = NULL;
104 0 : fd_halt();
105 0 : }
106 :
107 : sol_compat_features_t const *
108 0 : sol_compat_get_features_v1( void ) {
109 0 : static sol_compat_features_t features;
110 0 : static ulong hardcoded_features[ FD_FEATURE_ID_CNT ];
111 0 : static ulong supported_features[ FD_FEATURE_ID_CNT ];
112 :
113 0 : FD_ONCE_BEGIN {
114 0 : features.struct_size = sizeof(sol_compat_features_t);
115 0 : features.hardcoded_features = hardcoded_features;
116 0 : features.supported_features = supported_features;
117 0 : for( fd_feature_id_t const * iter = fd_feature_iter_init();
118 0 : !fd_feature_iter_done( iter );
119 0 : iter = fd_feature_iter_next( iter ) ) {
120 0 : if( iter->reverted ) continue; /* skip reverted features */
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_execute_wrapper( runner, input, &output, fd_solfuzz_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 : return ok;
159 0 : }
160 :
161 : int
162 : sol_compat_txn_execute_v1( uchar * out,
163 : ulong * out_sz,
164 : uchar const * in,
165 0 : ulong in_sz ) {
166 0 : fd_exec_test_txn_context_t input[1] = {0};
167 0 : void * res = sol_compat_decode_lenient( &input, in, in_sz, &fd_exec_test_txn_context_t_msg );
168 0 : if( FD_UNLIKELY( !res ) ) return 0;
169 :
170 0 : int ok = 0;
171 0 : fd_spad_push( runner->spad );
172 0 : void * output = NULL;
173 0 : fd_solfuzz_execute_wrapper( runner, input, &output, fd_solfuzz_txn_run );
174 0 : if( output ) {
175 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_txn_result_t_msg );
176 0 : }
177 0 : fd_spad_pop( runner->spad );
178 :
179 0 : pb_release( &fd_exec_test_txn_context_t_msg, input );
180 0 : return ok;
181 0 : }
182 :
183 : int
184 : sol_compat_block_execute_v1( uchar * out,
185 : ulong * out_sz,
186 : uchar const * in,
187 0 : ulong in_sz ) {
188 0 : fd_exec_test_block_context_t input[1] = {0};
189 0 : void * res = sol_compat_decode_lenient( &input, in, in_sz, &fd_exec_test_block_context_t_msg );
190 0 : if( FD_UNLIKELY( !res ) ) return 0;
191 :
192 0 : fd_spad_push( runner->spad );
193 0 : int ok = 0;
194 0 : void * output = NULL;
195 0 : fd_solfuzz_execute_wrapper( runner, input, &output, fd_solfuzz_block_run );
196 0 : if( output ) {
197 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_block_effects_t_msg );
198 0 : }
199 0 : fd_spad_pop( runner->spad );
200 :
201 0 : pb_release( &fd_exec_test_block_context_t_msg, input );
202 0 : return ok;
203 0 : }
204 :
205 : int
206 : sol_compat_elf_loader_v1( uchar * out,
207 : ulong * out_sz,
208 : uchar const * in,
209 0 : ulong in_sz ) {
210 0 : fd_exec_test_elf_loader_ctx_t input[1] = {0};
211 0 : void * res = sol_compat_decode( &input, in, in_sz, &fd_exec_test_elf_loader_ctx_t_msg );
212 0 : if( FD_UNLIKELY( !res ) ) return 0;
213 :
214 0 : fd_spad_push( runner->spad );
215 0 : int ok = 0;
216 0 : void * output = NULL;
217 0 : fd_solfuzz_execute_wrapper( runner, input, &output, fd_solfuzz_elf_loader_run );
218 0 : if( output ) {
219 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_elf_loader_effects_t_msg );
220 0 : }
221 0 : fd_spad_pop( runner->spad );
222 :
223 0 : pb_release( &fd_exec_test_elf_loader_ctx_t_msg, input );
224 0 : return ok;
225 0 : }
226 :
227 : int
228 : sol_compat_vm_syscall_execute_v1( uchar * out,
229 : ulong * out_sz,
230 : uchar const * in,
231 0 : ulong in_sz ) {
232 0 : fd_exec_test_syscall_context_t input[1] = {0};
233 0 : void * res = sol_compat_decode_lenient( &input, in, in_sz, &fd_exec_test_syscall_context_t_msg );
234 0 : if( FD_UNLIKELY( !res ) ) return 0;
235 :
236 0 : fd_spad_push( runner->spad );
237 0 : int ok = 0;
238 0 : void * output = NULL;
239 0 : fd_solfuzz_execute_wrapper( runner, input, &output, fd_solfuzz_syscall_run );
240 0 : if( output ) {
241 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_syscall_effects_t_msg );
242 0 : }
243 0 : fd_spad_pop( runner->spad );
244 :
245 0 : pb_release( &fd_exec_test_syscall_context_t_msg, input );
246 0 : return ok;
247 0 : }
248 :
249 : int
250 : sol_compat_vm_interp_v1( uchar * out,
251 : ulong * out_sz,
252 : uchar const * in,
253 0 : ulong in_sz ) {
254 0 : fd_exec_test_syscall_context_t input[1] = {0};
255 0 : void * res = sol_compat_decode_lenient( &input, in, in_sz, &fd_exec_test_syscall_context_t_msg );
256 0 : if( FD_UNLIKELY( !res ) ) return 0;
257 :
258 0 : fd_spad_push( runner->spad );
259 0 : int ok = 0;
260 0 : void * output = NULL;
261 0 : fd_solfuzz_execute_wrapper( runner, input, &output, fd_solfuzz_vm_interp_run );
262 0 : if( output ) {
263 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_syscall_effects_t_msg );
264 0 : }
265 0 : fd_spad_pop( runner->spad );
266 :
267 0 : pb_release( &fd_exec_test_syscall_context_t_msg, input );
268 0 : return ok;
269 0 : }
270 :
271 : int
272 : sol_compat_shred_parse_v1( uchar * out,
273 : ulong * out_sz,
274 : uchar const * in,
275 0 : ulong in_sz ) {
276 0 : fd_exec_test_shred_binary_t input[1] = {0};
277 0 : void * res = sol_compat_decode_lenient( &input, in, in_sz, &fd_exec_test_shred_binary_t_msg );
278 0 : if( FD_UNLIKELY( res==NULL ) ) {
279 0 : return 0;
280 0 : }
281 0 : if( FD_UNLIKELY( input[0].data==NULL ) ) {
282 0 : pb_release( &fd_exec_test_shred_binary_t_msg, input );
283 0 : return 0;
284 0 : }
285 0 : fd_exec_test_accepts_shred_t output[1] = {0};
286 0 : output[0].valid = !!fd_shred_parse( input[0].data->bytes, input[0].data->size );
287 0 : pb_release( &fd_exec_test_shred_binary_t_msg, input );
288 0 : return !!sol_compat_encode( out, out_sz, output, &fd_exec_test_accepts_shred_t_msg );
289 0 : }
290 :
291 : int
292 : sol_compat_type_execute_v1( uchar * out,
293 : ulong * out_sz,
294 : uchar const * in,
295 0 : ulong in_sz ) {
296 : // Setup
297 : // Decode context
298 0 : fd_exec_test_type_context_t input[1] = {0};
299 0 : void * res = sol_compat_decode_lenient( &input, in, in_sz, &fd_exec_test_type_context_t_msg );
300 0 : if( FD_UNLIKELY( !res ) ) return 0;
301 :
302 0 : fd_spad_push( runner->spad );
303 0 : int ok = 0;
304 0 : void * output = NULL;
305 0 : fd_solfuzz_execute_wrapper( runner, input, &output, fd_solfuzz_type_run );
306 0 : if( output ) {
307 0 : ok = !!sol_compat_encode( out, out_sz, output, &fd_exec_test_type_effects_t_msg );
308 0 : }
309 0 : fd_spad_pop( runner->spad );
310 :
311 0 : pb_release( &fd_exec_test_type_context_t_msg, input );
312 0 : return ok;
313 0 : }
|