11package  packfile
22
33import  (
4+ 	"bufio" 
45	"bytes" 
56	"errors" 
67	"io" 
8+ 	"math" 
79
810	"github.com/go-git/go-git/v5/plumbing" 
911	"github.com/go-git/go-git/v5/utils/ioutil" 
@@ -73,6 +75,131 @@ func PatchDelta(src, delta []byte) ([]byte, error) {
7375	return  b .Bytes (), nil 
7476}
7577
78+ func  ReaderFromDelta (h  * ObjectHeader , base  plumbing.EncodedObject , deltaRC  io.ReadCloser ) (io.ReadCloser , error ) {
79+ 	deltaBuf  :=  bufio .NewReaderSize (deltaRC , 1024 )
80+ 	srcSz , err  :=  decodeLEB128ByteReader (deltaBuf )
81+ 	if  err  !=  nil  {
82+ 		if  err  ==  io .EOF  {
83+ 			return  nil , ErrInvalidDelta 
84+ 		}
85+ 		return  nil , err 
86+ 	}
87+ 	if  srcSz  !=  uint (base .Size ()) {
88+ 		return  nil , ErrInvalidDelta 
89+ 	}
90+ 
91+ 	targetSz , err  :=  decodeLEB128ByteReader (deltaBuf )
92+ 	if  err  !=  nil  {
93+ 		if  err  ==  io .EOF  {
94+ 			return  nil , ErrInvalidDelta 
95+ 		}
96+ 		return  nil , err 
97+ 	}
98+ 	remainingTargetSz  :=  targetSz 
99+ 
100+ 	dstRd , dstWr  :=  io .Pipe ()
101+ 
102+ 	go  func () {
103+ 		baseRd , err  :=  base .Reader ()
104+ 		if  err  !=  nil  {
105+ 			_  =  dstWr .CloseWithError (ErrInvalidDelta )
106+ 			return 
107+ 		}
108+ 		defer  baseRd .Close ()
109+ 
110+ 		baseBuf  :=  bufio .NewReader (baseRd )
111+ 		basePos  :=  uint (0 )
112+ 
113+ 		for  {
114+ 			cmd , err  :=  deltaBuf .ReadByte ()
115+ 			if  err  ==  io .EOF  {
116+ 				_  =  dstWr .CloseWithError (ErrInvalidDelta )
117+ 				return 
118+ 			}
119+ 			if  err  !=  nil  {
120+ 				_  =  dstWr .CloseWithError (err )
121+ 				return 
122+ 			}
123+ 
124+ 			if  isCopyFromSrc (cmd ) {
125+ 				offset , err  :=  decodeOffsetByteReader (cmd , deltaBuf )
126+ 				if  err  !=  nil  {
127+ 					_  =  dstWr .CloseWithError (err )
128+ 					return 
129+ 				}
130+ 				sz , err  :=  decodeSizeByteReader (cmd , deltaBuf )
131+ 				if  err  !=  nil  {
132+ 					_  =  dstWr .CloseWithError (err )
133+ 					return 
134+ 				}
135+ 
136+ 				if  invalidSize (sz , targetSz ) || 
137+ 					invalidOffsetSize (offset , sz , srcSz ) {
138+ 					_  =  dstWr .Close ()
139+ 					return 
140+ 				}
141+ 
142+ 				discard  :=  offset  -  basePos 
143+ 				if  discard  <  0  {
144+ 					_  =  baseRd .Close ()
145+ 					baseRd , err  =  base .Reader ()
146+ 					if  err  !=  nil  {
147+ 						_  =  dstWr .CloseWithError (ErrInvalidDelta )
148+ 						return 
149+ 					}
150+ 					baseBuf .Reset (baseRd )
151+ 					discard  =  offset 
152+ 				}
153+ 				for  discard  >  math .MaxInt32  {
154+ 					n , err  :=  baseBuf .Discard (math .MaxInt32 )
155+ 					if  err  !=  nil  {
156+ 						_  =  dstWr .CloseWithError (err )
157+ 						return 
158+ 					}
159+ 					basePos  +=  uint (n )
160+ 					discard  -=  uint (n )
161+ 				}
162+ 				for  discard  >  0  {
163+ 					n , err  :=  baseBuf .Discard (int (discard ))
164+ 					if  err  !=  nil  {
165+ 						_  =  dstWr .CloseWithError (err )
166+ 						return 
167+ 					}
168+ 					basePos  +=  uint (n )
169+ 					discard  -=  uint (n )
170+ 				}
171+ 				if  _ , err  :=  io .Copy (dstWr , io .LimitReader (baseBuf , int64 (sz ))); err  !=  nil  {
172+ 					_  =  dstWr .CloseWithError (err )
173+ 					return 
174+ 				}
175+ 				remainingTargetSz  -=  sz 
176+ 				basePos  +=  sz 
177+ 			} else  if  isCopyFromDelta (cmd ) {
178+ 				sz  :=  uint (cmd ) // cmd is the size itself 
179+ 				if  invalidSize (sz , targetSz ) {
180+ 					_  =  dstWr .CloseWithError (ErrInvalidDelta )
181+ 					return 
182+ 				}
183+ 				if  _ , err  :=  io .Copy (dstWr , io .LimitReader (deltaBuf , int64 (sz ))); err  !=  nil  {
184+ 					_  =  dstWr .CloseWithError (err )
185+ 					return 
186+ 				}
187+ 
188+ 				remainingTargetSz  -=  sz 
189+ 			} else  {
190+ 				_  =  dstWr .CloseWithError (ErrDeltaCmd )
191+ 				return 
192+ 			}
193+ 			if  remainingTargetSz  <=  0  {
194+ 				_  =  dstWr .Close ()
195+ 				return 
196+ 			}
197+ 		}
198+ 	}()
199+ 
200+ 	return  dstRd , nil 
201+ }
202+ 
76203func  patchDelta (dst  * bytes.Buffer , src , delta  []byte ) error  {
77204	if  len (delta ) <  deltaSizeMin  {
78205		return  ErrInvalidDelta 
@@ -161,6 +288,25 @@ func decodeLEB128(input []byte) (uint, []byte) {
161288	return  num , input [sz :]
162289}
163290
291+ func  decodeLEB128ByteReader (input  io.ByteReader ) (uint , error ) {
292+ 	var  num , sz  uint 
293+ 	for  {
294+ 		b , err  :=  input .ReadByte ()
295+ 		if  err  !=  nil  {
296+ 			return  0 , err 
297+ 		}
298+ 
299+ 		num  |=  (uint (b ) &  payload ) <<  (sz  *  7 ) // concats 7 bits chunks 
300+ 		sz ++ 
301+ 
302+ 		if  uint (b )& continuation  ==  0  {
303+ 			break 
304+ 		}
305+ 	}
306+ 
307+ 	return  num , nil 
308+ }
309+ 
164310const  (
165311	payload       =  0x7f  // 0111 1111 
166312	continuation  =  0x80  // 1000 0000 
@@ -174,6 +320,40 @@ func isCopyFromDelta(cmd byte) bool {
174320	return  (cmd & 0x80 ) ==  0  &&  cmd  !=  0 
175321}
176322
323+ func  decodeOffsetByteReader (cmd  byte , delta  io.ByteReader ) (uint , error ) {
324+ 	var  offset  uint 
325+ 	if  (cmd  &  0x01 ) !=  0  {
326+ 		next , err  :=  delta .ReadByte ()
327+ 		if  err  !=  nil  {
328+ 			return  0 , err 
329+ 		}
330+ 		offset  =  uint (next )
331+ 	}
332+ 	if  (cmd  &  0x02 ) !=  0  {
333+ 		next , err  :=  delta .ReadByte ()
334+ 		if  err  !=  nil  {
335+ 			return  0 , err 
336+ 		}
337+ 		offset  |=  uint (next ) <<  8 
338+ 	}
339+ 	if  (cmd  &  0x04 ) !=  0  {
340+ 		next , err  :=  delta .ReadByte ()
341+ 		if  err  !=  nil  {
342+ 			return  0 , err 
343+ 		}
344+ 		offset  |=  uint (next ) <<  16 
345+ 	}
346+ 	if  (cmd  &  0x08 ) !=  0  {
347+ 		next , err  :=  delta .ReadByte ()
348+ 		if  err  !=  nil  {
349+ 			return  0 , err 
350+ 		}
351+ 		offset  |=  uint (next ) <<  24 
352+ 	}
353+ 
354+ 	return  offset , nil 
355+ }
356+ 
177357func  decodeOffset (cmd  byte , delta  []byte ) (uint , []byte , error ) {
178358	var  offset  uint 
179359	if  (cmd  &  0x01 ) !=  0  {
@@ -208,6 +388,36 @@ func decodeOffset(cmd byte, delta []byte) (uint, []byte, error) {
208388	return  offset , delta , nil 
209389}
210390
391+ func  decodeSizeByteReader (cmd  byte , delta  io.ByteReader ) (uint , error ) {
392+ 	var  sz  uint 
393+ 	if  (cmd  &  0x10 ) !=  0  {
394+ 		next , err  :=  delta .ReadByte ()
395+ 		if  err  !=  nil  {
396+ 			return  0 , err 
397+ 		}
398+ 		sz  =  uint (next )
399+ 	}
400+ 	if  (cmd  &  0x20 ) !=  0  {
401+ 		next , err  :=  delta .ReadByte ()
402+ 		if  err  !=  nil  {
403+ 			return  0 , err 
404+ 		}
405+ 		sz  |=  uint (next ) <<  8 
406+ 	}
407+ 	if  (cmd  &  0x40 ) !=  0  {
408+ 		next , err  :=  delta .ReadByte ()
409+ 		if  err  !=  nil  {
410+ 			return  0 , err 
411+ 		}
412+ 		sz  |=  uint (next ) <<  16 
413+ 	}
414+ 	if  sz  ==  0  {
415+ 		sz  =  0x10000 
416+ 	}
417+ 
418+ 	return  sz , nil 
419+ }
420+ 
211421func  decodeSize (cmd  byte , delta  []byte ) (uint , []byte , error ) {
212422	var  sz  uint 
213423	if  (cmd  &  0x10 ) !=  0  {
0 commit comments