Skip to content

Commit b948f80

Browse files
authored
Improve error messages in php_random_bytes() (#9169)
1 parent da84287 commit b948f80

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

ext/random/random.c

+24-6
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw)
470470
/* Defer to CryptGenRandom on Windows */
471471
if (php_win32_get_random_bytes(bytes, size) == FAILURE) {
472472
if (should_throw) {
473-
zend_throw_exception(zend_ce_exception, "Could not gather sufficient random data", 0);
473+
zend_throw_exception(zend_ce_exception, "Failed to retrieve randomness from the operating system (BCryptGenRandom)", 0);
474474
}
475475
return FAILURE;
476476
}
@@ -483,7 +483,7 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw)
483483
*/
484484
if (CCRandomGenerateBytes(bytes, size) != kCCSuccess) {
485485
if (should_throw) {
486-
zend_throw_exception(zend_ce_exception, "Error generating bytes", 0);
486+
zend_throw_exception(zend_ce_exception, "Failed to retrieve randomness from the operating system (CCRandomGenerateBytes)", 0);
487487
}
488488
return FAILURE;
489489
}
@@ -496,6 +496,8 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw)
496496
/* Linux getrandom(2) syscall or FreeBSD/DragonFlyBSD getrandom(2) function*/
497497
/* Keep reading until we get enough entropy */
498498
while (read_bytes < size) {
499+
errno = 0;
500+
499501
/* Below, (bytes + read_bytes) is pointer arithmetic.
500502
501503
bytes read_bytes size
@@ -522,7 +524,7 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw)
522524
/* Try again */
523525
continue;
524526
} else {
525-
/* If the syscall fails, fall back to reading from /dev/urandom */
527+
/* If the syscall fails, fall back to reading from /dev/urandom */
526528
break;
527529
}
528530
}
@@ -539,15 +541,22 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw)
539541
struct stat st;
540542

541543
if (fd < 0) {
544+
errno = 0;
542545
# if HAVE_DEV_URANDOM
543546
fd = open("/dev/urandom", O_RDONLY);
544547
# endif
545548
if (fd < 0) {
546549
if (should_throw) {
547-
zend_throw_exception(zend_ce_exception, "Cannot open source device", 0);
550+
if (errno != 0) {
551+
zend_throw_exception_ex(zend_ce_exception, 0, "Cannot open /dev/urandom: %s", strerror(errno));
552+
} else {
553+
zend_throw_exception_ex(zend_ce_exception, 0, "Cannot open /dev/urandom");
554+
}
548555
}
549556
return FAILURE;
550557
}
558+
559+
errno = 0;
551560
/* Does the file exist and is it a character device? */
552561
if (fstat(fd, &st) != 0 ||
553562
# ifdef S_ISNAM
@@ -558,14 +567,19 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw)
558567
) {
559568
close(fd);
560569
if (should_throw) {
561-
zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
570+
if (errno != 0) {
571+
zend_throw_exception_ex(zend_ce_exception, 0, "Error reading from /dev/urandom: %s", strerror(errno));
572+
} else {
573+
zend_throw_exception_ex(zend_ce_exception, 0, "Error reading from /dev/urandom");
574+
}
562575
}
563576
return FAILURE;
564577
}
565578
RANDOM_G(random_fd) = fd;
566579
}
567580

568581
for (read_bytes = 0; read_bytes < size; read_bytes += (size_t) n) {
582+
errno = 0;
569583
n = read(fd, bytes + read_bytes, size - read_bytes);
570584
if (n <= 0) {
571585
break;
@@ -574,7 +588,11 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw)
574588

575589
if (read_bytes < size) {
576590
if (should_throw) {
577-
zend_throw_exception(zend_ce_exception, "Could not gather sufficient random data", 0);
591+
if (errno != 0) {
592+
zend_throw_exception_ex(zend_ce_exception, 0, "Could not gather sufficient random data: %s", strerror(errno));
593+
} else {
594+
zend_throw_exception_ex(zend_ce_exception, 0, "Could not gather sufficient random data");
595+
}
578596
}
579597
return FAILURE;
580598
}

0 commit comments

Comments
 (0)