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