aboutsummaryrefslogtreecommitdiff
path: root/format
diff options
context:
space:
mode:
Diffstat (limited to 'format')
-rw-r--r--format/delta/apply/apply.go33
-rw-r--r--format/delta/apply/header.go5
-rw-r--r--format/pack/entry.go9
-rw-r--r--format/pack/pack.go4
4 files changed, 51 insertions, 0 deletions
diff --git a/format/delta/apply/apply.go b/format/delta/apply/apply.go
index f9f2fbaf..cd53f837 100644
--- a/format/delta/apply/apply.go
+++ b/format/delta/apply/apply.go
@@ -6,101 +6,129 @@ import "fmt"
// Apply applies one Git delta instruction stream to base.
func Apply(base, delta []byte) ([]byte, error) {
pos := 0
+
srcSize, err := readVarint(delta, &pos)
if err != nil {
return nil, err
}
+
dstSize, err := readVarint(delta, &pos)
if err != nil {
return nil, err
}
+
if srcSize != len(base) {
return nil, fmt.Errorf("format/delta/apply: delta source size mismatch: got %d want %d", srcSize, len(base))
}
out := make([]byte, dstSize)
outPos := 0
+
for pos < len(delta) {
op := delta[pos]
pos++
+
+ //nolint:nestif
if op&0x80 != 0 {
off := 0
+
if op&0x01 != 0 {
if pos >= len(delta) {
return nil, fmt.Errorf("format/delta/apply: malformed delta copy offset")
}
+
off |= int(delta[pos])
pos++
}
+
if op&0x02 != 0 {
if pos >= len(delta) {
return nil, fmt.Errorf("format/delta/apply: malformed delta copy offset")
}
+
off |= int(delta[pos]) << 8
pos++
}
+
if op&0x04 != 0 {
if pos >= len(delta) {
return nil, fmt.Errorf("format/delta/apply: malformed delta copy offset")
}
+
off |= int(delta[pos]) << 16
pos++
}
+
if op&0x08 != 0 {
if pos >= len(delta) {
return nil, fmt.Errorf("format/delta/apply: malformed delta copy offset")
}
+
off |= int(delta[pos]) << 24
pos++
}
n := 0
+
if op&0x10 != 0 {
if pos >= len(delta) {
return nil, fmt.Errorf("format/delta/apply: malformed delta copy size")
}
+
n |= int(delta[pos])
pos++
}
+
if op&0x20 != 0 {
if pos >= len(delta) {
return nil, fmt.Errorf("format/delta/apply: malformed delta copy size")
}
+
n |= int(delta[pos]) << 8
pos++
}
+
if op&0x40 != 0 {
if pos >= len(delta) {
return nil, fmt.Errorf("format/delta/apply: malformed delta copy size")
}
+
n |= int(delta[pos]) << 16
pos++
}
+
if n == 0 {
n = 0x10000
}
+
if off < 0 || n < 0 || off+n > len(base) || outPos+n > len(out) {
return nil, fmt.Errorf("format/delta/apply: delta copy out of bounds")
}
+
copy(out[outPos:outPos+n], base[off:off+n])
outPos += n
+
continue
}
if op == 0 {
return nil, fmt.Errorf("format/delta/apply: invalid delta opcode 0")
}
+
n := int(op)
if pos+n > len(delta) || outPos+n > len(out) {
return nil, fmt.Errorf("format/delta/apply: delta insert out of bounds")
}
+
copy(out[outPos:outPos+n], delta[pos:pos+n])
outPos += n
pos += n
}
+
if outPos != len(out) {
return nil, fmt.Errorf("format/delta/apply: delta output size mismatch: got %d want %d", outPos, len(out))
}
+
return out, nil
}
@@ -108,20 +136,25 @@ func Apply(base, delta []byte) ([]byte, error) {
func readVarint(buf []byte, pos *int) (int, error) {
value := 0
shift := uint(0)
+
for {
if *pos >= len(buf) {
return 0, fmt.Errorf("format/delta/apply: malformed delta varint")
}
+
b := buf[*pos]
*pos++
+
value |= int(b&0x7f) << shift
if b&0x80 == 0 {
break
}
+
shift += 7
if shift > 63 {
return 0, fmt.Errorf("format/delta/apply: delta varint overflow")
}
}
+
return value, nil
}
diff --git a/format/delta/apply/header.go b/format/delta/apply/header.go
index 996b006b..dbd29550 100644
--- a/format/delta/apply/header.go
+++ b/format/delta/apply/header.go
@@ -14,10 +14,12 @@ func ReadHeaderSizes(reader io.ByteReader) (int, int, error) {
if err != nil {
return 0, 0, err
}
+
dstSize, err := readVarintFromByteReader(reader)
if err != nil {
return 0, 0, err
}
+
return srcSize, dstSize, nil
}
@@ -25,15 +27,18 @@ func ReadHeaderSizes(reader io.ByteReader) (int, int, error) {
func readVarintFromByteReader(reader io.ByteReader) (int, error) {
value := 0
shift := uint(0)
+
for {
b, err := reader.ReadByte()
if err != nil {
return 0, fmt.Errorf("format/delta/apply: malformed delta varint: %w", err)
}
+
value |= int(b&0x7f) << shift
if b&0x80 == 0 {
return value, nil
}
+
shift += 7
if shift > 63 {
return 0, fmt.Errorf("format/delta/apply: delta varint overflow")
diff --git a/format/pack/entry.go b/format/pack/entry.go
index b95ad0ac..93d232a2 100644
--- a/format/pack/entry.go
+++ b/format/pack/entry.go
@@ -31,19 +31,23 @@ func ParseEntryHeader(data []byte) (EntryHeader, error) {
}
shift := uint(4)
+
b := first
for b&0x80 != 0 {
if header.HeaderSize >= len(data) {
return zero, fmt.Errorf("format/pack: truncated entry header")
}
+
b = data[header.HeaderSize]
header.HeaderSize++
header.Size |= int64(b&0x7f) << shift
shift += 7
}
+
if header.Size < 0 {
return zero, fmt.Errorf("format/pack: negative entry size")
}
+
return header, nil
}
@@ -73,6 +77,7 @@ func ParseEntry(data []byte, hashSize int) (Entry, error) {
if err != nil {
return zero, err
}
+
entry := Entry{
Type: header.Type,
Size: header.Size,
@@ -86,10 +91,12 @@ func ParseEntry(data []byte, hashSize int) (Entry, error) {
if hashSize <= 0 {
return zero, fmt.Errorf("format/pack: invalid hash size %d", hashSize)
}
+
end := entry.DataOffset + hashSize
if end > len(data) {
return zero, fmt.Errorf("format/pack: truncated ref-delta base id")
}
+
entry.RefBaseID = data[entry.DataOffset:end]
entry.DataOffset = end
case objecttype.TypeOfsDelta:
@@ -97,6 +104,7 @@ func ParseEntry(data []byte, hashSize int) (Entry, error) {
if err != nil {
return zero, err
}
+
entry.OfsBaseDistance = dist
entry.DataOffset += consumed
case objecttype.TypeInvalid, objecttype.TypeFuture:
@@ -108,5 +116,6 @@ func ParseEntry(data []byte, hashSize int) (Entry, error) {
if entry.DataOffset > len(data) {
return zero, fmt.Errorf("format/pack: entry data offset out of bounds")
}
+
return entry, nil
}
diff --git a/format/pack/pack.go b/format/pack/pack.go
index 45fe6a1c..e87e3360 100644
--- a/format/pack/pack.go
+++ b/format/pack/pack.go
@@ -33,16 +33,20 @@ func ParseOfsDeltaDistance(buf []byte) (uint64, int, error) {
if len(buf) == 0 {
return 0, 0, fmt.Errorf("format/pack: malformed ofs-delta distance")
}
+
b := buf[0]
dist := uint64(b & 0x7f)
+
consumed := 1
for b&0x80 != 0 {
if consumed >= len(buf) {
return 0, 0, fmt.Errorf("format/pack: malformed ofs-delta distance")
}
+
b = buf[consumed]
consumed++
dist = ((dist + 1) << 7) + uint64(b&0x7f)
}
+
return dist, consumed, nil
}