From: Bob Weinand <bobwei9@hotmail.com>
Date: Tue, 8 Sep 2015 22:58:09 +0000 (+0200)
Subject: Merged RFC Random Functions Throwing Exceptions in PHP 7
X-Git-Tag: php-7.1.0alpha1~1213
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c12917aa45639f7cb752645d2d1f37fd8b70c3e1;p=php

Merged RFC Random Functions Throwing Exceptions in PHP 7
Squashes commits from PR #1397

commit cd5dcc8c9eb43603d908abcea69c9e18df0f2ed5
Author: SammyK <sammyk@sammykmedia.com>
Date:   Tue Sep 8 13:53:42 2015 -0500

    Add min max samezies

commit b719499218a4e84efecd4dc1d4235d16142c9793
Author: SammyK <sammyk@sammykmedia.com>
Date:   Wed Sep 2 07:00:25 2015 -0500

    Make random_bytes() throw Error when $length <= 0 and random_int() throw Error when $min > $max

commit 0cca557291c278716ec4b00b32fc2bdc1c1c8848
Author: SammyK <sammyk@sammykmedia.com>
Date:   Wed Sep 2 06:55:59 2015 -0500

    Make random_*() functions throw Error exception when random bytes cannot be obtained

commit 998c7f1e209123605b41139e8d9093075ce16bd6
Author: SammyK <sammyk@sammykmedia.com>
Date:   Wed Sep 2 06:41:20 2015 -0500

    Make random_*() functions throw TypeError when zend_parse_parameters fails

commit 99d305c18820ff55d82d952777cbcdf1cf0158be
Author: SammyK <sammyk@sammykmedia.com>
Date:   Mon Jul 6 19:50:47 2015 -0500

    Make exceptions less specific

commit b042dfab290713366741a663a420cf12bf802f39
Author: SammyK <sammyk@sammykmedia.com>
Date:   Mon Jul 6 17:20:13 2015 -0500

    Upgrade warnings to RuntimeExceptions
---

diff --git a/NEWS b/NEWS
index a790f82919..4e0d012121 100644
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,10 @@ PHP                                                                        NEWS
   . Fixed bug #70449 (PHP won't compile on 10.4 and 10.5 because of missing
     constants). (Bob)
 
+- Standard:
+  . Implemented the RFC `Random Functions Throwing Exceptions in PHP 7`.
+    (Sammy Kaye Powers, Anthony)
+
 - Streams:
   . Fixed bug #70361 (HTTP stream wrapper doesn't close keep-alive connections).
     (Niklas Keller)
diff --git a/ext/standard/random.c b/ext/standard/random.c
index 9ae4e3c983..e2e48951cc 100644
--- a/ext/standard/random.c
+++ b/ext/standard/random.c
@@ -24,6 +24,7 @@
 #include <math.h>
 
 #include "php.h"
+#include "zend_exceptions.h"
 #include "php_random.h"
 
 #if PHP_WIN32
@@ -79,7 +80,7 @@ static int php_random_bytes(void *bytes, size_t size)
 #if PHP_WIN32
 	/* Defer to CryptGenRandom on Windows */
 	if (php_win32_get_random_bytes(bytes, size) == FAILURE) {
-		php_error_docref(NULL, E_WARNING, "Could not gather sufficient random data");
+		zend_throw_exception(zend_ce_exception, "Could not gather sufficient random data", 0);
 		return FAILURE;
 	}
 #elif HAVE_DECL_ARC4RANDOM_BUF
@@ -95,7 +96,7 @@ static int php_random_bytes(void *bytes, size_t size)
 		fd = open("/dev/urandom", O_RDONLY);
 #endif
 		if (fd < 0) {
-			php_error_docref(NULL, E_WARNING, "Cannot open source device");
+			zend_throw_exception(zend_ce_exception, "Cannot open source device", 0);
 			return FAILURE;
 		}
 
@@ -111,7 +112,7 @@ static int php_random_bytes(void *bytes, size_t size)
 	}
 
 	if (read_bytes < size) {
-		php_error_docref(NULL, E_WARNING, "Could not gather sufficient random data");
+		zend_throw_exception(zend_ce_exception, "Could not gather sufficient random data", 0);
 		return FAILURE;
 	}
 #endif
@@ -127,20 +128,20 @@ PHP_FUNCTION(random_bytes)
 	zend_long size;
 	zend_string *bytes;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &size) == FAILURE) {
+	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "l", &size) == FAILURE) {
 		return;
 	}
 
 	if (size < 1) {
-		php_error_docref(NULL, E_WARNING, "Length must be greater than 0");
-		RETURN_FALSE;
+		zend_throw_exception(zend_ce_error, "Length must be greater than 0", 0);
+		return;
 	}
 
 	bytes = zend_string_alloc(size, 0);
 
 	if (php_random_bytes(ZSTR_VAL(bytes), size) == FAILURE) {
 		zend_string_release(bytes);
-		RETURN_FALSE;
+		return;
 	}
 
 	ZSTR_VAL(bytes)[size] = '\0';
