Skip to content

Commit 00e1103

Browse files
committed
fix crashes found with go-fuzz.
1 parent b3f26eb commit 00e1103

File tree

2 files changed

+121
-7
lines changed

2 files changed

+121
-7
lines changed

decode.go

+68-7
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,17 @@ func decodemac(pkt []byte) uint64 {
7171

7272
// Decode decodes the headers of a Packet.
7373
func (p *Packet) Decode() {
74+
if len(p.Data) <= 14 {
75+
return
76+
}
77+
7478
p.Type = int(binary.BigEndian.Uint16(p.Data[12:14]))
7579
p.DestMac = decodemac(p.Data[0:6])
7680
p.SrcMac = decodemac(p.Data[6:12])
77-
p.Payload = p.Data[14:]
81+
82+
if len(p.Data) >= 15 {
83+
p.Payload = p.Data[14:]
84+
}
7885

7986
switch p.Type {
8087
case TYPE_IP:
@@ -163,20 +170,31 @@ func (arp *Arphdr) String() (s string) {
163170
}
164171

165172
func (p *Packet) decodeArp() {
173+
if len(p.Payload) < 8 {
174+
return
175+
}
176+
166177
pkt := p.Payload
167178
arp := new(Arphdr)
168179
arp.Addrtype = binary.BigEndian.Uint16(pkt[0:2])
169180
arp.Protocol = binary.BigEndian.Uint16(pkt[2:4])
170181
arp.HwAddressSize = pkt[4]
171182
arp.ProtAddressSize = pkt[5]
172183
arp.Operation = binary.BigEndian.Uint16(pkt[6:8])
184+
185+
if len(pkt) < int(8+2*arp.HwAddressSize+2*arp.ProtAddressSize) {
186+
return
187+
}
173188
arp.SourceHwAddress = pkt[8 : 8+arp.HwAddressSize]
174189
arp.SourceProtAddress = pkt[8+arp.HwAddressSize : 8+arp.HwAddressSize+arp.ProtAddressSize]
175190
arp.DestHwAddress = pkt[8+arp.HwAddressSize+arp.ProtAddressSize : 8+2*arp.HwAddressSize+arp.ProtAddressSize]
176191
arp.DestProtAddress = pkt[8+2*arp.HwAddressSize+arp.ProtAddressSize : 8+2*arp.HwAddressSize+2*arp.ProtAddressSize]
177192

178193
p.Headers = append(p.Headers, arp)
179-
p.Payload = p.Payload[8+2*arp.HwAddressSize+2*arp.ProtAddressSize:]
194+
195+
if len(pkt) >= int(8+2*arp.HwAddressSize+2*arp.ProtAddressSize) {
196+
p.Payload = p.Payload[8+2*arp.HwAddressSize+2*arp.ProtAddressSize:]
197+
}
180198
}
181199

182200
// IPadr is the header of an IP packet.
@@ -196,6 +214,10 @@ type Iphdr struct {
196214
}
197215

198216
func (p *Packet) decodeIp() {
217+
if len(p.Payload) < 20 {
218+
return
219+
}
220+
199221
pkt := p.Payload
200222
ip := new(Iphdr)
201223

@@ -212,11 +234,18 @@ func (p *Packet) decodeIp() {
212234
ip.Checksum = binary.BigEndian.Uint16(pkt[10:12])
213235
ip.SrcIp = pkt[12:16]
214236
ip.DestIp = pkt[16:20]
237+
215238
pEnd := int(ip.Length)
216239
if pEnd > len(pkt) {
217240
pEnd = len(pkt)
218241
}
219-
p.Payload = pkt[ip.Ihl*4 : pEnd]
242+
243+
if len(pkt) >= pEnd && int(ip.Ihl*4) < pEnd {
244+
p.Payload = pkt[ip.Ihl*4 : pEnd]
245+
} else {
246+
p.Payload = []byte{}
247+
}
248+
220249
p.Headers = append(p.Headers, ip)
221250
p.IP = ip
222251

@@ -250,12 +279,20 @@ func (v *Vlanhdr) String() {
250279
func (p *Packet) decodeVlan() {
251280
pkt := p.Payload
252281
vlan := new(Vlanhdr)
282+
if len(pkt) < 4 {
283+
return
284+
}
285+
253286
vlan.Priority = (pkt[2] & 0xE0) >> 13
254287
vlan.DropEligible = pkt[2]&0x10 != 0
255288
vlan.VlanIdentifier = int(binary.BigEndian.Uint16(pkt[:2])) & 0x0FFF
256289
vlan.Type = int(binary.BigEndian.Uint16(p.Payload[2:4]))
257290
p.Headers = append(p.Headers, vlan)
258-
p.Payload = p.Payload[4:]
291+
292+
if len(pkt) >= 5 {
293+
p.Payload = p.Payload[4:]
294+
}
295+
259296
switch vlan.Type {
260297
case TYPE_IP:
261298
p.decodeIp()
@@ -292,6 +329,10 @@ const (
292329
)
293330

294331
func (p *Packet) decodeTcp() {
332+
if len(p.Payload) < 20 {
333+
return
334+
}
335+
295336
pkt := p.Payload
296337
tcp := new(Tcphdr)
297338
tcp.SrcPort = binary.BigEndian.Uint16(pkt[0:2])
@@ -303,7 +344,9 @@ func (p *Packet) decodeTcp() {
303344
tcp.Window = binary.BigEndian.Uint16(pkt[14:16])
304345
tcp.Checksum = binary.BigEndian.Uint16(pkt[16:18])
305346
tcp.Urgent = binary.BigEndian.Uint16(pkt[18:20])
306-
p.Payload = pkt[tcp.DataOffset*4:]
347+
if len(pkt) >= int(tcp.DataOffset*4) {
348+
p.Payload = pkt[tcp.DataOffset*4:]
349+
}
307350
p.Headers = append(p.Headers, tcp)
308351
p.TCP = tcp
309352
}
@@ -354,6 +397,10 @@ type Udphdr struct {
354397
}
355398

356399
func (p *Packet) decodeUdp() {
400+
if len(p.Payload) < 8 {
401+
return
402+
}
403+
357404
pkt := p.Payload
358405
udp := new(Udphdr)
359406
udp.SrcPort = binary.BigEndian.Uint16(pkt[0:2])
@@ -362,7 +409,9 @@ func (p *Packet) decodeUdp() {
362409
udp.Checksum = binary.BigEndian.Uint16(pkt[6:8])
363410
p.Headers = append(p.Headers, udp)
364411
p.UDP = udp
365-
p.Payload = pkt[8:]
412+
if len(p.Payload) >= 8 {
413+
p.Payload = pkt[8:]
414+
}
366415
}
367416

368417
func (udp *Udphdr) String(hdr addrHdr) string {
@@ -381,6 +430,10 @@ type Icmphdr struct {
381430
}
382431

383432
func (p *Packet) decodeIcmp() *Icmphdr {
433+
if len(p.Payload) < 8 {
434+
return nil
435+
}
436+
384437
pkt := p.Payload
385438
icmp := new(Icmphdr)
386439
icmp.Type = pkt[0]
@@ -436,6 +489,10 @@ type Ip6hdr struct {
436489
}
437490

438491
func (p *Packet) decodeIp6() {
492+
if len(p.Payload) < 40 {
493+
return
494+
}
495+
439496
pkt := p.Payload
440497
ip6 := new(Ip6hdr)
441498
ip6.Version = uint8(pkt[0]) >> 4
@@ -446,7 +503,11 @@ func (p *Packet) decodeIp6() {
446503
ip6.HopLimit = pkt[7]
447504
ip6.SrcIp = pkt[8:24]
448505
ip6.DestIp = pkt[24:40]
449-
p.Payload = pkt[40:]
506+
507+
if len(p.Payload) >= 40 {
508+
p.Payload = pkt[40:]
509+
}
510+
450511
p.Headers = append(p.Headers, ip6)
451512

452513
switch ip6.NextHeader {

decode_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package pcap
33
import (
44
"bytes"
55
"testing"
6+
"time"
67
)
78

89
var testSimpleTcpPacket *Packet = &Packet{
@@ -192,3 +193,55 @@ func TestDecodeVlanPacket(t *testing.T) {
192193
t.Errorf("Third header isn't TCP: %q", p.Headers[2])
193194
}
194195
}
196+
197+
func TestDecodeFuzzFallout(t *testing.T) {
198+
testData := []struct {
199+
Data []byte
200+
}{
201+
{[]byte("000000000000\x81\x000")},
202+
{[]byte("000000000000\x81\x00000")},
203+
{[]byte("000000000000\x86\xdd0")},
204+
{[]byte("000000000000\b\x000")},
205+
{[]byte("000000000000\b\x060")},
206+
{[]byte{}},
207+
{[]byte("000000000000\b\x0600000000")},
208+
{[]byte("000000000000\x86\xdd000000\x01000000000000000000000000000000000")},
209+
{[]byte("000000000000\x81\x0000\b\x0600000000")},
210+
{[]byte("000000000000\b\x00n0000000000000000000")},
211+
{[]byte("000000000000\x86\xdd000000\x0100000000000000000000000000000000000")},
212+
{[]byte("000000000000\x81\x0000\b\x00g0000000000000000000")},
213+
//{[]byte()},
214+
{[]byte("000000000000\b\x00400000000\x110000000000")},
215+
{[]byte("0nMء\xfe\x13\x13\x81\x00gr\b\x00&x\xc9\xe5b'\x1e0\x00\x04\x00\x0020596224")},
216+
{[]byte("000000000000\x81\x0000\b\x00400000000\x110000000000")},
217+
{[]byte("000000000000\b\x00000000000\x0600\xff0000000")},
218+
{[]byte("000000000000\x86\xdd000000\x06000000000000000000000000000000000")},
219+
{[]byte("000000000000\x81\x0000\b\x00000000000\x0600b0000000")},
220+
{[]byte("000000000000\x81\x0000\b\x00400000000\x060000000000")},
221+
{[]byte("000000000000\x86\xdd000000\x11000000000000000000000000000000000")},
222+
{[]byte("000000000000\x86\xdd000000\x0600000000000000000000000000000000000000000000M")},
223+
{[]byte("000000000000\b\x00500000000\x0600000000000")},
224+
{[]byte("0nM\xd80\xfe\x13\x13\x81\x00gr\b\x00&x\xc9\xe5b'\x1e0\x00\x04\x00\x0020596224")},
225+
}
226+
227+
for _, entry := range testData {
228+
pkt := &Packet{
229+
Time: time.Now(),
230+
Caplen: uint32(len(entry.Data)),
231+
Len: uint32(len(entry.Data)),
232+
Data: entry.Data,
233+
}
234+
235+
pkt.Decode()
236+
/*
237+
func() {
238+
defer func() {
239+
if err := recover(); err != nil {
240+
t.Fatalf("%d. %q failed: %v", idx, string(entry.Data), err)
241+
}
242+
}()
243+
pkt.Decode()
244+
}()
245+
*/
246+
}
247+
}

0 commit comments

Comments
 (0)