]> Cypherpunks repositories - gostls13.git/commitdiff
net: make Dial, Listen{,Packet} for TCP/UDP with invalid port fail
authorMikio Hara <mikioh.mikioh@gmail.com>
Tue, 21 Jul 2015 03:51:01 +0000 (12:51 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Sun, 1 Nov 2015 05:28:17 +0000 (05:28 +0000)
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>
src/net/error_test.go
src/net/ipsock.go
src/net/lookup.go
src/net/parse.go
src/net/parse_test.go
src/net/port.go [deleted file]
src/net/port_test.go

index bf95ff6108cb1904e72b185890b3954b622d07c6..6e85362938860bd34dfe19b8a77ffa901f8bbfbd 100644 (file)
@@ -116,8 +116,10 @@ var dialErrorTests = []struct {
        {"tcp", "no-such-name:80"},
        {"tcp", "mh/astro/r70:http"},
 
-       {"tcp", "127.0.0.1:0"},
-       {"udp", "127.0.0.1:0"},
+       {"tcp", JoinHostPort("127.0.0.1", "-1")},
+       {"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"},
 
        {"unix", "/path/to/somewhere"},
@@ -145,10 +147,23 @@ func TestDialError(t *testing.T) {
        for i, tt := range dialErrorTests {
                c, err := d.Dial(tt.network, tt.address)
                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()
                        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 {
                        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", "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"},
        {"unixpacket", "/path/to/somewhere"},
@@ -223,10 +239,23 @@ func TestListenError(t *testing.T) {
        for i, tt := range listenErrorTests {
                ln, err := Listen(tt.network, tt.address)
                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()
                        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 {
                        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", "no-such-name:80"},
        {"udp", "mh/astro/r70:http"},
+
+       {"udp", JoinHostPort("127.0.0.1", "-1")},
+       {"udp", JoinHostPort("127.0.0.1", "123456789")},
 }
 
 func TestListenPacketError(t *testing.T) {
@@ -263,7 +295,7 @@ func TestListenPacketError(t *testing.T) {
        for i, tt := range listenPacketErrorTests {
                c, err := ListenPacket(tt.network, tt.address)
                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()
                        continue
                }
index 6e75c33d53471e91fa276736a91420bab316497e..55f697f622ed6d355a3a3d899510fb474a438c94 100644 (file)
@@ -213,7 +213,7 @@ func internetAddrList(net, addr string, deadline time.Time) (addrList, error) {
                        if host, port, err = SplitHostPort(addr); err != nil {
                                return nil, err
                        }
-                       if portnum, err = parsePort(net, port); err != nil {
+                       if portnum, err = LookupPort(net, port); err != nil {
                                return nil, err
                        }
                }
index 9008322dc5a76fd9a401e6e08fb181b8a9d4a99a..6e0cf62aec12cd813ad6ddbe65321691c4290219 100644 (file)
@@ -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.
 func LookupPort(network, service string) (port int, err error) {
-       if n, i, ok := dtoi(service, 0); ok && i == len(service) {
-               return n, nil
+       port, _, ok := dtoi(service, 0)
+       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.
index 2c686f5a9fb8738f64cc4aab5220eba1eadee552..93cdf8d73f9b8ebc7f8c073e944be1f788e8f305 100644 (file)
@@ -118,15 +118,27 @@ const big = 0xFFFFFF
 // Returns number, new offset, success.
 func dtoi(s string, i0 int) (n int, i int, ok bool) {
        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++ {
                n = n*10 + int(s[i]-'0')
                if n >= big {
-                       return 0, i, false
+                       if neg {
+                               return -big, i + 1, false
+                       }
+                       return big, i, false
                }
        }
        if i == i0 {
                return 0, i, false
        }
+       if neg {
+               n = -n
+               i++
+       }
        return n, i, true
 }
 
index 0f048fcea0bbb0cb78eeb30f926565a01cc54abf..fec92009465516712c0a6302775a6579195d446c 100644 (file)
@@ -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)
+               }
+       }
+}
diff --git a/src/net/port.go b/src/net/port.go
deleted file mode 100644 (file)
index a2a5387..0000000
+++ /dev/null
@@ -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
-}
index 258a5bda48f263fbf8b27c3747e0826420a6b261..362e6af9330fcfee8bc3434321f6e6486c46fe81 100644 (file)
@@ -9,12 +9,13 @@ import (
        "testing"
 )
 
-var portTests = []struct {
+var lookupPortTests = []struct {
        network string
        name    string
        port    int
        ok      bool
 }{
+       {"tcp", "0", 0, true},
        {"tcp", "echo", 7, true},
        {"tcp", "discard", 9, true},
        {"tcp", "systat", 11, true},
@@ -29,6 +30,7 @@ var portTests = []struct {
        {"tcp", "finger", 79, true},
        {"tcp", "42", 42, true},
 
+       {"udp", "0", 0, true},
        {"udp", "echo", 7, true},
        {"udp", "tftp", 69, true},
        {"udp", "bootpc", 68, true},
@@ -41,6 +43,10 @@ var portTests = []struct {
 
        {"--badnet--", "zzz", 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) {
@@ -49,9 +55,9 @@ func TestLookupPort(t *testing.T) {
                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 {
-                       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)
                }
        }
 }