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

Generated by: LCOV version 1.14