Line data Source code
1 : #include "fd_vinyl_bstream.h" 2 : 3 : void 4 : fd_vinyl_bstream_pair_hash( ulong seed, 5 3000000 : fd_vinyl_bstream_block_t * hdr ) { 6 : 7 3000000 : ulong ctl = hdr->ctl; 8 3000000 : ulong val_esz = fd_vinyl_bstream_ctl_sz( ctl ); 9 : 10 3000000 : ulong pair_sz = fd_vinyl_bstream_pair_sz( val_esz ); 11 : 12 3000000 : fd_vinyl_bstream_block_t * ftr = (fd_vinyl_bstream_block_t *)((uchar *)hdr + pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ); 13 : 14 3000000 : ulong off = sizeof(fd_vinyl_bstream_phdr_t) + val_esz; 15 3000000 : ulong zsz = pair_sz - off; /* covers zpad and footer so at least FD_VINYL_BSTREAM_FTR_SZ */ 16 : 17 3000000 : memset( (uchar *)hdr + off, 0, zsz ); 18 : 19 3000000 : ulong hash_trail = fd_vinyl_bstream_hash( seed, hdr+1, pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ ); 20 3000000 : ulong hash_blocks = fd_vinyl_bstream_hash( hash_trail, hdr, FD_VINYL_BSTREAM_BLOCK_SZ ); 21 : 22 3000000 : ftr->ftr.hash_trail = hash_trail; 23 3000000 : ftr->ftr.hash_blocks = hash_blocks; 24 3000000 : } 25 : 26 : char const * 27 : fd_vinyl_bstream_pair_test( ulong seed, 28 : ulong seq, 29 : fd_vinyl_bstream_block_t * hdr, 30 24000000 : ulong buf_sz ) { 31 24000000 : (void)seq; 32 : 33 24000000 : if( FD_UNLIKELY( !hdr ) ) return "NULL buf"; 34 21000000 : if( FD_UNLIKELY( buf_sz<FD_VINYL_BSTREAM_BLOCK_SZ ) ) return "buf_sz too small"; 35 : 36 17450307 : ulong pair_ctl = hdr->ctl; 37 17450307 : int pair_type = fd_vinyl_bstream_ctl_type( pair_ctl ); 38 17450307 : ulong pair_val_esz = fd_vinyl_bstream_ctl_sz ( pair_ctl ); 39 17450307 : ulong pair_val_sz = (ulong)hdr->phdr.info.val_sz; 40 : 41 17450307 : ulong pair_sz = fd_vinyl_bstream_pair_sz( pair_val_esz ); 42 : 43 17450307 : if( FD_UNLIKELY( pair_type != FD_VINYL_BSTREAM_CTL_TYPE_PAIR ) ) return "unexpected type"; 44 14450307 : if( FD_UNLIKELY( pair_val_sz > FD_VINYL_VAL_MAX ) ) return "unexpected val size"; 45 11450307 : if( FD_UNLIKELY( buf_sz < pair_sz ) ) return "truncated pair"; 46 : 47 9000000 : fd_vinyl_bstream_block_t * ftr = (fd_vinyl_bstream_block_t *)((ulong)hdr + pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ); 48 : 49 9000000 : ulong hash_trail = ftr->ftr.hash_trail; 50 9000000 : ulong hash_blocks = ftr->ftr.hash_blocks; 51 : 52 9000000 : ftr->ftr.hash_trail = 0UL; 53 9000000 : ftr->ftr.hash_blocks = 0UL; 54 : 55 : /* FIXME: test zero padding? */ 56 : 57 9000000 : if( FD_UNLIKELY( fd_vinyl_bstream_hash( seed, hdr+1, pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_trail ) ) 58 3000000 : return "unexpected trailing hash"; 59 : 60 6000000 : if( FD_UNLIKELY( fd_vinyl_bstream_hash( hash_trail, hdr, FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_blocks ) ) 61 3000000 : return "unexpected pair hash"; 62 : 63 3000000 : return NULL; 64 6000000 : } 65 : 66 : char const * 67 : fd_vinyl_bstream_pair_test_fast( ulong seed, 68 : ulong seq, 69 : fd_vinyl_bstream_block_t const * hdr, 70 21000000 : fd_vinyl_bstream_block_t * ftr ) { 71 21000000 : (void)seq; 72 : 73 21000000 : if( FD_UNLIKELY( !hdr ) ) return "NULL hdr"; 74 18000000 : if( FD_UNLIKELY( !ftr ) ) return "NULL ftr"; 75 : 76 15000000 : ulong pair_ctl = hdr->ctl; 77 15000000 : int pair_type = fd_vinyl_bstream_ctl_type( pair_ctl ); 78 15000000 : ulong pair_val_esz = fd_vinyl_bstream_ctl_sz ( pair_ctl ); 79 15000000 : ulong pair_val_sz = (ulong)hdr->phdr.info.val_sz; 80 : 81 15000000 : ulong pair_sz = fd_vinyl_bstream_pair_sz( pair_val_esz ); 82 : 83 15000000 : if( FD_UNLIKELY( pair_type != FD_VINYL_BSTREAM_CTL_TYPE_PAIR ) ) return "unexpected type"; 84 12000000 : if( FD_UNLIKELY( pair_val_sz > FD_VINYL_VAL_MAX ) ) return "unexpected pair val size"; 85 : 86 9000000 : ulong hash_trail = ftr->ftr.hash_trail; 87 9000000 : ulong hash_blocks = ftr->ftr.hash_blocks; 88 : 89 9000000 : ftr->ftr.hash_trail = 0UL; 90 9000000 : ftr->ftr.hash_blocks = 0UL; 91 : 92 9000000 : if( FD_UNLIKELY( pair_sz <= 2UL*FD_VINYL_BSTREAM_BLOCK_SZ ) && 93 9000000 : FD_UNLIKELY( fd_vinyl_bstream_hash( seed, ftr, pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_trail ) ) 94 1774974 : return "unexpected trailing hash"; 95 : 96 7225026 : if( FD_UNLIKELY( fd_vinyl_bstream_hash( hash_trail, hdr, FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_blocks ) ) 97 4225026 : return "unexpected pair hash"; 98 : 99 3000000 : return NULL; 100 7225026 : } 101 : 102 : char const * 103 : fd_vinyl_bstream_dead_test( ulong seed, 104 : ulong seq, 105 0 : fd_vinyl_bstream_block_t * block ) { 106 : 107 0 : if( FD_UNLIKELY( !block ) ) return "NULL block"; 108 : 109 0 : ulong dead_info_sz = block->dead.info_sz; 110 : 111 0 : int bad_ctl = (block->dead.ctl != fd_vinyl_bstream_ctl( FD_VINYL_BSTREAM_CTL_TYPE_DEAD, 112 0 : FD_VINYL_BSTREAM_CTL_STYLE_RAW, 113 0 : FD_VINYL_BSTREAM_BLOCK_SZ ) ); 114 0 : int bad_match = !fd_vinyl_seq_eq( block->dead.seq, seq ); 115 0 : int bad_seq = (!fd_ulong_is_aligned( block->dead.seq, FD_VINYL_BSTREAM_BLOCK_SZ )); 116 0 : int bad_pair_type = (fd_vinyl_bstream_ctl_type( block->dead.phdr.ctl ) != FD_VINYL_BSTREAM_CTL_TYPE_PAIR); 117 0 : int bad_pair_val_sz = ((ulong)block->dead.phdr.info.val_sz > FD_VINYL_VAL_MAX); 118 0 : int bad_info_sz = (dead_info_sz > FD_VINYL_BSTREAM_DEAD_INFO_MAX); 119 : 120 0 : if( FD_UNLIKELY( bad_ctl | bad_match | bad_seq | bad_pair_type | bad_pair_val_sz | bad_info_sz ) ) 121 0 : return bad_ctl ? "unexpected dead ctl" : 122 0 : bad_match ? "mismatched dead seq" : 123 0 : bad_seq ? "misaligned dead seq" : 124 0 : bad_pair_type ? "unexpected dead pair type" : 125 0 : bad_pair_val_sz ? "unexpected dead pair val size" : 126 0 : "unexpected dead info size"; 127 : 128 0 : for( ulong zpad_idx=dead_info_sz; zpad_idx<FD_VINYL_BSTREAM_DEAD_INFO_MAX; zpad_idx++ ) 129 0 : if( FD_UNLIKELY( block->dead.info[ zpad_idx ] ) ) return "data in zero padding"; 130 : 131 0 : if( FD_UNLIKELY( fd_vinyl_bstream_block_test( seed, block ) ) ) return "corrupt block"; 132 : 133 0 : return NULL; 134 0 : } 135 : 136 : char const * 137 : fd_vinyl_bstream_move_test( ulong seed, 138 : ulong seq, 139 : fd_vinyl_bstream_block_t * block, 140 0 : fd_vinyl_bstream_block_t * dst ) { 141 : 142 0 : if( FD_UNLIKELY( !block ) ) return "NULL block"; 143 0 : if( FD_UNLIKELY( !dst ) ) return "NULL dst"; 144 : 145 0 : ulong move_info_sz = block->move.info_sz; 146 : 147 0 : int bad_ctl = (block->move.ctl != fd_vinyl_bstream_ctl( FD_VINYL_BSTREAM_CTL_TYPE_MOVE, 148 0 : FD_VINYL_BSTREAM_CTL_STYLE_RAW, 149 0 : FD_VINYL_BSTREAM_BLOCK_SZ ) ); 150 0 : int bad_match = !fd_vinyl_seq_eq( block->move.seq, seq ); 151 0 : int bad_seq = (!fd_ulong_is_aligned( block->move.seq, FD_VINYL_BSTREAM_BLOCK_SZ )); 152 0 : int bad_src_type = (fd_vinyl_bstream_ctl_type( block->move.src.ctl ) != FD_VINYL_BSTREAM_CTL_TYPE_PAIR); 153 0 : int bad_src_val_sz = ((ulong)block->move.src.info.val_sz > FD_VINYL_VAL_MAX); 154 0 : int bad_move = fd_vinyl_key_eq( &block->move.src.key, &block->move.dst ); 155 0 : int bad_info_sz = (move_info_sz > FD_VINYL_BSTREAM_MOVE_INFO_MAX); 156 0 : int bad_dst_type = (fd_vinyl_bstream_ctl_type( dst->phdr.ctl ) != FD_VINYL_BSTREAM_CTL_TYPE_PAIR); 157 0 : int bad_dst_key = (!fd_vinyl_key_eq( &block->move.dst, &dst->phdr.key )); 158 0 : int bad_dst_info = (!!memcmp( &block->move.src.info, &dst->phdr.info, FD_VINYL_INFO_SZ )); 159 : 160 0 : if( FD_UNLIKELY( bad_ctl | bad_match | bad_seq | bad_src_type | bad_src_val_sz | bad_move | bad_info_sz | 161 0 : bad_dst_type | bad_dst_key | bad_dst_info ) ) 162 0 : return bad_ctl ? "unexpected move ctl" : 163 0 : bad_match ? "mismatched move seq" : 164 0 : bad_seq ? "misaligned move seq" : 165 0 : bad_src_type ? "unexpected move src type" : 166 0 : bad_src_val_sz ? "unexpected move src val size" : 167 0 : bad_move ? "dst key matches src key" : 168 0 : bad_info_sz ? "unexpected move info size" : 169 0 : bad_dst_type ? "mismatched move dst type" : 170 0 : bad_dst_key ? "mismatched move dst key" : 171 0 : "mismatched move dst info"; 172 : 173 : # if 0 /* Note: with BLOCK_SZ==128, MOVE_INFO_MAX=0 and there's no move.info field due to language limitations */ 174 : for( ulong zpad_idx=move_info_sz; zpad_idx<FD_VINYL_BSTREAM_MOVE_INFO_MAX; zpad_idx++ ) 175 : if( FD_UNLIKELY( block->move.info[ zpad_idx ] ) ) return "data in zero padding"; 176 : # endif 177 : 178 0 : if( FD_UNLIKELY( fd_vinyl_bstream_block_test( seed, block ) ) ) return "corrupt block"; 179 : 180 0 : return NULL; 181 0 : } 182 : 183 : char const * 184 : fd_vinyl_bstream_part_test( ulong seed, 185 : ulong seq, 186 0 : fd_vinyl_bstream_block_t * block ) { 187 : 188 0 : if( FD_UNLIKELY( !block ) ) return "NULL block"; 189 : 190 0 : ulong part_seq = block->part.seq; 191 0 : ulong part_seq0 = block->part.seq0; 192 0 : ulong part_dead_cnt = block->part.dead_cnt; 193 0 : ulong part_move_cnt = block->part.move_cnt; 194 0 : ulong part_info_sz = block->part.info_sz; 195 : 196 0 : ulong part_block_cnt = (part_seq - part_seq0) / FD_VINYL_BSTREAM_BLOCK_SZ; 197 : 198 0 : int bad_ctl = (block->part.ctl != fd_vinyl_bstream_ctl( FD_VINYL_BSTREAM_CTL_TYPE_PART, 199 0 : FD_VINYL_BSTREAM_CTL_STYLE_RAW, 200 0 : FD_VINYL_BSTREAM_BLOCK_SZ ) ); 201 0 : int bad_match = !fd_vinyl_seq_eq( block->part.seq, seq ); 202 0 : int bad_seq = (!fd_ulong_is_aligned( part_seq, FD_VINYL_BSTREAM_BLOCK_SZ )); 203 0 : int bad_seq0 = (!fd_ulong_is_aligned( part_seq0, FD_VINYL_BSTREAM_BLOCK_SZ )); 204 0 : int bad_order = fd_vinyl_seq_gt( part_seq0, part_seq ); 205 0 : int bad_dead_cnt = (part_dead_cnt > part_block_cnt); 206 0 : int bad_move_cnt = ((2UL*part_move_cnt) > part_block_cnt); 207 0 : int bad_block_cnt = ((part_dead_cnt+2UL*part_move_cnt) > part_block_cnt); 208 0 : int bad_info_sz = (part_info_sz > FD_VINYL_BSTREAM_PART_INFO_MAX); 209 : 210 0 : if( FD_UNLIKELY( bad_ctl | bad_match | bad_seq | bad_seq0 | bad_order | 211 0 : bad_dead_cnt | bad_move_cnt | bad_block_cnt | bad_info_sz ) ) 212 0 : return bad_ctl ? "unexpected partition ctl" : 213 0 : bad_match ? "mismatched partition seq" : 214 0 : bad_seq ? "misaligned partition seq" : 215 0 : bad_seq0 ? "misaligned partition seq previous" : 216 0 : bad_order ? "unordered partition seq/seq previous" : 217 0 : bad_dead_cnt ? "unexpected partition dead count" : 218 0 : bad_move_cnt ? "unexpected partition move count" : 219 0 : bad_block_cnt ? "unexpected partition block count" : 220 0 : "unexpected partition info size"; 221 : 222 0 : for( ulong zpad_idx=part_info_sz; zpad_idx<FD_VINYL_BSTREAM_PART_INFO_MAX; zpad_idx++ ) 223 0 : if( FD_UNLIKELY( block->part.info[ zpad_idx ] ) ) return "data in zero padding"; 224 : 225 0 : if( FD_UNLIKELY( fd_vinyl_bstream_block_test( seed, block ) ) ) return "corrupt block"; 226 : 227 0 : return NULL; 228 0 : } 229 : 230 : char const * 231 : fd_vinyl_bstream_zpad_test( ulong seed, 232 : ulong seq, 233 6000000 : fd_vinyl_bstream_block_t * block ) { 234 6000000 : (void)seed; (void)seq; 235 : 236 6000000 : if( FD_UNLIKELY( !block ) ) return "NULL block"; 237 : 238 6000000 : ulong const * buf = (ulong const *)block->zpad; 239 6000000 : ulong cnt = FD_VINYL_BSTREAM_BLOCK_SZ / sizeof(ulong); 240 : 241 54000000 : for( ulong idx=0UL; idx<cnt; idx++ ) if( FD_UNLIKELY( buf[idx] ) ) return "data in zero padding"; 242 : 243 3000000 : return NULL; 244 6000000 : } 245 : 246 : char const * 247 9 : fd_vinyl_bstream_ctl_style_cstr( int style ) { 248 9 : switch( style ) { 249 3 : case FD_VINYL_BSTREAM_CTL_STYLE_RAW: return "raw"; 250 3 : case FD_VINYL_BSTREAM_CTL_STYLE_LZ4: return "lz4"; 251 3 : default: break; 252 9 : } 253 3 : return "unk"; 254 9 : } 255 : 256 : int 257 12 : fd_cstr_to_vinyl_bstream_ctl_style( char const * cstr ) { 258 12 : if( FD_UNLIKELY( !cstr ) ) return -1; 259 9 : if( !fd_cstr_casecmp( cstr, "raw" ) ) return FD_VINYL_BSTREAM_CTL_STYLE_RAW; 260 6 : if( !fd_cstr_casecmp( cstr, "lz4" ) ) return FD_VINYL_BSTREAM_CTL_STYLE_LZ4; 261 3 : return -1; 262 6 : }