Skip to content

Commit e8bbbe0

Browse files
committed
net: ensure that ResolveTCPAddr(addr.String()) reproduces addr
And same for UDP. Fixes #6465. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/13740048
1 parent 2be6236 commit e8bbbe0

File tree

9 files changed

+65
-68
lines changed

9 files changed

+65
-68
lines changed

src/pkg/net/cgo_unix.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
155155
}
156156

157157
func copyIP(x IP) IP {
158+
if len(x) < 16 {
159+
return x.To16()
160+
}
158161
y := make(IP, len(x))
159162
copy(y, x)
160163
return y

src/pkg/net/ip.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,15 @@ func (ip IP) String() string {
312312
return s
313313
}
314314

315+
// ipEmptyString is like ip.String except that it returns
316+
// an empty string when ip is unset.
317+
func ipEmptyString(ip IP) string {
318+
if len(ip) == 0 {
319+
return ""
320+
}
321+
return ip.String()
322+
}
323+
315324
// MarshalText implements the encoding.TextMarshaler interface.
316325
// The encoding is the same as returned by String.
317326
func (ip IP) MarshalText() ([]byte, error) {

src/pkg/net/ipraw_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ func init() {
5252
}
5353
if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
5454
resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
55-
{"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1).To4()}, nil},
56-
{"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1).To4()}, nil},
55+
{"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
56+
{"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
5757
{"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil},
5858
}...)
5959
}

src/pkg/net/ipsock.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,11 @@ func firstSupportedAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr)
116116
}
117117

118118
// ipv4only returns IPv4 addresses that we can use with the kernel's
119-
// IPv4 addressing modes. It returns IPv4-mapped IPv6 addresses as
120-
// IPv4 addresses and returns other IPv6 address types as nils.
119+
// IPv4 addressing modes. If ip is an IPv4 address, ipv4only returns ip.
120+
// Otherwise it returns nil.
121121
func ipv4only(ip IP) IP {
122-
if supportsIPv4 {
123-
return ip.To4()
122+
if supportsIPv4 && ip.To4() != nil {
123+
return ip
124124
}
125125
return nil
126126
}

src/pkg/net/ipsock_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ var firstFavoriteAddrTests = []struct {
2626
},
2727
testInetaddr,
2828
addrList{
29-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
29+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
3030
&TCPAddr{IP: IPv6loopback, Port: 5682},
3131
},
3232
nil,
@@ -39,7 +39,7 @@ var firstFavoriteAddrTests = []struct {
3939
},
4040
testInetaddr,
4141
addrList{
42-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
42+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
4343
&TCPAddr{IP: IPv6loopback, Port: 5682},
4444
},
4545
nil,
@@ -51,7 +51,7 @@ var firstFavoriteAddrTests = []struct {
5151
IPv4(192, 168, 0, 1),
5252
},
5353
testInetaddr,
54-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
54+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
5555
nil,
5656
},
5757
{
@@ -74,7 +74,7 @@ var firstFavoriteAddrTests = []struct {
7474
},
7575
testInetaddr,
7676
addrList{
77-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
77+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
7878
&TCPAddr{IP: IPv6loopback, Port: 5682},
7979
},
8080
nil,
@@ -89,7 +89,7 @@ var firstFavoriteAddrTests = []struct {
8989
},
9090
testInetaddr,
9191
addrList{
92-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
92+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
9393
&TCPAddr{IP: IPv6loopback, Port: 5682},
9494
},
9595
nil,
@@ -104,7 +104,7 @@ var firstFavoriteAddrTests = []struct {
104104
},
105105
testInetaddr,
106106
addrList{
107-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
107+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
108108
&TCPAddr{IP: IPv6loopback, Port: 5682},
109109
},
110110
nil,
@@ -119,7 +119,7 @@ var firstFavoriteAddrTests = []struct {
119119
},
120120
testInetaddr,
121121
addrList{
122-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
122+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
123123
&TCPAddr{IP: IPv6loopback, Port: 5682},
124124
},
125125
nil,
@@ -132,7 +132,7 @@ var firstFavoriteAddrTests = []struct {
132132
IPv6loopback,
133133
},
134134
testInetaddr,
135-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
135+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
136136
nil,
137137
},
138138
{
@@ -142,7 +142,7 @@ var firstFavoriteAddrTests = []struct {
142142
IPv4(127, 0, 0, 1),
143143
},
144144
testInetaddr,
145-
&TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5682},
145+
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
146146
nil,
147147
},
148148

src/pkg/net/tcp_test.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ var resolveTCPAddrTests = []resolveTCPAddrTest{
292292
{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
293293
{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior
294294

295+
{"tcp", ":12345", &TCPAddr{Port: 12345}, nil},
296+
295297
{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
296298
}
297299

@@ -305,8 +307,8 @@ func init() {
305307
}
306308
if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
307309
resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
308-
{"tcp", "localhost:5", &TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5}, nil},
309-
{"tcp4", "localhost:6", &TCPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 6}, nil},
310+
{"tcp", "localhost:5", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5}, nil},
311+
{"tcp4", "localhost:6", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 6}, nil},
310312
{"tcp6", "localhost:7", &TCPAddr{IP: IPv6loopback, Port: 7}, nil},
311313
}...)
312314
}
@@ -319,7 +321,17 @@ func TestResolveTCPAddr(t *testing.T) {
319321
t.Fatalf("ResolveTCPAddr(%q, %q) failed: %v", tt.net, tt.litAddrOrName, err)
320322
}
321323
if !reflect.DeepEqual(addr, tt.addr) {
322-
t.Fatalf("got %#v; expected %#v", addr, tt.addr)
324+
t.Fatalf("ResolveTCPAddr(%q, %q) = %#v, want %#v", tt.net, tt.litAddrOrName, addr, tt.addr)
325+
}
326+
if err == nil {
327+
str := addr.String()
328+
addr1, err := ResolveTCPAddr(tt.net, str)
329+
if err != nil {
330+
t.Fatalf("ResolveTCPAddr(%q, %q) [from %q]: %v", tt.net, str, tt.litAddrOrName, err)
331+
}
332+
if !reflect.DeepEqual(addr1, addr) {
333+
t.Fatalf("ResolveTCPAddr(%q, %q) [from %q] = %#v, want %#v", tt.net, str, tt.litAddrOrName, addr1, addr)
334+
}
323335
}
324336
}
325337
}

