Home | History | Annotate | Download | only in net
      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 
      5 package 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.
     15 func 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