Line data Source code
1 : #include "fd_types_harness.h"
2 : #include "../../../types/fd_types_yaml.h"
3 : #include "../../../types/fd_types_reflect.h"
4 : #include <ctype.h>
5 :
6 : #include "generated/type.pb.h"
7 :
8 : struct CustomerSerializer {
9 : void * file;
10 : };
11 : typedef struct CustomerSerializer CustomerSerializer;
12 :
13 : static void
14 : custom_serializer_walk( void * _self,
15 : void const * arg,
16 : char const * name,
17 : int type,
18 : char const * type_name,
19 0 : uint level ) {
20 0 : (void)name;
21 0 : (void)type;
22 0 : (void)type_name;
23 0 : (void)level;
24 :
25 0 : CustomerSerializer * self = (CustomerSerializer *)_self;
26 0 : FILE * file = self->file;
27 :
28 0 : switch( type ) {
29 0 : case FD_FLAMENCO_TYPE_MAP:
30 0 : case FD_FLAMENCO_TYPE_MAP_END:
31 0 : break;
32 0 : case FD_FLAMENCO_TYPE_ENUM:
33 : // print the enum discriminant
34 0 : fprintf( file, "%u,", *(uint const*) arg );
35 0 : break;
36 0 : case FD_FLAMENCO_TYPE_ENUM_END:
37 0 : case FD_FLAMENCO_TYPE_ARR:
38 0 : case FD_FLAMENCO_TYPE_ARR_END:
39 0 : break;
40 0 : case FD_FLAMENCO_TYPE_NULL:
41 0 : break;
42 0 : case FD_FLAMENCO_TYPE_BOOL:
43 0 : fprintf( file, "%s,", (*(uchar const *)arg) ? "true" : "false" );
44 0 : break;
45 0 : case FD_FLAMENCO_TYPE_UCHAR:
46 0 : if (arg) fprintf( file, "%u,", *(uchar const *)arg );
47 0 : break;
48 0 : case FD_FLAMENCO_TYPE_SCHAR:
49 0 : fprintf( file, "%d,", *(schar const *)arg );
50 0 : break;
51 0 : case FD_FLAMENCO_TYPE_USHORT:
52 0 : fprintf( file, "%u,", *(ushort const *)arg );
53 0 : break;
54 0 : case FD_FLAMENCO_TYPE_SSHORT:
55 0 : fprintf( file, "%d,", *(short const *)arg );
56 0 : break;
57 0 : case FD_FLAMENCO_TYPE_UINT:
58 0 : fprintf( file, "%u,", *(uint const *)arg );
59 0 : break;
60 0 : case FD_FLAMENCO_TYPE_SINT:
61 0 : fprintf( file, "%d,", *(int const *)arg );
62 0 : break;
63 0 : case FD_FLAMENCO_TYPE_ULONG:
64 0 : fprintf( file, "%lu,", *(ulong const *)arg );
65 0 : break;
66 0 : case FD_FLAMENCO_TYPE_SLONG:
67 0 : fprintf( file, "%ld,", *(long const *)arg );
68 0 : break;
69 0 : # if FD_HAS_INT128
70 0 : case FD_FLAMENCO_TYPE_UINT128:
71 0 : case FD_FLAMENCO_TYPE_SINT128: {
72 0 : uint128 v = *(uint128 const *)arg;
73 : // fprintf( file, "%s: 0x%016lx%016lx\n", name,
74 : // (ulong)(v>>64), (ulong)v );
75 0 : if( v <= ULONG_MAX ) {
76 0 : fprintf( file, "%lu,", (ulong)v );
77 0 : } else {
78 0 : char str[40] = {0};
79 0 : char *p = str + sizeof(str) - 1;
80 :
81 0 : if( v == 0 ) {
82 0 : *--p = '0';
83 0 : } else {
84 0 : while( v != 0 ) {
85 0 : *--p = (char)('0' + (int)( v % 10 ));
86 0 : v /= 10;
87 0 : }
88 0 : }
89 0 : fprintf( file, "%s,", p );
90 0 : }
91 0 : break;
92 0 : }
93 0 : # endif
94 0 : case FD_FLAMENCO_TYPE_FLOAT: {
95 0 : double f = (double)( *(float const *)arg );
96 0 : for( ulong i=0; i < sizeof(f); ++i ) {
97 0 : fprintf( file, "0x%02X,", ((uchar *)&f)[i] );
98 0 : }
99 0 : break;
100 0 : }
101 0 : case FD_FLAMENCO_TYPE_DOUBLE: {
102 0 : double f = *(double const *)arg;
103 0 : for( ulong i=0; i < sizeof(f); ++i ) {
104 0 : fprintf( file, "0x%02X,", ((uchar *)&f)[i] );
105 0 : }
106 0 : break;
107 0 : }
108 0 : case FD_FLAMENCO_TYPE_HASH256: {
109 0 : for( ulong i=0; i < 32; ++i ) {
110 0 : fprintf( file, "%u,", ((uchar *)arg)[i] );
111 0 : }
112 0 : break;
113 0 : }
114 0 : case FD_FLAMENCO_TYPE_HASH1024:
115 0 : for( ulong i=0; i < 128; ++i ) {
116 0 : fprintf( file, "%u,", ((uchar *)arg)[i] );
117 0 : }
118 0 : break;
119 0 : case FD_FLAMENCO_TYPE_HASH16384:
120 0 : for( ulong i=0; i < 2048; ++i ) {
121 0 : fprintf( file, "%u,", ((uchar *)arg)[i] );
122 0 : }
123 0 : break;
124 0 : case FD_FLAMENCO_TYPE_SIG512: {
125 0 : for( ulong i=0; i < 64; ++i ) {
126 0 : fprintf( file, "%u,", ((uchar *)arg)[i] );
127 0 : }
128 0 : break;
129 0 : }
130 0 : case FD_FLAMENCO_TYPE_CSTR:
131 0 : if( arg==NULL ) {
132 0 : fprintf( file, "," );
133 0 : } else {
134 0 : fprintf( file, "'%s',", (char const *)arg );
135 0 : }
136 0 : break;
137 0 : case FD_FLAMENCO_TYPE_ENUM_DISC:
138 0 : break;
139 0 : default:
140 0 : FD_LOG_CRIT(( "unknown type %#x", (uint)type ));
141 0 : break;
142 0 : }
143 0 : }
144 :
145 : static int
146 : fd_runtime_fuzz_decode_type_run( fd_runtime_fuzz_runner_t * runner,
147 : uchar const * input,
148 : ulong input_sz,
149 : uchar * output,
150 0 : ulong * output_sz ) {
151 :
152 0 : FD_SPAD_FRAME_BEGIN( runner->spad ) {
153 0 : if( input_sz < 1 ) {
154 0 : *output_sz = 0;
155 0 : return 0;
156 0 : }
157 :
158 : // First byte is the type ID
159 0 : uchar type_id = input[0];
160 0 : if( type_id >= fd_types_vt_list_cnt ) {
161 0 : FD_LOG_WARNING(( "Invalid type ID: %d", type_id ));
162 0 : *output_sz = 0;
163 0 : return 0;
164 0 : }
165 :
166 0 : fd_types_vt_t const * type_meta = &fd_types_vt_list[ type_id ];
167 :
168 : // Set up decode context
169 0 : fd_bincode_decode_ctx_t decode_ctx = {
170 0 : .data = input + 1,
171 0 : .dataend = (void *)( (ulong)input + input_sz ),
172 0 : };
173 :
174 : // Get the size needed for the decoded object
175 0 : ulong total_sz = 0UL;
176 0 : int err = type_meta->decode_footprint( &decode_ctx, &total_sz );
177 0 : if( err != FD_BINCODE_SUCCESS ) {
178 0 : *output_sz = 0;
179 0 : return 0;
180 0 : }
181 :
182 : // Allocate memory for the decoded object
183 0 : void * decoded = fd_spad_alloc( runner->spad, 1UL, total_sz );
184 0 : if( !decoded ) {
185 0 : *output_sz = 0;
186 0 : return 0;
187 0 : }
188 :
189 : // Decode the object
190 0 : void * result = type_meta->decode( decoded, &decode_ctx );
191 0 : if (result == NULL) {
192 0 : *output_sz = 0;
193 0 : return 0;
194 0 : }
195 :
196 : // Output buffer structure:
197 : // - serialized_sz (ulong)
198 : // - serialized data (bytes)
199 : // - yaml data (bytes)
200 :
201 0 : uchar * output_ptr = output;
202 0 : ulong remaining_sz = *output_sz;
203 :
204 : // Skip serialized_sz for now (we'll write it after serialization)
205 0 : uchar * serialized_sz_ptr = output_ptr;
206 0 : output_ptr += sizeof(ulong);
207 0 : remaining_sz -= sizeof(ulong);
208 :
209 : // Serialize the memory representation
210 0 : uchar * serialized_data_ptr = output_ptr;
211 0 : FILE * file = fmemopen( serialized_data_ptr, remaining_sz, "w" );
212 0 : if( !file ) {
213 0 : *output_sz = 0;
214 0 : return 0;
215 0 : }
216 :
217 0 : CustomerSerializer serializer = {
218 0 : .file = file,
219 0 : };
220 :
221 : // Walk the decoded object and serialize it
222 0 : type_meta->walk( &serializer, decoded, custom_serializer_walk, type_meta->name, 0 );
223 0 : if( ferror( file ) ) {
224 0 : fclose( file );
225 0 : *output_sz = 0;
226 0 : return 0;
227 0 : }
228 0 : long serialized_sz = ftell( file );
229 0 : fclose( file );
230 :
231 : // Write serialized_sz
232 0 : *(ulong *)serialized_sz_ptr = (ulong)serialized_sz;
233 :
234 : // Update output_ptr and remaining_sz
235 0 : output_ptr += serialized_sz;
236 0 : remaining_sz -= (ulong)serialized_sz;
237 :
238 : // Generate YAML representation
239 0 : uchar * yaml_data_ptr = output_ptr;
240 0 : file = fmemopen( yaml_data_ptr, remaining_sz, "w" );
241 0 : if( !file ) {
242 0 : *output_sz = 0;
243 0 : return 0;
244 0 : }
245 :
246 0 : void * yaml_mem = fd_spad_alloc( runner->spad, fd_flamenco_yaml_align(), fd_flamenco_yaml_footprint() );
247 0 : fd_flamenco_yaml_t * yaml = fd_flamenco_yaml_init( fd_flamenco_yaml_new( yaml_mem ), file );
248 :
249 : // Walk the decoded object and generate YAML
250 0 : type_meta->walk( yaml, decoded, fd_flamenco_yaml_walk, type_meta->name, 0 );
251 0 : if( ferror( file ) ) {
252 0 : fclose( file );
253 0 : *output_sz = 0;
254 0 : return 0;
255 0 : }
256 :
257 0 : long yaml_sz = ftell( file );
258 0 : fclose( file );
259 :
260 : // Update output_ptr and remaining_sz
261 0 : output_ptr += yaml_sz;
262 0 : remaining_sz -= (ulong)yaml_sz;
263 :
264 : // Calculate total size
265 0 : *output_sz = (ulong)(output_ptr - output);
266 0 : return 1;
267 0 : } FD_SPAD_FRAME_END;
268 :
269 0 : *output_sz = 0;
270 0 : return 0;
271 0 : }
272 :
273 : ulong
274 : fd_runtime_fuzz_type_run( fd_runtime_fuzz_runner_t * runner,
275 : void const * input_,
276 : void ** output_,
277 : void * output_buf,
278 0 : ulong output_bufsz ) {
279 0 : fd_exec_test_type_context_t const * input = fd_type_pun_const( input_ );
280 0 : fd_exec_test_type_effects_t ** output = fd_type_pun( output_ );
281 :
282 0 : ulong output_end = (ulong)output_buf + output_bufsz;
283 0 : FD_SCRATCH_ALLOC_INIT(l, output_buf);
284 :
285 0 : fd_exec_test_type_effects_t * effects =
286 0 : FD_SCRATCH_ALLOC_APPEND(l, alignof(fd_exec_test_type_effects_t),
287 0 : sizeof(fd_exec_test_type_effects_t));
288 0 : if (FD_UNLIKELY(_l > output_end)) {
289 0 : return 0UL;
290 0 : }
291 :
292 0 : if( input == NULL || input->content == NULL ) {
293 0 : return 0UL;
294 0 : }
295 :
296 0 : if(input->content->size == 0) {
297 0 : return 0UL;
298 0 : }
299 :
300 : // Initialize effects
301 0 : effects->result = 0;
302 0 : effects->representation = NULL;
303 0 : effects->yaml = NULL;
304 :
305 : // Decode the type
306 0 : ulong max_content_size = output_bufsz - (_l - (ulong)output_buf);
307 0 : uchar * temp_buffer = (uchar *)_l;
308 0 : if (FD_UNLIKELY(_l > output_end)) {
309 0 : return 0UL;
310 0 : }
311 :
312 0 : ulong decoded_sz = max_content_size;
313 0 : int success = fd_runtime_fuzz_decode_type_run( runner,
314 0 : input->content->bytes,
315 0 : input->content->size,
316 0 : temp_buffer,
317 0 : &decoded_sz);
318 :
319 0 : if (!success || decoded_sz == 0) {
320 0 : effects->result = 1;
321 0 : } else {
322 0 : effects->result = 0;
323 :
324 : // The decoded data contains:
325 : // - serialized_sz (ulong)
326 : // - serialized data (bytes)
327 : // - yaml data (bytes)
328 :
329 : // Extract serialized_sz
330 0 : ulong serialized_sz = *(ulong*)temp_buffer;
331 :
332 : // Allocate and copy the representation (serialized data)
333 0 : _l += decoded_sz;
334 0 : effects->representation = FD_SCRATCH_ALLOC_APPEND(l, alignof(pb_bytes_array_t),
335 0 : PB_BYTES_ARRAY_T_ALLOCSIZE(serialized_sz));
336 0 : if( FD_UNLIKELY( _l > output_end ) ) {
337 0 : return 0UL;
338 0 : }
339 0 : effects->representation->size = (pb_size_t)serialized_sz;
340 0 : fd_memcpy(effects->representation->bytes, temp_buffer + sizeof(ulong), serialized_sz);
341 :
342 : // Allocate and copy the yaml data
343 0 : ulong yaml_sz = decoded_sz - sizeof(ulong) - serialized_sz;
344 0 : effects->yaml = FD_SCRATCH_ALLOC_APPEND(l, alignof(pb_bytes_array_t),
345 0 : PB_BYTES_ARRAY_T_ALLOCSIZE(yaml_sz));
346 0 : if( FD_UNLIKELY( _l > output_end ) ) {
347 0 : return 0UL;
348 0 : }
349 0 : effects->yaml->size = (pb_size_t)yaml_sz;
350 0 : fd_memcpy(effects->yaml->bytes, temp_buffer + sizeof(ulong) + serialized_sz, yaml_sz);
351 0 : }
352 :
353 0 : ulong actual_end = FD_SCRATCH_ALLOC_FINI(l, 1UL);
354 0 : *output = effects;
355 0 : return actual_end - (ulong)output_buf;
356 0 : }
|