port.mx raw

   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 []byte) (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