From e2c3f62f186eb6ca253220df061a12107b4fc495 Mon Sep 17 00:00:00 2001 From: upstream Date: Fri, 4 Sep 2026 04:36:21 +0200 Subject: [PATCH] Upstream oklog/ulid state of the touched files before a7f0dceacf --- ulid.go | 13 ++++--------- ulid_test.go | 44 -------------------------------------------- 2 files changed, 4 insertions(+), 53 deletions(-) diff --git a/ulid.go b/ulid.go index 8bbda1b..e07e1a6 100644 --- a/ulid.go +++ b/ulid.go @@ -641,7 +641,7 @@ func (m *MonotonicEntropy) increment() error { return nil } -// random returns a uniform random value in [1, m.inc], reading entropy +// random returns a uniform random value in [1, m.inc), reading entropy // from m.Reader. When m.inc == 0 || m.inc == 1, it returns 1. // Adapted from: https://golang.org/pkg/crypto/rand/#Int func (m *MonotonicEntropy) random() (inc uint64, err error) { @@ -651,7 +651,7 @@ func (m *MonotonicEntropy) random() (inc uint64, err error) { // Fast path for using a underlying rand.Rand directly. if m.rng != nil { - // Range: [1, m.inc] + // Range: [1, m.inc) return 1 + uint64(m.rng.Int63n(int64(m.inc))), nil } @@ -667,7 +667,7 @@ func (m *MonotonicEntropy) random() (inc uint64, err error) { msbitLen = 8 } - for { + for inc == 0 || inc >= m.inc { if _, err = io.ReadFull(m.Reader, m.rand[:byteLen]); err != nil { return 0, err } @@ -688,14 +688,9 @@ func (m *MonotonicEntropy) random() (inc uint64, err error) { case 5, 6, 7, 8: inc = uint64(binary.LittleEndian.Uint64(m.rand[:8])) } - - // inc may exceed m.inc; redraw rather than bias the low end of the range. - if inc < m.inc { - break - } } - // Range: [1, m.inc] + // Range: [1, m.inc) return 1 + inc, nil } diff --git a/ulid_test.go b/ulid_test.go index 7c4bf90..afa194b 100644 --- a/ulid_test.go +++ b/ulid_test.go @@ -19,7 +19,6 @@ import ( "fmt" "io" "math" - "math/big" "math/rand" "strings" "testing" @@ -630,49 +629,6 @@ func TestMonotonic(t *testing.T) { } } -// Regression test: random() rejected a masked draw of 0, making an -// increment of 1 unreachable and inc == 2 fully deterministic. The reader -// yields an exact byte sequence so the result does not depend on chance. -func TestMonotonicIncrementRange(t *testing.T) { - t.Parallel() - - // The first 10 bytes seed the first ULID; the rest are consumed by random(). - seed := append([]byte{0x01}, bytes.Repeat([]byte{0x00}, 9)...) - draws := []byte{0x00, 0x01, 0x02, 0x03, 0x00} - reader := bytes.NewReader(append(seed, draws...)) - - entropy := ulid.Monotonic(reader, 2) - - prev, err := ulid.New(123, entropy) - if err != nil { - t.Fatal(err) - } - - // masked 0 and 1 are accepted as increments 1 and 2; 2 and 3 are redrawn - wantDeltas := []uint64{1, 2, 1} - - for i, want := range wantDeltas { - next, err := ulid.New(123, entropy) - if err != nil { - t.Fatalf("draw %d: %v", i, err) - } - - if prev.Compare(next) >= 0 { - t.Fatalf("draw %d: monotonicity violated: prev=%v next=%v", i, prev, next) - } - - delta := new(big.Int).Sub( - new(big.Int).SetBytes(next.Entropy()), - new(big.Int).SetBytes(prev.Entropy()), - ).Uint64() - if delta != want { - t.Fatalf("draw %d: delta = %d, want %d", i, delta, want) - } - - prev = next - } -} - func TestMonotonicOverflow(t *testing.T) { t.Parallel()