src/pkg/net/tcpsock.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ func (a *TCPAddr) String() string {
1818
if a == nil {
1919
return "<nil>"
2020
}
21+
ip := ipEmptyString(a.IP)
2122
if a.Zone != "" {
22-
return JoinHostPort(a.IP.String()+"%"+a.Zone, itoa(a.Port))
23+
return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
2324
}
24-
return JoinHostPort(a.IP.String(), itoa(a.Port))
25+
return JoinHostPort(ip, itoa(a.Port))
2526
}
2627

2728
func (a *TCPAddr) toAddr() Addr {

src/pkg/net/udp_test.go

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,60 +5,31 @@
55
package net
66

77
import (
8-
"fmt"
98
"reflect"
109
"runtime"
10+
"strings"
1111
"testing"
1212
)
1313

14-
type resolveUDPAddrTest struct {
15-
net string
16-
litAddrOrName string
17-
addr *UDPAddr
18-
err error
19-
}
20-
21-
var resolveUDPAddrTests = []resolveUDPAddrTest{
22-
{"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
23-
{"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
24-
25-
{"udp", "[::1]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1}, nil},
26-
{"udp6", "[::1]:65534", &UDPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
27-
28-
{"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
29-
{"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
30-
31-
{"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
32-
{"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior
33-
34-
{"sip", "127.0.0.1:0", nil, UnknownNetworkError("sip")},
35-
}
36-
37-
func init() {
38-
if ifi := loopbackInterface(); ifi != nil {
39-
index := fmt.Sprintf("%v", ifi.Index)
40-
resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{
41-
{"udp6", "[fe80::1%" + ifi.Name + "]:3", &UDPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
42-
{"udp6", "[fe80::1%" + index + "]:4", &UDPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
43-
}...)
44-
}
45-
if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
46-
resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{
47-
{"udp", "localhost:5", &UDPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 5}, nil},
48-
{"udp4", "localhost:6", &UDPAddr{IP: IPv4(127, 0, 0, 1).To4(), Port: 6}, nil},
49-
{"udp6", "localhost:7", &UDPAddr{IP: IPv6loopback, Port: 7}, nil},
50-
}...)
51-
}
52-
}
53-
5414
func TestResolveUDPAddr(t *testing.T) {
55-
for _, tt := range resolveUDPAddrTests {
56-
addr, err := ResolveUDPAddr(tt.net, tt.litAddrOrName)
15+
for _, tt := range resolveTCPAddrTests {
16+
net := strings.Replace(tt.net, "tcp", "udp", -1)
17+
addr, err := ResolveUDPAddr(net, tt.litAddrOrName)
5718
if err != tt.err {
58-
t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", tt.net, tt.litAddrOrName, err)
19+
t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, tt.litAddrOrName, err)
20+
}
21+
if !reflect.DeepEqual(addr, (*UDPAddr)(tt.addr)) {
22+
t.Fatalf("ResolveUDPAddr(%q, %q) = %#v, want %#v", net, tt.litAddrOrName, addr, tt.addr)
5923
}
60-
if !reflect.DeepEqual(addr, tt.addr) {
61-
t.Fatalf("got %#v; expected %#v", addr, tt.addr)
24+
if err == nil {
25+
str := addr.String()
26+
addr1, err := ResolveUDPAddr(net, str)
27+
if err != nil {
28+
t.Fatalf("ResolveUDPAddr(%q, %q) [from %q]: %v", net, str, tt.litAddrOrName, err)
29+
}
30+
if !reflect.DeepEqual(addr1, addr) {
31+
t.Fatalf("ResolveUDPAddr(%q, %q) [from %q] = %#v, want %#v", net, str, tt.litAddrOrName, addr1, addr)
32+
}
6233
}
6334
}
6435
}

src/pkg/net/udpsock.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ func (a *UDPAddr) String() string {
2222
if a == nil {
2323
return "<nil>"
2424
}
25+
ip := ipEmptyString(a.IP)
2526
if a.Zone != "" {
26-
return JoinHostPort(a.IP.String()+"%"+a.Zone, itoa(a.Port))
27+
return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
2728
}
28-
return JoinHostPort(a.IP.String(), itoa(a.Port))
29+
return JoinHostPort(ip, itoa(a.Port))
2930
}
3031

3132
func (a *UDPAddr) toAddr() Addr {

0 commit comments

Comments
 (0)