1
1
package packfile
2
2
3
3
import (
4
+ "errors"
4
5
"io/ioutil"
5
6
6
7
"gopkg.in/src-d/go-git.v4/plumbing"
@@ -30,7 +31,11 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) error {
30
31
return err
31
32
}
32
33
33
- dst := PatchDelta (src , delta )
34
+ dst , err := PatchDelta (src , delta )
35
+ if err != nil {
36
+ return err
37
+ }
38
+
34
39
target .SetSize (int64 (len (dst )))
35
40
36
41
if _ , err := w .Write (dst ); err != nil {
@@ -40,15 +45,22 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) error {
40
45
return nil
41
46
}
42
47
48
+ var (
49
+ ErrInvalidDelta = errors .New ("invalid delta" )
50
+ ErrDeltaCmd = errors .New ("wrong delta command" )
51
+ )
52
+
43
53
// PatchDelta returns the result of applying the modification deltas in delta to src.
44
- func PatchDelta (src , delta []byte ) []byte {
54
+ // An error will be returned if delta is corrupted (ErrDeltaLen) or an action command
55
+ // is not copy from source or copy from delta (ErrDeltaCmd).
56
+ func PatchDelta (src , delta []byte ) ([]byte , error ) {
45
57
if len (delta ) < deltaSizeMin {
46
- return nil
58
+ return nil , ErrInvalidDelta
47
59
}
48
60
49
61
srcSz , delta := decodeLEB128 (delta )
50
62
if srcSz != uint (len (src )) {
51
- return nil
63
+ return nil , ErrInvalidDelta
52
64
}
53
65
54
66
targetSz , delta := decodeLEB128 (delta )
@@ -57,12 +69,25 @@ func PatchDelta(src, delta []byte) []byte {
57
69
var dest []byte
58
70
var cmd byte
59
71
for {
72
+ if len (delta ) == 0 {
73
+ return nil , ErrInvalidDelta
74
+ }
75
+
60
76
cmd = delta [0 ]
61
77
delta = delta [1 :]
62
78
if isCopyFromSrc (cmd ) {
63
79
var offset , sz uint
64
- offset , delta = decodeOffset (cmd , delta )
65
- sz , delta = decodeSize (cmd , delta )
80
+ var err error
81
+ offset , delta , err = decodeOffset (cmd , delta )
82
+ if err != nil {
83
+ return nil , err
84
+ }
85
+
86
+ sz , delta , err = decodeSize (cmd , delta )
87
+ if err != nil {
88
+ return nil , err
89
+ }
90
+
66
91
if invalidSize (sz , targetSz ) ||
67
92
invalidOffsetSize (offset , sz , srcSz ) {
68
93
break
@@ -72,21 +97,26 @@ func PatchDelta(src, delta []byte) []byte {
72
97
} else if isCopyFromDelta (cmd ) {
73
98
sz := uint (cmd ) // cmd is the size itself
74
99
if invalidSize (sz , targetSz ) {
75
- break
100
+ return nil , ErrInvalidDelta
101
+ }
102
+
103
+ if uint (len (delta )) < sz {
104
+ return nil , ErrInvalidDelta
76
105
}
106
+
77
107
dest = append (dest , delta [0 :sz ]... )
78
108
remainingTargetSz -= sz
79
109
delta = delta [sz :]
80
110
} else {
81
- return nil
111
+ return nil , ErrDeltaCmd
82
112
}
83
113
84
114
if remainingTargetSz <= 0 {
85
115
break
86
116
}
87
117
}
88
118
89
- return dest
119
+ return dest , nil
90
120
}
91
121
92
122
// Decodes a number encoded as an unsigned LEB128 at the start of some
@@ -124,47 +154,68 @@ func isCopyFromDelta(cmd byte) bool {
124
154
return (cmd & 0x80 ) == 0 && cmd != 0
125
155
}
126
156
127
- func decodeOffset (cmd byte , delta []byte ) (uint , []byte ) {
157
+ func decodeOffset (cmd byte , delta []byte ) (uint , []byte , error ) {
128
158
var offset uint
129
159
if (cmd & 0x01 ) != 0 {
160
+ if len (delta ) == 0 {
161
+ return 0 , nil , ErrInvalidDelta
162
+ }
130
163
offset = uint (delta [0 ])
131
164
delta = delta [1 :]
132
165
}
133
166
if (cmd & 0x02 ) != 0 {
167
+ if len (delta ) == 0 {
168
+ return 0 , nil , ErrInvalidDelta
169
+ }
134
170
offset |= uint (delta [0 ]) << 8
135
171
delta = delta [1 :]
136
172
}
137
173
if (cmd & 0x04 ) != 0 {
174
+ if len (delta ) == 0 {
175
+ return 0 , nil , ErrInvalidDelta
176
+ }
138
177
offset |= uint (delta [0 ]) << 16
139
178
delta = delta [1 :]
140
179
}
141
180
if (cmd & 0x08 ) != 0 {
181
+ if len (delta ) == 0 {
182
+ return 0 , nil , ErrInvalidDelta
183
+ }
142
184
offset |= uint (delta [0 ]) << 24
143
185
delta = delta [1 :]
144
186
}
145
187
146
- return offset , delta
188
+ return offset , delta , nil
147
189
}
148
190
149
- func decodeSize (cmd byte , delta []byte ) (uint , []byte ) {
191
+ func decodeSize (cmd byte , delta []byte ) (uint , []byte , error ) {
150
192
var sz uint
151
193
if (cmd & 0x10 ) != 0 {
194
+ if len (delta ) == 0 {
195
+ return 0 , nil , ErrInvalidDelta
196
+ }
152
197
sz = uint (delta [0 ])
153
198
delta = delta [1 :]
154
199
}
155
200
if (cmd & 0x20 ) != 0 {
201
+ if len (delta ) == 0 {
202
+ return 0 , nil , ErrInvalidDelta
203
+ }
156
204
sz |= uint (delta [0 ]) << 8
157
205
delta = delta [1 :]
158
206
}
159
207
if (cmd & 0x40 ) != 0 {
208
+ if len (delta ) == 0 {
209
+ return 0 , nil , ErrInvalidDelta
210
+ }
160
211
sz |= uint (delta [0 ]) << 16
161
212
delta = delta [1 :]
162
213
}
163
214
if sz == 0 {
164
215
sz = 0x10000
165
216
}
166
217
167
- return sz , delta
218
+ return sz , delta , nil
168
219
}
169
220
170
221
func invalidSize (sz , targetSz uint ) bool {
0 commit comments