mirror of
https://github.com/golang/go
synced 2024-11-24 02:50:11 -07:00
net: make Dial, Listen{,Packet} for TCP/UDP with invalid port fail
This change makes Dial, Listen and ListenPacket with invalid port fail whatever GODEBUG=netdns is. Please be informed that cgoLookupPort with an out of range literal number may return either the lower or upper bound value, 0 or 65535, with no error on some platform. Fixes #11715. Change-Id: I43f9c4fb5526d1bf50b97698e0eb39d29fd74c35 Reviewed-on: https://go-review.googlesource.com/12447 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
3d5163cf43
commit
b50b21d3e1
@ -116,8 +116,10 @@ var dialErrorTests = []struct {
|
|||||||
{"tcp", "no-such-name:80"},
|
{"tcp", "no-such-name:80"},
|
||||||
{"tcp", "mh/astro/r70:http"},
|
{"tcp", "mh/astro/r70:http"},
|
||||||
|
|
||||||
{"tcp", "127.0.0.1:0"},
|
{"tcp", JoinHostPort("127.0.0.1", "-1")},
|
||||||
{"udp", "127.0.0.1:0"},
|
{"tcp", JoinHostPort("127.0.0.1", "123456789")},
|
||||||
|
{"udp", JoinHostPort("127.0.0.1", "-1")},
|
||||||
|
{"udp", JoinHostPort("127.0.0.1", "123456789")},
|
||||||
{"ip:icmp", "127.0.0.1"},
|
{"ip:icmp", "127.0.0.1"},
|
||||||
|
|
||||||
{"unix", "/path/to/somewhere"},
|
{"unix", "/path/to/somewhere"},
|
||||||
@ -145,10 +147,23 @@ func TestDialError(t *testing.T) {
|
|||||||
for i, tt := range dialErrorTests {
|
for i, tt := range dialErrorTests {
|
||||||
c, err := d.Dial(tt.network, tt.address)
|
c, err := d.Dial(tt.network, tt.address)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("#%d: should fail; %s:%s->%s", i, tt.network, c.LocalAddr(), c.RemoteAddr())
|
t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
|
||||||
c.Close()
|
c.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if tt.network == "tcp" || tt.network == "udp" {
|
||||||
|
nerr := err
|
||||||
|
if op, ok := nerr.(*OpError); ok {
|
||||||
|
nerr = op.Err
|
||||||
|
}
|
||||||
|
if sys, ok := nerr.(*os.SyscallError); ok {
|
||||||
|
nerr = sys.Err
|
||||||
|
}
|
||||||
|
if nerr == errOpNotSupported {
|
||||||
|
t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
if c != nil {
|
if c != nil {
|
||||||
t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
|
t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
|
||||||
}
|
}
|
||||||
@ -198,7 +213,8 @@ var listenErrorTests = []struct {
|
|||||||
{"tcp", "no-such-name:80"},
|
{"tcp", "no-such-name:80"},
|
||||||
{"tcp", "mh/astro/r70:http"},
|
{"tcp", "mh/astro/r70:http"},
|
||||||
|
|
||||||
{"tcp", "127.0.0.1:0"},
|
{"tcp", JoinHostPort("127.0.0.1", "-1")},
|
||||||
|
{"tcp", JoinHostPort("127.0.0.1", "123456789")},
|
||||||
|
|
||||||
{"unix", "/path/to/somewhere"},
|
{"unix", "/path/to/somewhere"},
|
||||||
{"unixpacket", "/path/to/somewhere"},
|
{"unixpacket", "/path/to/somewhere"},
|
||||||
@ -223,10 +239,23 @@ func TestListenError(t *testing.T) {
|
|||||||
for i, tt := range listenErrorTests {
|
for i, tt := range listenErrorTests {
|
||||||
ln, err := Listen(tt.network, tt.address)
|
ln, err := Listen(tt.network, tt.address)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("#%d: should fail; %s:%s->", i, tt.network, ln.Addr())
|
t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
|
||||||
ln.Close()
|
ln.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if tt.network == "tcp" {
|
||||||
|
nerr := err
|
||||||
|
if op, ok := nerr.(*OpError); ok {
|
||||||
|
nerr = op.Err
|
||||||
|
}
|
||||||
|
if sys, ok := nerr.(*os.SyscallError); ok {
|
||||||
|
nerr = sys.Err
|
||||||
|
}
|
||||||
|
if nerr == errOpNotSupported {
|
||||||
|
t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
if ln != nil {
|
if ln != nil {
|
||||||
t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
|
t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
|
||||||
}
|
}
|
||||||
@ -246,6 +275,9 @@ var listenPacketErrorTests = []struct {
|
|||||||
{"udp", "127.0.0.1:☺"},
|
{"udp", "127.0.0.1:☺"},
|
||||||
{"udp", "no-such-name:80"},
|
{"udp", "no-such-name:80"},
|
||||||
{"udp", "mh/astro/r70:http"},
|
{"udp", "mh/astro/r70:http"},
|
||||||
|
|
||||||
|
{"udp", JoinHostPort("127.0.0.1", "-1")},
|
||||||
|
{"udp", JoinHostPort("127.0.0.1", "123456789")},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListenPacketError(t *testing.T) {
|
func TestListenPacketError(t *testing.T) {
|
||||||
@ -263,7 +295,7 @@ func TestListenPacketError(t *testing.T) {
|
|||||||
for i, tt := range listenPacketErrorTests {
|
for i, tt := range listenPacketErrorTests {
|
||||||
c, err := ListenPacket(tt.network, tt.address)
|
c, err := ListenPacket(tt.network, tt.address)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("#%d: should fail; %s:%s->", i, tt.network, c.LocalAddr())
|
t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
|
||||||
c.Close()
|
c.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ func internetAddrList(net, addr string, deadline time.Time) (addrList, error) {
|
|||||||
if host, port, err = SplitHostPort(addr); err != nil {
|
if host, port, err = SplitHostPort(addr); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if portnum, err = parsePort(net, port); err != nil {
|
if portnum, err = LookupPort(net, port); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,10 +123,17 @@ func lookupIPDeadline(host string, deadline time.Time) (addrs []IPAddr, err erro
|
|||||||
|
|
||||||
// LookupPort looks up the port for the given network and service.
|
// LookupPort looks up the port for the given network and service.
|
||||||
func LookupPort(network, service string) (port int, err error) {
|
func LookupPort(network, service string) (port int, err error) {
|
||||||
if n, i, ok := dtoi(service, 0); ok && i == len(service) {
|
port, _, ok := dtoi(service, 0)
|
||||||
return n, nil
|
if !ok && port != big && port != -big {
|
||||||
|
port, err = lookupPort(network, service)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
}
|
}
|
||||||
return lookupPort(network, service)
|
}
|
||||||
|
if 0 > port || port > 65535 {
|
||||||
|
return 0, &AddrError{Err: "invalid port", Addr: service}
|
||||||
|
}
|
||||||
|
return port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupCNAME returns the canonical DNS host for the given name.
|
// LookupCNAME returns the canonical DNS host for the given name.
|
||||||
|
@ -118,15 +118,27 @@ const big = 0xFFFFFF
|
|||||||
// Returns number, new offset, success.
|
// Returns number, new offset, success.
|
||||||
func dtoi(s string, i0 int) (n int, i int, ok bool) {
|
func dtoi(s string, i0 int) (n int, i int, ok bool) {
|
||||||
n = 0
|
n = 0
|
||||||
|
neg := false
|
||||||
|
if len(s) > 0 && s[0] == '-' {
|
||||||
|
neg = true
|
||||||
|
s = s[1:]
|
||||||
|
}
|
||||||
for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
|
for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
|
||||||
n = n*10 + int(s[i]-'0')
|
n = n*10 + int(s[i]-'0')
|
||||||
if n >= big {
|
if n >= big {
|
||||||
return 0, i, false
|
if neg {
|
||||||
|
return -big, i + 1, false
|
||||||
|
}
|
||||||
|
return big, i, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i == i0 {
|
if i == i0 {
|
||||||
return 0, i, false
|
return 0, i, false
|
||||||
}
|
}
|
||||||
|
if neg {
|
||||||
|
n = -n
|
||||||
|
i++
|
||||||
|
}
|
||||||
return n, i, true
|
return n, i, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,3 +77,25 @@ func TestGoDebugString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDtoi(t *testing.T) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
in string
|
||||||
|
out int
|
||||||
|
off int
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{"", 0, 0, false},
|
||||||
|
|
||||||
|
{"-123456789", -big, 9, false},
|
||||||
|
{"-1", -1, 2, true},
|
||||||
|
{"0", 0, 1, true},
|
||||||
|
{"65536", 65536, 5, true},
|
||||||
|
{"123456789", big, 8, false},
|
||||||
|
} {
|
||||||
|
n, i, ok := dtoi(tt.in, 0)
|
||||||
|
if n != tt.out || i != tt.off || ok != tt.ok {
|
||||||
|
t.Errorf("got %d, %d, %v; want %d, %d, %v", n, i, ok, tt.out, tt.off, tt.ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Network service port manipulations
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
// parsePort parses port as a network service port number for both
|
|
||||||
// TCP and UDP.
|
|
||||||
func parsePort(net, port string) (int, error) {
|
|
||||||
p, i, ok := dtoi(port, 0)
|
|
||||||
if !ok || i != len(port) {
|
|
||||||
var err error
|
|
||||||
p, err = LookupPort(net, port)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if p < 0 || p > 0xFFFF {
|
|
||||||
return 0, &AddrError{Err: "invalid port", Addr: port}
|
|
||||||
}
|
|
||||||
return p, nil
|
|
||||||
}
|
|
@ -9,12 +9,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var portTests = []struct {
|
var lookupPortTests = []struct {
|
||||||
network string
|
network string
|
||||||
name string
|
name string
|
||||||
port int
|
port int
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
|
{"tcp", "0", 0, true},
|
||||||
{"tcp", "echo", 7, true},
|
{"tcp", "echo", 7, true},
|
||||||
{"tcp", "discard", 9, true},
|
{"tcp", "discard", 9, true},
|
||||||
{"tcp", "systat", 11, true},
|
{"tcp", "systat", 11, true},
|
||||||
@ -29,6 +30,7 @@ var portTests = []struct {
|
|||||||
{"tcp", "finger", 79, true},
|
{"tcp", "finger", 79, true},
|
||||||
{"tcp", "42", 42, true},
|
{"tcp", "42", 42, true},
|
||||||
|
|
||||||
|
{"udp", "0", 0, true},
|
||||||
{"udp", "echo", 7, true},
|
{"udp", "echo", 7, true},
|
||||||
{"udp", "tftp", 69, true},
|
{"udp", "tftp", 69, true},
|
||||||
{"udp", "bootpc", 68, true},
|
{"udp", "bootpc", 68, true},
|
||||||
@ -41,6 +43,10 @@ var portTests = []struct {
|
|||||||
|
|
||||||
{"--badnet--", "zzz", 0, false},
|
{"--badnet--", "zzz", 0, false},
|
||||||
{"tcp", "--badport--", 0, false},
|
{"tcp", "--badport--", 0, false},
|
||||||
|
{"tcp", "-1", 0, false},
|
||||||
|
{"tcp", "65536", 0, false},
|
||||||
|
{"udp", "-1", 0, false},
|
||||||
|
{"udp", "65536", 0, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupPort(t *testing.T) {
|
func TestLookupPort(t *testing.T) {
|
||||||
@ -49,9 +55,9 @@ func TestLookupPort(t *testing.T) {
|
|||||||
t.Skipf("not supported on %s", runtime.GOOS)
|
t.Skipf("not supported on %s", runtime.GOOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range portTests {
|
for _, tt := range lookupPortTests {
|
||||||
if port, err := LookupPort(tt.network, tt.name); port != tt.port || (err == nil) != tt.ok {
|
if port, err := LookupPort(tt.network, tt.name); port != tt.port || (err == nil) != tt.ok {
|
||||||
t.Errorf("LookupPort(%q, %q) = %v, %v; want %v", tt.network, tt.name, port, err, tt.port)
|
t.Errorf("LookupPort(%q, %q) = %d, %v; want %d", tt.network, tt.name, port, err, tt.port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user