LCOV - code coverage report
Current view: top level - flamenco/runtime/tests/harness - fd_types_harness.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 258 0.0 %
Date: 2025-07-01 05:00:49 Functions: 0 3 0.0 %

          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 : }

Generated by: LCOV version 1.14