Skip to content

Commit be1bea8

Browse files
committed
ipv4: fix potential misaligned memory access
Also makes use of encoding/binary package. Change-Id: Id41ea874487f88a3de9fa28b613a77eb66643cc8 Reviewed-on: https://go-review.googlesource.com/19534 Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent a896e56 commit be1bea8

File tree

2 files changed

+32
-23
lines changed

2 files changed

+32
-23
lines changed

ipv4/header.go

+15-23
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
package ipv4
66

77
import (
8+
"encoding/binary"
89
"fmt"
910
"net"
1011
"runtime"
1112
"syscall"
12-
"unsafe"
1313
)
1414

1515
const (
@@ -64,17 +64,16 @@ func (h *Header) Marshal() ([]byte, error) {
6464
flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13)
6565
switch runtime.GOOS {
6666
case "darwin", "dragonfly", "freebsd", "netbsd":
67-
// TODO(mikio): fix potential misaligned memory access
68-
*(*uint16)(unsafe.Pointer(&b[2:3][0])) = uint16(h.TotalLen)
69-
*(*uint16)(unsafe.Pointer(&b[6:7][0])) = uint16(flagsAndFragOff)
67+
nativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
68+
nativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
7069
default:
71-
b[2], b[3] = byte(h.TotalLen>>8), byte(h.TotalLen)
72-
b[6], b[7] = byte(flagsAndFragOff>>8), byte(flagsAndFragOff)
70+
binary.BigEndian.PutUint16(b[2:4], uint16(h.TotalLen))
71+
binary.BigEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
7372
}
74-
b[4], b[5] = byte(h.ID>>8), byte(h.ID)
73+
binary.BigEndian.PutUint16(b[4:6], uint16(h.ID))
7574
b[8] = byte(h.TTL)
7675
b[9] = byte(h.Protocol)
77-
b[10], b[11] = byte(h.Checksum>>8), byte(h.Checksum)
76+
binary.BigEndian.PutUint16(b[10:12], uint16(h.Checksum))
7877
if ip := h.Src.To4(); ip != nil {
7978
copy(b[12:16], ip[:net.IPv4len])
8079
}
@@ -89,9 +88,6 @@ func (h *Header) Marshal() ([]byte, error) {
8988
return b, nil
9089
}
9190

92-
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
93-
var freebsdVersion uint32
94-
9591
// ParseHeader parses b as an IPv4 header.
9692
func ParseHeader(b []byte) (*Header, error) {
9793
if len(b) < HeaderLen {
@@ -105,30 +101,26 @@ func ParseHeader(b []byte) (*Header, error) {
105101
Version: int(b[0] >> 4),
106102
Len: hdrlen,
107103
TOS: int(b[1]),
108-
ID: int(b[4])<<8 | int(b[5]),
104+
ID: int(binary.BigEndian.Uint16(b[4:6])),
109105
TTL: int(b[8]),
110106
Protocol: int(b[9]),
111-
Checksum: int(b[10])<<8 | int(b[11]),
107+
Checksum: int(binary.BigEndian.Uint16(b[10:12])),
112108
Src: net.IPv4(b[12], b[13], b[14], b[15]),
113109
Dst: net.IPv4(b[16], b[17], b[18], b[19]),
114110
}
115111
switch runtime.GOOS {
116112
case "darwin", "dragonfly", "netbsd":
117-
// TODO(mikio): fix potential misaligned memory access
118-
h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0]))) + hdrlen
119-
// TODO(mikio): fix potential misaligned memory access
120-
h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[6:7][0])))
113+
h.TotalLen = int(nativeEndian.Uint16(b[2:4])) + hdrlen
114+
h.FragOff = int(nativeEndian.Uint16(b[6:8]))
121115
case "freebsd":
122-
// TODO(mikio): fix potential misaligned memory access
123-
h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0])))
116+
h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
124117
if freebsdVersion < 1000000 {
125118
h.TotalLen += hdrlen
126119
}
127-
// TODO(mikio): fix potential misaligned memory access
128-
h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[6:7][0])))
120+
h.FragOff = int(nativeEndian.Uint16(b[6:8]))
129121
default:
130-
h.TotalLen = int(b[2])<<8 | int(b[3])
131-
h.FragOff = int(b[6])<<8 | int(b[7])
122+
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
123+
h.FragOff = int(binary.BigEndian.Uint16(b[6:8]))
132124
}
133125
h.Flags = HeaderFlags(h.FragOff&0xe000) >> 13
134126
h.FragOff = h.FragOff & 0x1fff

ipv4/helper.go

+17
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
package ipv4
66

77
import (
8+
"encoding/binary"
89
"errors"
910
"net"
11+
"unsafe"
1012
)
1113

1214
var (
@@ -18,8 +20,23 @@ var (
1820
errOpNoSupport = errors.New("operation not supported")
1921
errNoSuchInterface = errors.New("no such interface")
2022
errNoSuchMulticastInterface = errors.New("no such multicast interface")
23+
24+
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
25+
freebsdVersion uint32
26+
27+
nativeEndian binary.ByteOrder
2128
)
2229

30+
func init() {
31+
i := uint32(1)
32+
b := (*[4]byte)(unsafe.Pointer(&i))
33+
if b[0] == 1 {
34+
nativeEndian = binary.LittleEndian
35+
} else {
36+
nativeEndian = binary.BigEndian
37+
}
38+
}
39+
2340
func boolint(b bool) int {
2441
if b {
2542
return 1

0 commit comments

Comments
 (0)