Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 223221b

Browse files
bpo-40286: Makes simpler the relation between randbytes() and getrandbits() (GH-19574)
1 parent 5b1d918 commit 223221b

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

Lib/test/test_random.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ def test_randbytes(self):
758758
# Mersenne Twister randbytes() is deterministic
759759
# and does not depend on the endian and bitness.
760760
seed = 8675309
761-
expected = b'f\xf9\xa836\xd0\xa4\xf4\x82\x9f\x8f\x19\xf0eo\x02'
761+
expected = b'3\xa8\xf9f\xf4\xa4\xd06\x19\x8f\x9f\x82\x02oe\xf0'
762762

763763
self.gen.seed(seed)
764764
self.assertEqual(self.gen.randbytes(16), expected)
@@ -773,19 +773,35 @@ def test_randbytes(self):
773773
self.assertEqual(b''.join([self.gen.randbytes(4) for _ in range(4)]),
774774
expected)
775775

776-
# Each randbytes(2) or randbytes(3) call consumes 4 bytes of entropy
776+
# Each randbytes(1), randbytes(2) or randbytes(3) call consumes
777+
# 4 bytes of entropy
777778
self.gen.seed(seed)
778-
expected2 = b''.join(expected[i:i + 2]
779+
expected1 = expected[3::4]
780+
self.assertEqual(b''.join(self.gen.randbytes(1) for _ in range(4)),
781+
expected1)
782+
783+
self.gen.seed(seed)
784+
expected2 = b''.join(expected[i + 2: i + 4]
779785
for i in range(0, len(expected), 4))
780786
self.assertEqual(b''.join(self.gen.randbytes(2) for _ in range(4)),
781787
expected2)
782788

783789
self.gen.seed(seed)
784-
expected3 = b''.join(expected[i:i + 3]
790+
expected3 = b''.join(expected[i + 1: i + 4]
785791
for i in range(0, len(expected), 4))
786792
self.assertEqual(b''.join(self.gen.randbytes(3) for _ in range(4)),
787793
expected3)
788794

795+
def test_randbytes_getrandbits(self):
796+
# There is a simple relation between randbytes() and getrandbits()
797+
seed = 2849427419
798+
gen2 = random.Random()
799+
self.gen.seed(seed)
800+
gen2.seed(seed)
801+
for n in range(9):
802+
self.assertEqual(self.gen.randbytes(n),
803+
gen2.getrandbits(n * 8).to_bytes(n, 'little'))
804+
789805

790806
def gamma(z, sqrt2pi=(2.0*pi)**0.5):
791807
# Reflection to right half of complex plane

Modules/_randommodule.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -534,31 +534,25 @@ _random_Random_randbytes_impl(RandomObject *self, Py_ssize_t n)
534534
return NULL;
535535
}
536536

537-
if (n == 0) {
538-
/* Don't consume any entropy */
539-
return PyBytes_FromStringAndSize(NULL, 0);
540-
}
541-
542537
PyObject *bytes = PyBytes_FromStringAndSize(NULL, n);
543538
if (bytes == NULL) {
544539
return NULL;
545540
}
546541
uint8_t *ptr = (uint8_t *)PyBytes_AS_STRING(bytes);
547542

548-
do {
543+
for (; n; ptr += 4, n -= 4) {
549544
uint32_t word = genrand_uint32(self);
550-
#if PY_LITTLE_ENDIAN
551-
/* Convert to big endian */
545+
#if PY_BIG_ENDIAN
546+
/* Convert to little endian */
552547
word = _Py_bswap32(word);
553548
#endif
554549
if (n < 4) {
555-
memcpy(ptr, &word, n);
550+
/* Drop least significant bits */
551+
memcpy(ptr, (uint8_t *)&word + (4 - n), n);
556552
break;
557553
}
558554
memcpy(ptr, &word, 4);
559-
ptr += 4;
560-
n -= 4;
561-
} while (n);
555+
}
562556

563557
return bytes;
564558
}

0 commit comments

Comments
 (0)