From 3b5be4522a21df8ce52a06a0c4ba005c89a8590f Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Sun, 18 Jan 2015 16:28:15 +0900 Subject: [PATCH] net: more accurate parsing of IPv4 header on IPConn As shown in #9395, inaccurate implementation would be a cause of parsing IPv4 header twice and corrupted upper-layer message issues. Change-Id: Ia1a042e7ca58ee4fcb38fe9ec753c2ab100592ca Reviewed-on: https://go-review.googlesource.com/3001 Reviewed-by: Ian Lance Taylor --- src/net/iprawsock_posix.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/net/iprawsock_posix.go b/src/net/iprawsock_posix.go index 99b081ba8c..e11eacec6a 100644 --- a/src/net/iprawsock_posix.go +++ b/src/net/iprawsock_posix.go @@ -83,17 +83,28 @@ func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) { switch sa := sa.(type) { case *syscall.SockaddrInet4: addr = &IPAddr{IP: sa.Addr[0:]} - if len(b) >= IPv4len { // discard ipv4 header - hsize := (int(b[0]) & 0xf) * 4 - copy(b, b[hsize:]) - n -= hsize - } + n = stripIPv4Header(n, b) case *syscall.SockaddrInet6: addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))} } return n, addr, err } +func stripIPv4Header(n int, b []byte) int { + if len(b) < 20 { + return n + } + l := int(b[0]&0x0f) << 2 + if 20 > l || l > len(b) { + return n + } + if b[0]>>4 != 4 { + return n + } + copy(b, b[l:]) + return n - l +} + // ReadFrom implements the PacketConn ReadFrom method. func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) { if !c.ok() { -- 2.50.0