@@ -158,19 +159,23 @@ PHP_FUNCTION(random_int)
 	zend_ulong umax;
 	zend_ulong result;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &min, &max) == FAILURE) {
+	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "ll", &min, &max) == FAILURE) {
 		return;
 	}
 
-	if (min >= max) {
-		php_error_docref(NULL, E_WARNING, "Minimum value must be less than the maximum value");
-		RETURN_FALSE;
+	if (min > max) {
+		zend_throw_exception(zend_ce_error, "Minimum value must be less than or equal to the maximum value", 0);
+		return;
+	}
+
+	if (min == max) {
+		RETURN_LONG(min);
 	}
 
 	umax = max - min;
 
 	if (php_random_bytes(&result, sizeof(result)) == FAILURE) {
-		RETURN_FALSE;
+		return;
 	}
 
 	/* Special case where no modulus is required */
@@ -185,11 +190,11 @@ PHP_FUNCTION(random_int)
 	if ((umax & (umax - 1)) != 0) {
 		/* Ceiling under which ZEND_LONG_MAX % max == 0 */
 		zend_ulong limit = ZEND_ULONG_MAX - (ZEND_ULONG_MAX % umax) - 1;
-	
+
 		/* Discard numbers over the limit to avoid modulo bias */
 		while (result > limit) {
 			if (php_random_bytes(&result, sizeof(result)) == FAILURE) {
-				RETURN_FALSE;
+				return;
 			}
 		}
 	}
diff --git a/ext/standard/tests/random/random_bytes_error.phpt b/ext/standard/tests/random/random_bytes_error.phpt
index 466a3ac3bf..c1607c01ff 100644
--- a/ext/standard/tests/random/random_bytes_error.phpt
+++ b/ext/standard/tests/random/random_bytes_error.phpt
@@ -4,14 +4,19 @@ Test error operation of random_bytes()
 <?php
 //-=-=-=-
 
-var_dump(random_bytes());
+try {
+    $bytes = random_bytes();
+} catch (TypeError $e) {
+    echo $e->getMessage().PHP_EOL;
+}
 
-var_dump(random_bytes(-1));
+try {
+    $bytes = random_bytes(0);
+} catch (Error $e) {
+    echo $e->getMessage().PHP_EOL;
+}
 
 ?>
---EXPECTF--
-Warning: random_bytes() expects exactly 1 parameter, 0 given in %s on line %d
-NULL
-
-Warning: random_bytes(): Length must be greater than 0 in %s on line %d
-bool(false)
+--EXPECT--
+random_bytes() expects exactly 1 parameter, 0 given
+Length must be greater than 0
diff --git a/ext/standard/tests/random/random_int.phpt b/ext/standard/tests/random/random_int.phpt
index 0c3081452c..768bc4f97d 100644
--- a/ext/standard/tests/random/random_int.phpt
+++ b/ext/standard/tests/random/random_int.phpt
@@ -11,8 +11,11 @@ var_dump($x >= 10 && $x <= 100);
 
 var_dump(random_int(-1000, -1) < 0);
 
+var_dump(random_int(42,42));
+
 ?>
 --EXPECT--
 bool(true)
 bool(true)
 bool(true)
+int(42)
diff --git a/ext/standard/tests/random/random_int_error.phpt b/ext/standard/tests/random/random_int_error.phpt
index 5f7a69b215..9b98bdd7c0 100644
--- a/ext/standard/tests/random/random_int_error.phpt
+++ b/ext/standard/tests/random/random_int_error.phpt
@@ -4,19 +4,26 @@ Test error operation of random_int()
 <?php
 //-=-=-=-
 
-var_dump(random_int());
+try {
+    $randomInt = random_int();
+} catch (TypeError $e) {
+    echo $e->getMessage().PHP_EOL;
+}
 
-var_dump(random_int(10));
+try {
+    $randomInt = random_int(42);
+} catch (TypeError $e) {
+    echo $e->getMessage().PHP_EOL;
+}
 
-var_dump(random_int(10, 0));
+try {
+    $randomInt = random_int(42,0);
+} catch (Error $e) {
+    echo $e->getMessage().PHP_EOL;
+}
 
 ?>
---EXPECTF--
-Warning: random_int() expects exactly 2 parameters, 0 given in %s on line %d
-NULL
-
-Warning: random_int() expects exactly 2 parameters, 1 given in %s on line %d
-NULL
-
-Warning: random_int(): Minimum value must be less than the maximum value in %s on line %d
-bool(false)
+--EXPECT--
+random_int() expects exactly 2 parameters, 0 given
+random_int() expects exactly 2 parameters, 1 given
+Minimum value must be less than or equal to the maximum value