| // Copyright 2016 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. |
| |
| package net |
| |
| // parsePort parses service as a decimal integer and returns the |
| // corresponding value as port. It is the caller's responsibility to |
| // parse service as a non-decimal integer when needsLookup is true. |
| // |
| // Some system resolvers will return a valid port number when given a number |
| // over 65536 (see https://golang.org/issues/11715). Alas, the parser |
| // can't bail early on numbers > 65536. Therefore reasonably large/small |
| // numbers are parsed in full and rejected if invalid. |
| func parsePort(service string) (port int, needsLookup bool) { |
| if service == "" { |
| // Lock in the legacy behavior that an empty string |
| // means port 0. See golang.org/issue/13610. |
| return 0, false |
| } |
| const ( |
| max = uint32(1<<32 - 1) |
| cutoff = uint32(1 << 30) |
| ) |
| neg := false |
| if service[0] == '+' { |
| service = service[1:] |
| } else if service[0] == '-' { |
| neg = true |
| service = service[1:] |
| } |
| var n uint32 |
| for _, d := range service { |
| if '0' <= d && d <= '9' { |
| d -= '0' |
| } else { |
| return 0, true |
| } |
| if n >= cutoff { |
| n = max |
| break |
| } |
| n *= 10 |
| nn := n + uint32(d) |
| if nn < n || nn > max { |
| n = max |
| break |
| } |
| n = nn |
| } |
| if !neg && n >= cutoff { |
| port = int(cutoff - 1) |
| } else if neg && n > cutoff { |
| port = int(cutoff) |
| } else { |
| port = int(n) |
| } |
| if neg { |
| port = -port |
| } |
| return port, false |
| } |