diff --git a/main.go b/main.go index db67f8c7..88aa711e 100644 --- a/main.go +++ b/main.go @@ -1,16 +1,13 @@ package main import ( - "math/rand" "runtime" - "time" "github.com/navidrome/navidrome/cmd" _ "github.com/navidrome/navidrome/model/criteria" ) func main() { - rand.Seed(time.Now().UTC().UnixNano()) runtime.MemProfileRate = 0 cmd.Execute() } diff --git a/server/backgrounds/handler.go b/server/backgrounds/handler.go index 592c39f3..a8f8d6ad 100644 --- a/server/backgrounds/handler.go +++ b/server/backgrounds/handler.go @@ -2,9 +2,11 @@ package backgrounds import ( "context" + "crypto/rand" "encoding/base64" + "errors" "io" - "math/rand" + "math/big" "net/http" "net/url" "path" @@ -48,7 +50,11 @@ func (h *Handler) getRandomImage(ctx context.Context) (string, error) { if err != nil { return "", err } - return list[rand.Intn(len(list))], nil + if len(list) == 0 { + return "", errors.New("no images available") + } + rnd, _ := rand.Int(rand.Reader, big.NewInt(int64(len(list)))) + return list[rnd.Int64()], nil } func (h *Handler) getImageList(ctx context.Context) ([]string, error) { diff --git a/utils/weighted_random_chooser.go b/utils/weighted_random_chooser.go index 78f17440..7f82d0fb 100644 --- a/utils/weighted_random_chooser.go +++ b/utils/weighted_random_chooser.go @@ -1,24 +1,19 @@ package utils import ( + "crypto/rand" "errors" - "math/rand" - "time" + "math/big" ) type WeightedChooser struct { entries []interface{} weights []int totalWeight int - rng *rand.Rand } func NewWeightedRandomChooser() *WeightedChooser { - src := rand.NewSource(time.Now().UTC().UnixNano()) - - return &WeightedChooser{ - rng: rand.New(src), // nolint:gosec - } + return &WeightedChooser{} } func (w *WeightedChooser) Put(value interface{}, weight int) { @@ -43,9 +38,14 @@ func (w *WeightedChooser) GetAndRemove() (interface{}, error) { // Based on https://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/ func (w *WeightedChooser) weightedChoice() (int, error) { - rnd := w.rng.Intn(w.totalWeight) + if w.totalWeight == 0 { + return 0, errors.New("no choices available") + } + rndBig, _ := rand.Int(rand.Reader, big.NewInt(int64(w.totalWeight))) + + rnd := rndBig.Int64() for i, weight := range w.weights { - rnd -= weight + rnd -= int64(weight) if rnd < 0 { return i, nil }