@@ -276,7 +276,52 @@ static int encode_header(enum object_type type, unsigned long size, unsigned cha
276276 * we are going to reuse the existing object data as is. make
277277 * sure it is not corrupt.
278278 */
279- static int check_inflate (unsigned char * data , unsigned long len , unsigned long expect )
279+ static int check_pack_inflate (struct packed_git * p ,
280+ struct pack_window * * w_curs ,
281+ unsigned long offset ,
282+ unsigned long len ,
283+ unsigned long expect )
284+ {
285+ z_stream stream ;
286+ unsigned char fakebuf [4096 ], * in ;
287+ int st ;
288+
289+ memset (& stream , 0 , sizeof (stream ));
290+ inflateInit (& stream );
291+ do {
292+ in = use_pack (p , w_curs , offset , & stream .avail_in );
293+ stream .next_in = in ;
294+ stream .next_out = fakebuf ;
295+ stream .avail_out = sizeof (fakebuf );
296+ st = inflate (& stream , Z_FINISH );
297+ offset += stream .next_in - in ;
298+ } while (st == Z_OK || st == Z_BUF_ERROR );
299+ inflateEnd (& stream );
300+ return (st == Z_STREAM_END &&
301+ stream .total_out == expect &&
302+ stream .total_in == len ) ? 0 : -1 ;
303+ }
304+
305+ static void copy_pack_data (struct sha1file * f ,
306+ struct packed_git * p ,
307+ struct pack_window * * w_curs ,
308+ unsigned long offset ,
309+ unsigned long len )
310+ {
311+ unsigned char * in ;
312+ unsigned int avail ;
313+
314+ while (len ) {
315+ in = use_pack (p , w_curs , offset , & avail );
316+ if (avail > len )
317+ avail = len ;
318+ sha1write (f , in , avail );
319+ offset += avail ;
320+ len -= avail ;
321+ }
322+ }
323+
324+ static int check_loose_inflate (unsigned char * data , unsigned long len , unsigned long expect )
280325{
281326 z_stream stream ;
282327 unsigned char fakebuf [4096 ];
@@ -323,7 +368,7 @@ static int revalidate_loose_object(struct object_entry *entry,
323368 return -1 ;
324369 map += used ;
325370 mapsize -= used ;
326- return check_inflate (map , mapsize , size );
371+ return check_loose_inflate (map , mapsize , size );
327372}
328373
329374static unsigned long write_object (struct sha1file * f ,
@@ -416,6 +461,8 @@ static unsigned long write_object(struct sha1file *f,
416461 }
417462 else {
418463 struct packed_git * p = entry -> in_pack ;
464+ struct pack_window * w_curs = NULL ;
465+ unsigned long offset ;
419466
420467 if (entry -> delta ) {
421468 obj_type = (allow_ofs_delta && entry -> delta -> offset ) ?
@@ -437,16 +484,14 @@ static unsigned long write_object(struct sha1file *f,
437484 hdrlen += 20 ;
438485 }
439486
440- use_packed_git (p );
441- buf = (char * ) p -> pack_base
442- + entry -> in_pack_offset
443- + entry -> in_pack_header_size ;
487+ offset = entry -> in_pack_offset + entry -> in_pack_header_size ;
444488 datalen = find_packed_object_size (p , entry -> in_pack_offset )
445489 - entry -> in_pack_header_size ;
446- if (!pack_to_stdout && check_inflate (buf , datalen , entry -> size ))
490+ if (!pack_to_stdout && check_pack_inflate (p , & w_curs ,
491+ offset , datalen , entry -> size ))
447492 die ("corrupt delta in pack %s" , sha1_to_hex (entry -> sha1 ));
448- sha1write (f , buf , datalen );
449- unuse_packed_git ( p );
493+ copy_pack_data (f , p , & w_curs , offset , datalen );
494+ unuse_pack ( & w_curs );
450495 reused ++ ;
451496 }
452497 if (entry -> delta )
@@ -937,22 +982,19 @@ static void check_object(struct object_entry *entry)
937982
938983 if (entry -> in_pack && !entry -> preferred_base ) {
939984 struct packed_git * p = entry -> in_pack ;
985+ struct pack_window * w_curs = NULL ;
940986 unsigned long left = p -> pack_size - entry -> in_pack_offset ;
941987 unsigned long size , used ;
942988 unsigned char * buf ;
943989 struct object_entry * base_entry = NULL ;
944990
945- use_packed_git (p );
946- buf = p -> pack_base ;
947- buf += entry -> in_pack_offset ;
991+ buf = use_pack (p , & w_curs , entry -> in_pack_offset , NULL );
948992
949993 /* We want in_pack_type even if we do not reuse delta.
950994 * There is no point not reusing non-delta representations.
951995 */
952996 used = unpack_object_header_gently (buf , left ,
953997 & entry -> in_pack_type , & size );
954- if (!used || left - used <= 20 )
955- die ("corrupt pack for %s" , sha1_to_hex (entry -> sha1 ));
956998
957999 /* Check if it is delta, and the base is also an object
9581000 * we are going to pack. If so we will reuse the existing
@@ -961,36 +1003,42 @@ static void check_object(struct object_entry *entry)
9611003 if (!no_reuse_delta ) {
9621004 unsigned char c , * base_name ;
9631005 unsigned long ofs ;
1006+ unsigned long used_0 ;
9641007 /* there is at least 20 bytes left in the pack */
9651008 switch (entry -> in_pack_type ) {
9661009 case OBJ_REF_DELTA :
967- base_name = buf + used ;
1010+ base_name = use_pack (p , & w_curs ,
1011+ entry -> in_pack_offset + used , NULL );
9681012 used += 20 ;
9691013 break ;
9701014 case OBJ_OFS_DELTA :
971- c = buf [used ++ ];
1015+ buf = use_pack (p , & w_curs ,
1016+ entry -> in_pack_offset + used , NULL );
1017+ used_0 = 0 ;
1018+ c = buf [used_0 ++ ];
9721019 ofs = c & 127 ;
9731020 while (c & 128 ) {
9741021 ofs += 1 ;
9751022 if (!ofs || ofs & ~(~0UL >> 7 ))
9761023 die ("delta base offset overflow in pack for %s" ,
9771024 sha1_to_hex (entry -> sha1 ));
978- c = buf [used ++ ];
1025+ c = buf [used_0 ++ ];
9791026 ofs = (ofs << 7 ) + (c & 127 );
9801027 }
9811028 if (ofs >= entry -> in_pack_offset )
9821029 die ("delta base offset out of bound for %s" ,
9831030 sha1_to_hex (entry -> sha1 ));
9841031 ofs = entry -> in_pack_offset - ofs ;
9851032 base_name = find_packed_object_name (p , ofs );
1033+ used += used_0 ;
9861034 break ;
9871035 default :
9881036 base_name = NULL ;
9891037 }
9901038 if (base_name )
9911039 base_entry = locate_object_entry (base_name );
9921040 }
993- unuse_packed_git ( p );
1041+ unuse_pack ( & w_curs );
9941042 entry -> in_pack_header_size = used ;
9951043
9961044 if (base_entry ) {
0 commit comments