LCOV - code coverage report
Current view: top level - ballet/bmtree - fuzz_bmtree.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 6 78 7.7 %
Date: 2024-11-13 11:58:15 Functions: 1 2 50.0 %

          Line data    Source code
       1             : #if !FD_HAS_HOSTED
       2             : #error "This target requires FD_HAS_HOSTED"
       3             : #endif
       4             : 
       5             : #include <assert.h>
       6             : #include <stdio.h>
       7             : #include <stdlib.h>
       8             : 
       9             : #include "../../util/fd_util.h"
      10             : #include "../../util/sanitize/fd_fuzz.h"
      11             : #include "fd_bmtree.h"
      12             : 
      13             : #define MAX_LEAF_CNT (256UL)
      14             : #define MAX_DEPTH (9UL)
      15             : #define MEMORY_SZ (70UL*1024UL*1024UL)
      16             : 
      17             : static uchar memory1[ MEMORY_SZ ];
      18             : static uchar memory2[ MEMORY_SZ ];
      19             : static uchar inc_proof[ 32UL * ( MAX_DEPTH - 1UL ) ];
      20             : 
      21             : int
      22             : LLVMFuzzerInitialize( int  *   pargc,
      23          18 :                       char *** pargv ) {
      24             :   /* Set up shell without signal handlers */
      25          18 :   putenv( "FD_LOG_BACKTRACE=0" );
      26          18 :   fd_boot( pargc, pargv );
      27          18 :   atexit( fd_halt );
      28          18 :   return 0;
      29          18 : }
      30             : 
      31             : static int
      32             : fuzz_bmtree( fd_bmtree_node_t const * leafs,
      33             :              ulong leaf_cnt,
      34             :              ulong hash_sz,
      35           0 :              ulong prefix_sz ) {
      36             : 
      37             :   /* figure out the footprint needed given the leaf_cnt */
      38           0 :   ulong depth = fd_bmtree_depth( leaf_cnt );
      39             : 
      40           0 :   if( FD_UNLIKELY( depth > MAX_DEPTH ) ) return -1;
      41           0 :   ulong footprint = fd_bmtree_commit_footprint( depth );
      42             : 
      43             :   /* check that we have enough memory, check for overflows along the way */
      44           0 :   uchar * memory_start = memory1;
      45           0 :   uchar * first_tree_end = memory_start+footprint;
      46           0 :   if( FD_UNLIKELY( first_tree_end<memory_start || (ulong)first_tree_end<footprint ) ) {
      47           0 :     return -1;
      48           0 :   }
      49             : 
      50           0 :   uchar * second_tree_start = (uchar *)fd_ulong_align_up( (ulong)first_tree_end, FD_BMTREE_COMMIT_ALIGN );
      51           0 :   if( FD_UNLIKELY( second_tree_start<first_tree_end ) ) {
      52           0 :     printf("FD_UNLIKELY( second_tree_start<first_tree_end )\n");
      53           0 :     return -1;
      54           0 :   }
      55             : 
      56           0 :   uchar * memory_end = second_tree_start+footprint;
      57           0 :   if( FD_UNLIKELY( memory_end<second_tree_start || (ulong)memory_end<footprint ) ) {
      58           0 :     printf("FD_UNLIKELY( memory_end<second_tree_start || memory_end<footprint )\n");
      59           0 :     return -1;
      60           0 :   }
      61             : 
      62           0 :   ulong memory_required = (ulong) (memory_end - memory_start);
      63           0 :   if( FD_UNLIKELY( memory_required > MEMORY_SZ ) ) {
      64           0 :     printf("FD_UNLIKELY( memory_required < MEMORY_SZ )\n");
      65           0 :     printf("%lu < %lu\n", memory_required, MEMORY_SZ);
      66           0 :     return -1;
      67           0 :   }
      68             : 
      69             :   /* create first tree from leafs */
      70           0 :   fd_bmtree_commit_t * tree = fd_bmtree_commit_init( memory1, hash_sz, prefix_sz, 0UL );
      71           0 :   assert( tree );
      72             : 
      73             :   /* no leaf has been appended thus far */
      74           0 :   assert( 0UL == fd_bmtree_commit_leaf_cnt( tree ) );
      75             : 
      76             :   /* append all leafs */
      77           0 :   assert( tree == fd_bmtree_commit_append( tree, leafs, leaf_cnt ) );
      78             : 
      79             :   /* tree has the expected amount of leafs */
      80           0 :   assert( leaf_cnt == fd_bmtree_commit_leaf_cnt( tree ) );
      81             : 
      82             :   /* commit to the tree */
      83           0 :   uchar * root_1 = fd_bmtree_commit_fini( tree );
      84           0 :   assert( root_1 );
      85             : 
      86           0 :   assert( leaf_cnt == fd_bmtree_commit_leaf_cnt( tree ) );
      87             : 
      88             :   /* create second tree from proofs */
      89           0 :   fd_bmtree_commit_t * tree2 = fd_bmtree_commit_init( memory2, hash_sz, prefix_sz, depth );
      90           0 :   assert( tree2 );
      91             : 
      92           0 :   fd_bmtree_node_t proof_root_1[1];
      93           0 :   fd_bmtree_node_t proof_root_2[1];
      94           0 :   fd_bmtree_node_t leaf[1];
      95             : 
      96           0 :   for( ulong i=0UL; i<leaf_cnt; i++ ) {
      97           0 :     fd_memcpy( leaf, leafs+i, sizeof( fd_bmtree_node_t ) );
      98             : 
      99           0 :     int res = fd_bmtree_get_proof( tree, inc_proof, i );
     100           0 :     if ( res == -1 ) {
     101           0 :       FD_FUZZ_MUST_BE_COVERED;
     102           0 :       return 0;
     103           0 :     }
     104             : 
     105           0 :     assert( proof_root_1 == fd_bmtree_from_proof( leaf, i, proof_root_1, inc_proof, depth-1UL, hash_sz, prefix_sz ) );
     106             : 
     107           0 :     assert( fd_memeq( root_1, proof_root_1, hash_sz ) );
     108             : 
     109           0 :     assert( fd_bmtree_commitp_insert_with_proof( tree2, i, leaf, inc_proof, depth-1UL, proof_root_2 ) );
     110             : 
     111           0 :     assert( fd_memeq( root_1, proof_root_2, hash_sz ) );
     112             : 
     113           0 :     if( FD_LIKELY( leaf_cnt>1UL ) ) {
     114           0 :       FD_FUZZ_MUST_BE_COVERED;
     115           0 :       inc_proof[ 1 ]++; /* Corrupt the proof */
     116           0 :       assert( proof_root_1 == fd_bmtree_from_proof( leaf, i, proof_root_1, inc_proof, depth-1UL, hash_sz, prefix_sz ) );
     117             : 
     118           0 :       assert( !fd_memeq( root_1, proof_root_1, hash_sz ) );
     119             : 
     120           0 :       assert( !fd_bmtree_commitp_insert_with_proof( tree2, i, leaf, inc_proof, depth-1UL, NULL ) );
     121             : 
     122           0 :       inc_proof[ 1 ]--;
     123           0 :     } /* Otherwise the proof is empty, so there's nothing to corrupt */
     124             : 
     125           0 :     root_1[ 1 ]++; /* Corrupt the root */
     126           0 :     assert( proof_root_1 == fd_bmtree_from_proof( leaf, i, proof_root_1, inc_proof, depth-1UL, hash_sz, prefix_sz ) );
     127             : 
     128           0 :     assert( !fd_memeq( root_1, proof_root_1, hash_sz ) );
     129             : 
     130           0 :     root_1[ 1 ]--;
     131             : 
     132           0 :     leaf->hash[ 1 ]++; /* Corrupt the leaf */
     133           0 :     assert( proof_root_1 == fd_bmtree_from_proof( leaf, i, proof_root_1, inc_proof, depth-1UL, hash_sz, prefix_sz ) );
     134             : 
     135           0 :     assert( !fd_memeq( root_1, proof_root_1, hash_sz ) );
     136             : 
     137           0 :     assert( !fd_bmtree_commitp_insert_with_proof( tree2, i, leaf, inc_proof, depth-1UL, NULL ) );
     138             : 
     139           0 :     leaf->hash[ 1 ]--;
     140           0 :   }
     141           0 :   uchar * root_2 = fd_bmtree_commitp_fini( tree2, leaf_cnt );
     142           0 :   assert( root_2 );
     143             : 
     144           0 :   assert( fd_memeq( root_1, root_2, hash_sz ) );
     145             : 
     146           0 :   return 0;
     147           0 : }
     148             : 
     149             : struct bmtree_test {
     150             :   ulong leaf_cnt;
     151             :   uchar leaf_hashes[ ];
     152             : };
     153             : typedef struct bmtree_test bmtree_test_t;
     154             : 
     155             : int
     156             : LLVMFuzzerTestOneInput( uchar const * data,
     157             :                         ulong         size ) {
     158             :   if( FD_UNLIKELY( size<sizeof( bmtree_test_t ) ) ) return -1;
     159             :   bmtree_test_t * const test = ( bmtree_test_t * const ) data;
     160             :   ulong leaf_cnt = test->leaf_cnt % MAX_LEAF_CNT + 1UL;
     161             : 
     162             :   if( FD_UNLIKELY( size<sizeof( bmtree_test_t )+leaf_cnt*sizeof( fd_bmtree_node_t ) ) ) return -1;
     163             :   fd_bmtree_node_t const * leafs = ( fd_bmtree_node_t const * ) test->leaf_hashes;
     164             : 
     165             :   int result = fuzz_bmtree( leafs, leaf_cnt, 32UL, FD_BMTREE_SHORT_PREFIX_SZ );
     166             :   if ( result != 0 ) {
     167             :     return result;
     168             :   }
     169             : 
     170             :   result = fuzz_bmtree( leafs, leaf_cnt, 20UL, FD_BMTREE_LONG_PREFIX_SZ );
     171             : 
     172             :   FD_FUZZ_MUST_BE_COVERED;
     173             :   return result;
     174             : }

Generated by: LCOV version 1.14