net: remove dependency on math/rand

Like we did for sync, let the runtime give net random numbers,
to avoid forcing an import of math/rand for DNS.

Change-Id: Iab3e64121d687d288a3961a8ccbcebe589047253
Reviewed-on: https://go-review.googlesource.com/c/go/+/241258
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Russ Cox 2020-07-07 09:07:16 -04:00
parent 349a287646
commit 39b5276914
5 changed files with 23 additions and 12 deletions

View File

@ -318,7 +318,6 @@ var depsRules = `
# so large dependencies must be kept out. # so large dependencies must be kept out.
# This is a long-looking list but most of these # This is a long-looking list but most of these
# are small with few dependencies. # are small with few dependencies.
# math/rand should probably be removed at some point.
CGO, CGO,
golang.org/x/net/dns/dnsmessage, golang.org/x/net/dns/dnsmessage,
golang.org/x/net/lif, golang.org/x/net/lif,
@ -327,11 +326,11 @@ var depsRules = `
internal/poll, internal/poll,
internal/singleflight, internal/singleflight,
internal/race, internal/race,
math/rand,
os os
< net; < net;
fmt, unicode !< net; fmt, unicode !< net;
math/rand !< net; # net uses runtime instead
# NET is net plus net-helper packages. # NET is net plus net-helper packages.
FMT, net FMT, net
@ -479,7 +478,7 @@ var depsRules = `
CGO, OS, fmt CGO, OS, fmt
< os/signal/internal/pty; < os/signal/internal/pty;
NET, testing NET, testing, math/rand
< golang.org/x/net/nettest; < golang.org/x/net/nettest;
FMT, container/heap, math/rand FMT, container/heap, math/rand

View File

@ -5,12 +5,25 @@
package net package net
import ( import (
"math/rand"
"sort" "sort"
"golang.org/x/net/dns/dnsmessage" "golang.org/x/net/dns/dnsmessage"
) )
// provided by runtime
func fastrand() uint32
func randInt() int {
x, y := fastrand(), fastrand() // 32-bit halves
u := uint(x)<<31 ^ uint(int32(y)) // full uint, even on 64-bit systems; avoid 32-bit shift on 32-bit systems
i := int(u >> 1) // clear sign bit, even on 32-bit systems
return i
}
func randIntn(n int) int {
return randInt() % n
}
// reverseaddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP // reverseaddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address addr suitable for rDNS (PTR) record lookup or an error if it fails // address addr suitable for rDNS (PTR) record lookup or an error if it fails
// to parse the IP address. // to parse the IP address.
@ -162,7 +175,7 @@ func (addrs byPriorityWeight) shuffleByWeight() {
} }
for sum > 0 && len(addrs) > 1 { for sum > 0 && len(addrs) > 1 {
s := 0 s := 0
n := rand.Intn(sum) n := randIntn(sum)
for i := range addrs { for i := range addrs {
s += int(addrs[i].Weight) s += int(addrs[i].Weight)
if s > n { if s > n {
@ -206,7 +219,7 @@ func (s byPref) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// sort reorders MX records as specified in RFC 5321. // sort reorders MX records as specified in RFC 5321.
func (s byPref) sort() { func (s byPref) sort() {
for i := range s { for i := range s {
j := rand.Intn(i + 1) j := randIntn(i + 1)
s[i], s[j] = s[j], s[i] s[i], s[j] = s[j], s[i]
} }
sort.Sort(s) sort.Sort(s)

View File

@ -5,7 +5,6 @@
package net package net
import ( import (
"math/rand"
"testing" "testing"
) )
@ -17,7 +16,7 @@ func checkDistribution(t *testing.T, data []*SRV, margin float64) {
results := make(map[string]int) results := make(map[string]int)
count := 1000 count := 10000
for j := 0; j < count; j++ { for j := 0; j < count; j++ {
d := make([]*SRV, len(data)) d := make([]*SRV, len(data))
copy(d, data) copy(d, data)
@ -39,7 +38,6 @@ func checkDistribution(t *testing.T, data []*SRV, margin float64) {
} }
func testUniformity(t *testing.T, size int, margin float64) { func testUniformity(t *testing.T, size int, margin float64) {
rand.Seed(1)
data := make([]*SRV, size) data := make([]*SRV, size)
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
data[i] = &SRV{Target: string('a' + rune(i)), Weight: 1} data[i] = &SRV{Target: string('a' + rune(i)), Weight: 1}
@ -55,7 +53,6 @@ func TestDNSSRVUniformity(t *testing.T) {
} }
func testWeighting(t *testing.T, margin float64) { func testWeighting(t *testing.T, margin float64) {
rand.Seed(1)
data := []*SRV{ data := []*SRV{
{Target: "a", Weight: 60}, {Target: "a", Weight: 60},
{Target: "b", Weight: 30}, {Target: "b", Weight: 30},

View File

@ -18,7 +18,6 @@ import (
"context" "context"
"errors" "errors"
"io" "io"
"math/rand"
"os" "os"
"sync" "sync"
"time" "time"
@ -47,7 +46,7 @@ var (
) )
func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err error) { func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err error) {
id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano()) id = uint16(randInt())
b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true}) b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true})
b.EnableCompression() b.EnableCompression()
if err := b.StartQuestions(); err != nil { if err := b.StartQuestions(); err != nil {

View File

@ -130,6 +130,9 @@ func fastrandn(n uint32) uint32 {
//go:linkname sync_fastrand sync.fastrand //go:linkname sync_fastrand sync.fastrand
func sync_fastrand() uint32 { return fastrand() } func sync_fastrand() uint32 { return fastrand() }
//go:linkname net_fastrand net.fastrand
func net_fastrand() uint32 { return fastrand() }
// in internal/bytealg/equal_*.s // in internal/bytealg/equal_*.s
//go:noescape //go:noescape
func memequal(a, b unsafe.Pointer, size uintptr) bool func memequal(a, b unsafe.Pointer, size uintptr) bool