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 0 : fd_vinyl_bstream_block_t * hdr ) {
20 :
21 0 : ulong ctl = hdr->ctl;
22 0 : ulong val_esz = fd_vinyl_bstream_ctl_sz( ctl );
23 :
24 0 : ulong pair_sz = fd_vinyl_bstream_pair_sz( val_esz );
25 :
26 0 : fd_vinyl_bstream_block_t * ftr = (fd_vinyl_bstream_block_t *)((uchar *)hdr + pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ);
27 :
28 0 : ulong off = sizeof(fd_vinyl_bstream_phdr_t) + val_esz;
29 0 : ulong zsz = pair_sz - off; /* covers zpad and footer so at least FD_VINYL_BSTREAM_FTR_SZ */
30 :
31 0 : memset( (uchar *)hdr + off, 0, zsz );
32 :
33 0 : ulong hash_trail = fd_vinyl_bstream_hash( seed, hdr+1, pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ );
34 0 : ulong hash_blocks = fd_vinyl_bstream_hash( hash_trail, hdr, FD_VINYL_BSTREAM_BLOCK_SZ );
35 :
36 0 : ftr->ftr.hash_trail = hash_trail;
37 0 : ftr->ftr.hash_blocks = hash_blocks;
38 0 : }
39 :
40 : char const *
41 : fd_vinyl_bstream_pair_test( ulong seed,
42 : ulong seq,
43 : fd_vinyl_bstream_block_t * hdr,
44 0 : ulong buf_sz ) {
45 0 : (void)seq;
46 :
47 0 : if( FD_UNLIKELY( !hdr ) ) return "NULL buf";
48 0 : if( FD_UNLIKELY( buf_sz<FD_VINYL_BSTREAM_BLOCK_SZ ) ) return "buf_sz too small";
49 :
50 0 : ulong pair_ctl = hdr->ctl;
51 0 : int pair_type = fd_vinyl_bstream_ctl_type( pair_ctl );
52 0 : ulong pair_val_esz = fd_vinyl_bstream_ctl_sz ( pair_ctl );
53 0 : ulong pair_val_sz = (ulong)hdr->phdr.info.val_sz;
54 :
55 0 : ulong pair_sz = fd_vinyl_bstream_pair_sz( pair_val_esz );
56 :
57 0 : if( FD_UNLIKELY( pair_type != FD_VINYL_BSTREAM_CTL_TYPE_PAIR ) ) return "unexpected type";
58 0 : if( FD_UNLIKELY( pair_val_sz > FD_VINYL_VAL_MAX ) ) return "unexpected val size";
59 0 : if( FD_UNLIKELY( buf_sz < pair_sz ) ) return "truncated pair";
60 :
61 0 : fd_vinyl_bstream_block_t * ftr = (fd_vinyl_bstream_block_t *)((ulong)hdr + pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ);
62 :
63 0 : ulong hash_trail = ftr->ftr.hash_trail;
64 0 : ulong hash_blocks = ftr->ftr.hash_blocks;
65 :
66 0 : ftr->ftr.hash_trail = 0UL;
67 0 : ftr->ftr.hash_blocks = 0UL;
68 :
69 : /* FIXME: test zero padding? */
70 :
71 0 : if( FD_UNLIKELY( fd_vinyl_bstream_hash( seed, hdr+1, pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_trail ) )
72 0 : return "unexpected trailing hash";
73 :
74 0 : if( FD_UNLIKELY( fd_vinyl_bstream_hash( hash_trail, hdr, FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_blocks ) )
75 0 : return "unexpected pair hash";
76 :
77 0 : return NULL;
78 0 : }
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 0 : fd_vinyl_bstream_block_t * ftr ) {
85 0 : (void)seq;
86 :
87 0 : if( FD_UNLIKELY( !hdr ) ) return "NULL hdr";
88 0 : if( FD_UNLIKELY( !ftr ) ) return "NULL ftr";
89 :
90 0 : ulong pair_ctl = hdr->ctl;
91 0 : int pair_type = fd_vinyl_bstream_ctl_type( pair_ctl );
92 0 : ulong pair_val_esz = fd_vinyl_bstream_ctl_sz ( pair_ctl );
93 0 : ulong pair_val_sz = (ulong)hdr->phdr.info.val_sz;
94 :
95 0 : ulong pair_sz = fd_vinyl_bstream_pair_sz( pair_val_esz );
96 :
97 0 : if( FD_UNLIKELY( pair_type != FD_VINYL_BSTREAM_CTL_TYPE_PAIR ) ) return "unexpected type";
98 0 : if( FD_UNLIKELY( pair_val_sz > FD_VINYL_VAL_MAX ) ) return "unexpected pair val size";
99 :
100 0 : ulong hash_trail = ftr->ftr.hash_trail;
101 0 : ulong hash_blocks = ftr->ftr.hash_blocks;
102 :
103 0 : ftr->ftr.hash_trail = 0UL;
104 0 : ftr->ftr.hash_blocks = 0UL;
105 :
106 0 : if( FD_UNLIKELY( pair_sz <= 2UL*FD_VINYL_BSTREAM_BLOCK_SZ ) &&
107 0 : FD_UNLIKELY( fd_vinyl_bstream_hash( seed, ftr, pair_sz - FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_trail ) )
108 0 : return "unexpected trailing hash";
109 :
110 0 : if( FD_UNLIKELY( fd_vinyl_bstream_hash( hash_trail, hdr, FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_blocks ) )
111 0 : return "unexpected pair hash";
112 :
113 0 : return NULL;
114 0 : }
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 : # if 0 /* Note: with BLOCK_SZ==128, MOVE_INFO_MAX=0 and there's no move.info field due to language limitations */
188 : for( ulong zpad_idx=move_info_sz; zpad_idx<FD_VINYL_BSTREAM_MOVE_INFO_MAX; zpad_idx++ )
189 : if( FD_UNLIKELY( block->move.info[ zpad_idx ] ) ) return "data in zero padding";
190 : # endif
191 :
192 0 : if( FD_UNLIKELY( fd_vinyl_bstream_block_test( seed, block ) ) ) return "corrupt block";
193 :
194 0 : return NULL;
195 0 : }
196 :
197 : char const *
198 : fd_vinyl_bstream_part_test( ulong seed,
199 : ulong seq,
200 0 : fd_vinyl_bstream_block_t * block ) {
201 :
202 0 : if( FD_UNLIKELY( !block ) ) return "NULL block";
203 :
204 0 : ulong part_seq = block->part.seq;
205 0 : ulong part_seq0 = block->part.seq0;
206 0 : ulong part_dead_cnt = block->part.dead_cnt;
207 0 : ulong part_move_cnt = block->part.move_cnt;
208 0 : ulong part_info_sz = block->part.info_sz;
209 :
210 0 : ulong part_block_cnt = (part_seq - part_seq0) / FD_VINYL_BSTREAM_BLOCK_SZ;
211 :
212 0 : int bad_ctl = (block->part.ctl != fd_vinyl_bstream_ctl( FD_VINYL_BSTREAM_CTL_TYPE_PART,
213 0 : FD_VINYL_BSTREAM_CTL_STYLE_RAW,
214 0 : FD_VINYL_BSTREAM_BLOCK_SZ ) );
215 0 : int bad_match = !fd_vinyl_seq_eq( block->part.seq, seq );
216 0 : int bad_seq = (!fd_ulong_is_aligned( part_seq, FD_VINYL_BSTREAM_BLOCK_SZ ));
217 0 : int bad_seq0 = (!fd_ulong_is_aligned( part_seq0, FD_VINYL_BSTREAM_BLOCK_SZ ));
218 0 : int bad_order = fd_vinyl_seq_gt( part_seq0, part_seq );
219 0 : int bad_dead_cnt = (part_dead_cnt > part_block_cnt);
220 0 : int bad_move_cnt = ((2UL*part_move_cnt) > part_block_cnt);
221 0 : int bad_block_cnt = ((part_dead_cnt+2UL*part_move_cnt) > part_block_cnt);
222 0 : int bad_info_sz = (part_info_sz > FD_VINYL_BSTREAM_PART_INFO_MAX);
223 :
224 0 : if( FD_UNLIKELY( bad_ctl | bad_match | bad_seq | bad_seq0 | bad_order |
225 0 : bad_dead_cnt | bad_move_cnt | bad_block_cnt | bad_info_sz ) )
226 0 : return bad_ctl ? "unexpected partition ctl" :
227 0 : bad_match ? "mismatched partition seq" :
228 0 : bad_seq ? "misaligned partition seq" :
229 0 : bad_seq0 ? "misaligned partition seq previous" :
230 0 : bad_order ? "unordered partition seq/seq previous" :
231 0 : bad_dead_cnt ? "unexpected partition dead count" :
232 0 : bad_move_cnt ? "unexpected partition move count" :
233 0 : bad_block_cnt ? "unexpected partition block count" :
234 0 : "unexpected partition info size";
235 :
236 0 : for( ulong zpad_idx=part_info_sz; zpad_idx<FD_VINYL_BSTREAM_PART_INFO_MAX; zpad_idx++ )
237 0 : if( FD_UNLIKELY( block->part.info[ zpad_idx ] ) ) return "data in zero padding";
238 :
239 0 : if( FD_UNLIKELY( fd_vinyl_bstream_block_test( seed, block ) ) ) return "corrupt block";
240 :
241 0 : return NULL;
242 0 : }
243 :
244 : char const *
245 : fd_vinyl_bstream_zpad_test( ulong seed,
246 : ulong seq,
247 0 : fd_vinyl_bstream_block_t * block ) {
248 0 : (void)seed; (void)seq;
249 :
250 0 : if( FD_UNLIKELY( !block ) ) return "NULL block";
251 :
252 0 : ulong const * buf = (ulong const *)block->zpad;
253 0 : ulong cnt = FD_VINYL_BSTREAM_BLOCK_SZ / sizeof(ulong);
254 :
255 0 : for( ulong idx=0UL; idx<cnt; idx++ ) if( FD_UNLIKELY( buf[idx] ) ) return "data in zero padding";
256 :
257 0 : return NULL;
258 0 : }
259 :
260 : char const *
261 0 : fd_vinyl_bstream_ctl_style_cstr( int style ) {
262 0 : switch( style ) {
263 0 : case FD_VINYL_BSTREAM_CTL_STYLE_RAW: return "raw";
264 0 : case FD_VINYL_BSTREAM_CTL_STYLE_LZ4: return "lz4";
265 0 : default: break;
266 0 : }
267 0 : return "unk";
268 0 : }
269 :
270 : int
271 0 : fd_cstr_to_vinyl_bstream_ctl_style( char const * cstr ) {
272 0 : if( FD_UNLIKELY( !cstr ) ) return -1;
273 0 : if( !fd_cstr_casecmp( cstr, "raw" ) ) return FD_VINYL_BSTREAM_CTL_STYLE_RAW;
274 0 : if( !fd_cstr_casecmp( cstr, "lz4" ) ) return FD_VINYL_BSTREAM_CTL_STYLE_LZ4;
275 0 : return -1;
276 0 : }
|