1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package net
6
7// parsePort parses service as a decimal integer and returns the
8// corresponding value as port. It is the caller's responsibility to
9// parse service as a non-decimal integer when needsLookup is true.
10//
11// Some system resolvers will return a valid port number when given a number
12// over 65536 (see https://golang.org/issues/11715). Alas, the parser
13// can't bail early on numbers > 65536. Therefore reasonably large/small
14// numbers are parsed in full and rejected if invalid.
15func parsePort(service string) (port int, needsLookup bool) {
16	if service == "" {
17		// Lock in the legacy behavior that an empty string
18		// means port 0. See golang.org/issue/13610.
19		return 0, false
20	}
21	const (
22		max    = uint32(1<<32 - 1)
23		cutoff = uint32(1 << 30)
24	)
25	neg := false
26	if service[0] == '+' {
27		service = service[1:]
28	} else if service[0] == '-' {
29		neg = true
30		service = service[1:]
31	}
32	var n uint32
33	for _, d := range service {
34		if '0' <= d && d <= '9' {
35			d -= '0'
36		} else {
37			return 0, true
38		}
39		if n >= cutoff {
40			n = max
41			break
42		}
43		n *= 10
44		nn := n + uint32(d)
45		if nn < n || nn > max {
46			n = max
47			break
48		}
49		n = nn
50	}
51	if !neg && n >= cutoff {
52		port = int(cutoff - 1)
53	} else if neg && n > cutoff {
54		port = int(cutoff)
55	} else {
56		port = int(n)
57	}
58	if neg {
59		port = -port
60	}
61	return port, false
62}
63