LCOV - code coverage report
Current view: top level - disco/gui - fd_gui_config_parse.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 62 0.0 %
Date: 2025-11-25 04:50:41 Functions: 0 2 0.0 %

          Line data    Source code
       1             : #include "fd_gui_config_parse.h"
       2             : 
       3             : #include "../../ballet/utf8/fd_utf8.h"
       4             : 
       5             : int
       6             : fd_gui_config_parse_validator_info_check( uchar const * data,
       7             :                                           ulong         sz,
       8             :                                           cJSON **      out_json,
       9           0 :                                           fd_pubkey_t * out_pubkey ) {
      10             :   /*
      11             :     pub struct ConfigKeys {
      12             :         #[cfg_attr(feature = "serde", serde(with = "short_vec"))]
      13             :         pub keys: Vec<(Pubkey, bool)>,
      14             :     }
      15             : 
      16             :     The memory layout of a ConfigProgram account is a bincode serialized
      17             :     ConfigKeys followed immediately by a stringified json object
      18             :     containing the desired info.
      19             : 
      20             :     The short_vec serialization format is a 1-3 bytes size field (where
      21             :     the highest bit in a given byte is a continuation bit) followed by
      22             :     serialized elements in the vector (in this case, each element is a
      23             :     32byte pubkey followed by a 1byte bool. For our simple parser, we
      24             :     only need to consider vectors smaller than 128 elements.
      25             : 
      26             :     The JSON schema for a validator info object is the following
      27             : 
      28             :     {
      29             :       "name": "<validator name>",
      30             :       "website": "<website url>",
      31             :       "details": "<validator details>",
      32             :       "iconUrl": "<icon url>"
      33             :     }
      34             : 
      35             :     Since accounts are at most 10MB, we should be safely within cJSON's
      36             :     allocator limits.
      37             : */
      38           0 :   ulong i = 0UL;
      39             : 
      40           0 : #define CHECK( cond )  do { \
      41           0 :     if( FD_UNLIKELY( !(cond) ) ) { \
      42           0 :       return 0; \
      43           0 :     } \
      44           0 :   } while( 0 )
      45             : 
      46             :   /* CHECK that it is safe to read at least n more bytes assuming i is
      47             :      the current location. n is untrusted and could trigger overflow, so
      48             :      don't do i+n<=payload_sz */
      49           0 : #define CHECK_LEFT( n ) CHECK( (n)<=(sz-i) )
      50             : 
      51           0 :   CHECK_LEFT( 1UL ); uchar ck_sz = FD_LOAD( uchar, data+i ); i++;
      52           0 :   if( FD_UNLIKELY( ck_sz!=2 ) ) return 0;
      53             : 
      54           0 :   struct __attribute__((packed, aligned(1))) config_keys {
      55           0 :     fd_pubkey_t pubkey;
      56           0 :     uchar       is_signer;
      57           0 :   };
      58             : 
      59           0 :   struct config_keys * data_config_keys = (struct config_keys *)(data + i);
      60           0 :   CHECK_LEFT( (sizeof(fd_pubkey_t) + 1UL)*ck_sz ); i += (sizeof(fd_pubkey_t) + 1UL)*ck_sz;
      61           0 :   CHECK_LEFT( FD_GUI_CONFIG_PARSE_VALIDATOR_INFO_MAX_SZ );
      62             : 
      63             :   /* First entry should be Va1idator1nfo111111111111111111111111111111 */
      64           0 :   uchar expected[ 32UL ] = { 0x07, 0x51, 0x97, 0x01, 0x74, 0x48, 0xf2, 0xac, 0x5d, 0xc2, 0x3c, 0x9e, 0xbc, 0x7a, 0xc7, 0x8c, 0x0a, 0x27, 0x25, 0x7a, 0xc6, 0x14, 0x45, 0x8d, 0xe0, 0xa4, 0xf1, 0x6f, 0x80, 0x00, 0x00, 0x00 };
      65           0 :   if( FD_UNLIKELY( memcmp( data_config_keys[0].pubkey.uc, expected, sizeof(fd_pubkey_t) ) || data_config_keys[0].is_signer ) ) return 0;
      66             : 
      67           0 :   CHECK_LEFT( sizeof(ulong) ); ulong json_str_sz = FD_LOAD( ulong, data+i ); i += sizeof(ulong);
      68             : 
      69           0 :   CHECK_LEFT( json_str_sz+1UL ); /* cJSON_ParseWithLengthOpts requires having byte after the JSON payload */
      70           0 :   cJSON * json = cJSON_ParseWithLengthOpts( (char *)(data+i), json_str_sz, NULL, 0 );
      71           0 :   if( FD_UNLIKELY( !json ) ) return 0;
      72             : 
      73           0 : #undef CHECK
      74           0 : #undef CHECK_LEFT
      75             : 
      76           0 :   *out_json = json;
      77           0 :   fd_memcpy( out_pubkey->uc, data_config_keys[1].pubkey.uc, sizeof(fd_pubkey_t) );
      78           0 :   return 1;
      79           0 : }
      80             : 
      81             : void
      82           0 : fd_gui_config_parse_validator_info( cJSON * json, fd_gui_config_parse_info_t * node_info ) {
      83           0 :   const cJSON * name = cJSON_GetObjectItemCaseSensitive( json, "name" );
      84             :   /* cJSON guarantees name->valuestring is NULL terminated */
      85           0 :   int missing_name = !cJSON_IsString( name )
      86           0 :                   || strlen(name->valuestring)>FD_GUI_CONFIG_PARSE_VALIDATOR_INFO_NAME_SZ
      87           0 :                   || !fd_cstr_printf_check( node_info->name, strlen(name->valuestring)+1UL, NULL, "%s", name->valuestring )
      88           0 :                   || !fd_utf8_verify( node_info->name, strlen(node_info->name) );
      89           0 :   if( FD_UNLIKELY( missing_name ) ) node_info->name[ 0 ] = '\0';
      90             : 
      91           0 :   const cJSON * website = cJSON_GetObjectItemCaseSensitive( json, "website" );
      92           0 :   int missing_website = !cJSON_IsString( website )
      93           0 :                      || strlen(website->valuestring)>FD_GUI_CONFIG_PARSE_VALIDATOR_INFO_WEBSITE_SZ
      94           0 :                      || !fd_cstr_printf_check( node_info->website, strlen(website->valuestring)+1UL, NULL, "%s", website->valuestring )
      95           0 :                      || !fd_utf8_verify( node_info->website, strlen(node_info->website) );
      96           0 :   if( FD_UNLIKELY( missing_website ) ) node_info->website[ 0 ] = '\0';
      97             : 
      98           0 :   const cJSON * details = cJSON_GetObjectItemCaseSensitive( json, "details" );
      99           0 :   int missing_details = !cJSON_IsString( details )
     100           0 :                      || strlen(details->valuestring)>FD_GUI_CONFIG_PARSE_VALIDATOR_INFO_DETAILS_SZ
     101           0 :                      || !fd_cstr_printf_check( node_info->details, strlen(details->valuestring)+1UL, NULL, "%s", details->valuestring )
     102           0 :                      || !fd_utf8_verify( node_info->details, strlen(node_info->details) );
     103           0 :   if( FD_UNLIKELY( missing_details ) ) node_info->details[ 0 ] = '\0';
     104             : 
     105           0 :   const cJSON * icon_uri = cJSON_GetObjectItemCaseSensitive( json, "iconUrl" );
     106           0 :   int missing_icon_uri = !cJSON_IsString( icon_uri )
     107           0 :                       || strlen(icon_uri->valuestring)>FD_GUI_CONFIG_PARSE_VALIDATOR_INFO_ICON_URI_SZ
     108           0 :                       || !fd_cstr_printf_check( node_info->icon_uri, strlen(icon_uri->valuestring)+1UL, NULL, "%s", icon_uri->valuestring )
     109           0 :                       || !fd_utf8_verify( node_info->icon_uri, strlen(node_info->icon_uri) );
     110           0 :   if( FD_UNLIKELY( missing_icon_uri ) ) node_info->icon_uri[ 0 ] = '\0';
     111             : 
     112           0 :   const cJSON * keybase_username = cJSON_GetObjectItemCaseSensitive( json, "keybaseUsername" );
     113           0 :   int missing_keybase_username = !cJSON_IsString( keybase_username )
     114           0 :                       || strlen(keybase_username->valuestring)>FD_GUI_CONFIG_PARSE_VALIDATOR_INFO_KEYBASE_USERNAME_SZ
     115           0 :                       || !fd_cstr_printf_check( node_info->keybase_username, strlen(keybase_username->valuestring)+1UL, NULL, "%s", keybase_username->valuestring )
     116           0 :                       || !fd_utf8_verify( node_info->keybase_username, strlen(node_info->keybase_username) );
     117           0 :   if( FD_UNLIKELY( missing_keybase_username ) ) node_info->keybase_username[ 0 ] = '\0';
     118             : 
     119           0 :   cJSON_Delete( json );
     120           0 : }

Generated by: LCOV version 1.14