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

Skip to content

Commit af59732

Browse files
committed
Cleanup random.c
Issue #27955: modify py_getrnadom() and dev_urandom() * Add comments from Python 3.7 * PEP 7 style: add {...}
1 parent a327331 commit af59732

1 file changed

Lines changed: 53 additions & 28 deletions

File tree

Python/random.c

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,20 @@ py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal)
119119
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
120120
#define PY_GETRANDOM 1
121121

122+
/* Call getrandom()
123+
- Return 1 on success
124+
- Return 0 if getrandom() syscall is not available (failed with ENOSYS)
125+
or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom
126+
not initialized yet) and raise=0.
127+
- Raise an exception (if raise is non-zero) and return -1 on error:
128+
getrandom() failed with EINTR and the Python signal handler raised an
129+
exception, or getrandom() failed with a different error. */
122130
static int
123131
py_getrandom(void *buffer, Py_ssize_t size, int raise)
124132
{
125-
/* Is getrandom() supported by the running kernel?
126-
* Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */
133+
/* Is getrandom() supported by the running kernel? Set to 0 if getrandom()
134+
failed with ENOSYS. Need Linux kernel 3.17 or newer, or Solaris
135+
11.3 or newer */
127136
static int getrandom_works = 1;
128137

129138
/* getrandom() on Linux will block if called before the kernel has
@@ -134,8 +143,9 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
134143
const int flags = GRND_NONBLOCK;
135144
long n;
136145

137-
if (!getrandom_works)
146+
if (!getrandom_works) {
138147
return 0;
148+
}
139149

140150
while (0 < size) {
141151
#ifdef sun
@@ -171,36 +181,42 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
171181
#endif
172182

173183
if (n < 0) {
184+
/* ENOSYS: getrandom() syscall not supported by the kernel (but
185+
* maybe supported by the host which built Python). */
174186
if (errno == ENOSYS) {
175187
getrandom_works = 0;
176188
return 0;
177189
}
178190
if (errno == EAGAIN) {
179-
/* If we failed with EAGAIN, the entropy pool was
180-
* uninitialized. In this case, we return failure to fall
181-
* back to reading from /dev/urandom.
182-
*
183-
* Note: In this case the data read will not be random so
184-
* should not be used for cryptographic purposes. Retaining
185-
* the existing semantics for practical purposes. */
191+
/* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system
192+
urandom is not initialiazed yet. In this case, fall back on
193+
reading from /dev/urandom.
194+
195+
Note: In this case the data read will not be random so
196+
should not be used for cryptographic purposes. Retaining
197+
the existing semantics for practical purposes. */
186198
getrandom_works = 0;
187199
return 0;
188200
}
189201

190202
if (errno == EINTR) {
191203
if (PyErr_CheckSignals()) {
192-
if (!raise)
204+
if (!raise) {
193205
Py_FatalError("getrandom() interrupted by a signal");
206+
}
194207
return -1;
195208
}
209+
196210
/* retry getrandom() */
197211
continue;
198212
}
199213

200-
if (raise)
214+
if (raise) {
201215
PyErr_SetFromErrno(PyExc_OSError);
202-
else
216+
}
217+
else {
203218
Py_FatalError("getrandom() failed");
219+
}
204220
return -1;
205221
}
206222

@@ -218,7 +234,9 @@ static struct {
218234
} urandom_cache = { -1 };
219235

220236

221-
/* Read size bytes from /dev/urandom into buffer.
237+
/* Read 'size' random bytes from py_getrandom(). Fall back on reading from
238+
/dev/urandom if getrandom() is not available.
239+
222240
Call Py_FatalError() on error. */
223241
static void
224242
dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
@@ -229,24 +247,26 @@ dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
229247
assert (0 < size);
230248

231249
#ifdef PY_GETRANDOM
232-
if (py_getrandom(buffer, size, 0) == 1)
250+
if (py_getrandom(buffer, size, 0) == 1) {
233251
return;
234-
/* getrandom() is not supported by the running kernel, fall back
235-
* on reading /dev/urandom */
252+
}
253+
/* getrandom() failed with ENOSYS,
254+
fall back on reading /dev/urandom */
236255
#endif
237256

238257
fd = _Py_open_noraise("/dev/urandom", O_RDONLY);
239-
if (fd < 0)
258+
if (fd < 0) {
240259
Py_FatalError("Failed to open /dev/urandom");
260+
}
241261

242262
while (0 < size)
243263
{
244264
do {
245265
n = read(fd, buffer, (size_t)size);
246266
} while (n < 0 && errno == EINTR);
247-
if (n <= 0)
248-
{
249-
/* stop on error or if read(size) returned 0 */
267+
268+
if (n <= 0) {
269+
/* read() failed or returned 0 bytes */
250270
Py_FatalError("Failed to read bytes from /dev/urandom");
251271
break;
252272
}
@@ -256,8 +276,10 @@ dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
256276
close(fd);
257277
}
258278

259-
/* Read size bytes from /dev/urandom into buffer.
260-
Return 0 on success, raise an exception and return -1 on error. */
279+
/* Read 'size' random bytes from py_getrandom(). Fall back on reading from
280+
/dev/urandom if getrandom() is not available.
281+
282+
Return 0 on success. Raise an exception and return -1 on error. */
261283
static int
262284
dev_urandom_python(char *buffer, Py_ssize_t size)
263285
{
@@ -273,12 +295,14 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
273295

274296
#ifdef PY_GETRANDOM
275297
res = py_getrandom(buffer, size, 1);
276-
if (res < 0)
298+
if (res < 0) {
277299
return -1;
278-
if (res == 1)
300+
}
301+
if (res == 1) {
279302
return 0;
280-
/* getrandom() is not supported by the running kernel, fall back
281-
* on reading /dev/urandom */
303+
}
304+
/* getrandom() failed with ENOSYS,
305+
fall back on reading /dev/urandom */
282306
#endif
283307

284308
if (urandom_cache.fd >= 0) {
@@ -325,8 +349,9 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
325349

326350
do {
327351
n = _Py_read(fd, buffer, (size_t)size);
328-
if (n == -1)
352+
if (n == -1) {
329353
return -1;
354+
}
330355
if (n == 0) {
331356
PyErr_Format(PyExc_RuntimeError,
332357
"Failed to read %zi bytes from /dev/urandom",

0 commit comments

Comments
 (0)