@@ -28,14 +28,17 @@ struct solv_zchunk {
2828 unsigned int flags ; /* header flags */
2929 unsigned int comp ; /* compression type */
3030
31- unsigned char * data_chk_ptr ;
32- int data_chk_len ;
33- Chksum * data_chk ; /* for data checksum verification */
31+ unsigned int hdr_chk_type ; /* header + data checksum */
32+ unsigned int hdr_chk_len ;
33+ Id hdr_chk_id ;
3434
3535 unsigned int chunk_chk_type ; /* chunk checksum */
36- int chunk_chk_len ;
36+ unsigned int chunk_chk_len ;
3737 Id chunk_chk_id ;
3838
39+ Chksum * data_chk ; /* for data checksum verification */
40+ unsigned char * data_chk_ptr ;
41+
3942 unsigned int streamid ; /* stream we are reading */
4043 unsigned int nchunks ; /* chunks left */
4144 unsigned char * chunks ;
@@ -83,31 +86,32 @@ getuint(unsigned char *p, unsigned char *endp, unsigned int *dp)
8386 return 0 ;
8487}
8588
86- static int
87- chksum_len (unsigned int type )
88- {
89- if (type == 0 )
90- return 20 ;
91- if (type == 1 )
92- return 32 ;
93- if (type == 2 )
94- return 64 ;
95- if (type == 3 )
96- return 16 ;
97- return -1 ;
98- }
99-
100- static Id
101- chksum_id (unsigned int type )
89+ static unsigned char *
90+ getchksum (unsigned char * p , unsigned char * endp , unsigned int * typep , unsigned int * lenp , Id * idp )
10291{
103- if (type == 0 )
104- return REPOKEY_TYPE_SHA1 ;
105- if (type == 1 )
106- return REPOKEY_TYPE_SHA256 ;
107- if (type == 2 )
108- return REPOKEY_TYPE_SHA512 ;
109- if (type == 3 )
110- return REPOKEY_TYPE_SHA512 ;
92+ if ((p = getuint (p , endp , typep )) == 0 )
93+ return 0 ;
94+ switch (* typep )
95+ {
96+ case 0 :
97+ * lenp = 20 ;
98+ * idp = REPOKEY_TYPE_SHA1 ;
99+ return p ;
100+ case 1 :
101+ * lenp = 32 ;
102+ * idp = REPOKEY_TYPE_SHA256 ;
103+ return p ;
104+ case 2 :
105+ * lenp = 64 ;
106+ * idp = REPOKEY_TYPE_SHA512 ;
107+ return p ;
108+ case 3 :
109+ * lenp = 16 ;
110+ * idp = REPOKEY_TYPE_SHA512 ;
111+ return p ;
112+ default :
113+ break ;
114+ }
111115 return 0 ;
112116}
113117
@@ -131,7 +135,7 @@ static int
131135nextchunk (struct solv_zchunk * zck , unsigned int streamid )
132136{
133137 unsigned char * p = zck -> chunks ;
134- unsigned char * chunk_chksum ;
138+ unsigned char * chunk_chk_ptr ;
135139 unsigned int sid , chunk_len , uncompressed_len ;
136140 unsigned char * cbuf ;
137141
@@ -153,7 +157,7 @@ nextchunk(struct solv_zchunk *zck, unsigned int streamid)
153157 /* check if this is the correct stream */
154158 if ((zck -> flags & 1 ) != 0 && (p = getuint (p , zck -> hdr_end , & sid )) == 0 )
155159 return 0 ;
156- chunk_chksum = p ;
160+ chunk_chk_ptr = p ; /* remember for verification */
157161 p += zck -> chunk_chk_len ;
158162 if (p >= zck -> hdr_end )
159163 return 0 ;
@@ -182,7 +186,7 @@ nextchunk(struct solv_zchunk *zck, unsigned int streamid)
182186 if (zck -> data_chk )
183187 solv_chksum_add (zck -> data_chk , cbuf , chunk_len );
184188
185- /* verify the checksum */
189+ /* verify the chunk checksum */
186190 if (zck -> chunk_chk_id )
187191 {
188192 Chksum * chk = solv_chksum_create (zck -> chunk_chk_id );
@@ -192,7 +196,7 @@ nextchunk(struct solv_zchunk *zck, unsigned int streamid)
192196 return 0 ;
193197 }
194198 solv_chksum_add (chk , cbuf , chunk_len );
195- if (memcmp (solv_chksum_get (chk , 0 ), chunk_chksum , zck -> chunk_chk_len ) != 0 )
199+ if (memcmp (solv_chksum_get (chk , 0 ), chunk_chk_ptr , zck -> chunk_chk_len ) != 0 )
196200 {
197201 solv_chksum_free (chk , 0 );
198202 solv_free (cbuf );
@@ -218,7 +222,7 @@ nextchunk(struct solv_zchunk *zck, unsigned int streamid)
218222 {
219223 /* zstd compressed */
220224 size_t r ;
221- zck -> buf = solv_malloc (uncompressed_len + 1 );
225+ zck -> buf = solv_malloc (uncompressed_len + 1 ); /* +1 so we can detect too large frames */
222226 if (zck -> ddict )
223227 r = ZSTD_decompress_usingDDict (zck -> dctx , zck -> buf , uncompressed_len + 1 , cbuf , chunk_len , zck -> ddict );
224228 else
@@ -245,9 +249,6 @@ solv_zchunk_open(FILE *fp, unsigned int streamid)
245249{
246250 struct solv_zchunk * zck ;
247251 unsigned char * p ;
248- unsigned int hdr_chk_type ;
249- int hdr_chk_len ;
250- Id hdr_chk_id ;
251252 unsigned int hdr_size ; /* preface + index + signatures */
252253 unsigned int lead_size ;
253254 unsigned int preface_size ;
@@ -256,72 +257,64 @@ solv_zchunk_open(FILE *fp, unsigned int streamid)
256257
257258 zck = solv_calloc (1 , sizeof (* zck ));
258259
259- /* read the header */
260+ /* read and parse the lead, read the complete header */
260261 zck -> hdr = solv_calloc (15 , 1 );
262+ zck -> hdr_end = zck -> hdr + 15 ;
261263 if (fread (zck -> hdr , 15 , 1 , fp ) != 1 || memcmp (zck -> hdr , "\000ZCK1" , 5 ) != 0 )
262264 return open_error (zck );
263265 p = zck -> hdr + 5 ;
264- if ((p = getuint (p , zck -> hdr + 15 , & hdr_chk_type )) == 0 )
266+ if ((p = getchksum (p , zck -> hdr_end , & zck -> hdr_chk_type , & zck -> hdr_chk_len , & zck -> hdr_chk_id )) == 0 )
265267 return open_error (zck );
266- hdr_chk_len = chksum_len (hdr_chk_type );
267- if (hdr_chk_len < 0 )
268+ if ((p = getuint (p , zck -> hdr_end , & hdr_size )) == 0 || hdr_size > MAX_HDR_SIZE )
268269 return open_error (zck );
269- hdr_chk_id = chksum_id (hdr_chk_type );
270- if ((p = getuint (p , zck -> hdr + 15 , & hdr_size )) == 0 || hdr_size > MAX_HDR_SIZE )
271- return open_error (zck );
272- lead_size = p - zck -> hdr + hdr_chk_len ;
270+ lead_size = p - zck -> hdr + zck -> hdr_chk_len ;
273271 zck -> hdr = solv_realloc (zck -> hdr , lead_size + hdr_size );
274272 zck -> hdr_end = zck -> hdr + lead_size + hdr_size ;
275273 if (fread (zck -> hdr + 15 , lead_size + hdr_size - 15 , 1 , fp ) != 1 )
276274 return open_error (zck );
277275
278276 /* verify header checksum to guard against corrupt files */
279- if (hdr_chk_id )
277+ if (zck -> hdr_chk_id )
280278 {
281- Chksum * chk = solv_chksum_create (hdr_chk_id );
279+ Chksum * chk = solv_chksum_create (zck -> hdr_chk_id );
282280 if (!chk )
283281 return open_error (zck );
284- solv_chksum_add (chk , zck -> hdr , lead_size - hdr_chk_len );
282+ solv_chksum_add (chk , zck -> hdr , lead_size - zck -> hdr_chk_len );
285283 solv_chksum_add (chk , zck -> hdr + lead_size , hdr_size );
286- if (memcmp (solv_chksum_get (chk , 0 ), zck -> hdr + (lead_size - hdr_chk_len ), hdr_chk_len ) != 0 )
284+ if (memcmp (solv_chksum_get (chk , 0 ), zck -> hdr + (lead_size - zck -> hdr_chk_len ), zck -> hdr_chk_len ) != 0 )
287285 {
288286 solv_chksum_free (chk , 0 );
289287 return open_error (zck );
290288 }
291289 solv_chksum_free (chk , 0 );
292290 }
293291
294- /* parse preface */
292+ /* parse preface: data chksum, flags, compression */
295293 p = zck -> hdr + lead_size ;
296- if (p + hdr_chk_len + 4 > zck -> hdr_end )
294+ if (p + zck -> hdr_chk_len > zck -> hdr_end )
297295 return open_error (zck );
296+ zck -> data_chk_ptr = p ;
297+ p += zck -> hdr_chk_len ;
298298#ifdef VERIFY_DATA_CHKSUM
299- if (hdr_chk_id && (zck -> data_chk = solv_chksum_create (hdr_chk_id )) == 0 )
299+ if (zck -> hdr_chk_id && (zck -> data_chk = solv_chksum_create (zck -> hdr_chk_id )) == 0 )
300300 return open_error (zck );
301- zck -> data_chk_ptr = zck -> hdr + lead_size ;
302- zck -> data_chk_len = hdr_chk_len ;
303301#endif
304- p += hdr_chk_len ; /* skip data checksum */
305302 if ((p = getuint (p , zck -> hdr_end , & zck -> flags )) == 0 )
306303 return open_error (zck );
307304 if ((zck -> flags & ~(1 )) != 0 )
308305 return open_error (zck );
309306 if ((p = getuint (p , zck -> hdr_end , & zck -> comp )) == 0 || (zck -> comp != 0 && zck -> comp != 2 ))
310- return open_error (zck ); /* only uncompressed + zstd */
307+ return open_error (zck ); /* only uncompressed + zstd supported */
311308 preface_size = p - (zck -> hdr + lead_size );
312309
313- /* parse index */
310+ /* parse index: index size, index chksum type, num chunks, chunk data */
314311 if ((p = getuint (p , zck -> hdr_end , & index_size )) == 0 )
315312 return open_error (zck );
316313 if (hdr_size < preface_size + index_size )
317314 return open_error (zck );
318- if ((p = getuint (p , zck -> hdr_end , & zck -> chunk_chk_type )) == 0 )
319- return open_error (zck );
320- zck -> chunk_chk_len = chksum_len (zck -> chunk_chk_type );
321- if (zck -> chunk_chk_len < 0 )
315+ if ((p = getchksum (p , zck -> hdr_end , & zck -> chunk_chk_type , & zck -> chunk_chk_len , & zck -> chunk_chk_id )) == 0 )
322316 return open_error (zck );
323-
324- if ((p = getuint (p , zck -> hdr_end , & nchunks )) == 0 || nchunks > MAX_CHUNK_CNT )
317+ if ((p = getuint (p , zck -> hdr_end , & nchunks )) == 0 || nchunks < 1 || nchunks > MAX_CHUNK_CNT )
325318 return open_error (zck );
326319
327320 /* setup decompressor */
@@ -358,27 +351,25 @@ solv_zchunk_open(FILE *fp, unsigned int streamid)
358351 zck -> buf_avail = 0 ;
359352
360353 /* ready to read the rest of the chunks */
361- zck -> nchunks = nchunks ;
354+ zck -> nchunks = nchunks - 1 ; /* subtract 1 for the dict stream */
362355 return zck ;
363356}
364357
365358ssize_t
366359solv_zchunk_read (struct solv_zchunk * zck , char * buf , size_t len )
367360{
368361 size_t n = 0 ;
369- unsigned int bite ;
370362 if (!zck || zck -> eof == 2 )
371363 return -1 ;
372- if (!len || zck -> eof )
373- return 0 ;
374- for (;;)
364+ while (n < len && !zck -> eof )
375365 {
366+ unsigned int bite ;
376367 while (!zck -> buf_avail )
377368 {
378369 if (!zck -> nchunks )
379370 {
380371 /* verify data checksum if requested */
381- if (zck -> streamid != 0 && zck -> data_chk && memcmp (solv_chksum_get (zck -> data_chk , 0 ), zck -> data_chk_ptr , zck -> data_chk_len ) != 0 ) {
372+ if (zck -> streamid != 0 && zck -> data_chk && memcmp (solv_chksum_get (zck -> data_chk , 0 ), zck -> data_chk_ptr , zck -> hdr_chk_len ) != 0 ) {
382373 zck -> eof = 2 ;
383374 return -1 ;
384375 }
@@ -396,9 +387,8 @@ solv_zchunk_read(struct solv_zchunk *zck, char *buf, size_t len)
396387 n += bite ;
397388 zck -> buf_used += bite ;
398389 zck -> buf_avail -= bite ;
399- if (n == len )
400- return n ;
401390 }
391+ return n ;
402392}
403393
404394int
0 commit comments