@@ -105,42 +105,49 @@ PHP_FUNCTION(random_bytes)
105
105
Return an arbitrary pseudo-random integer */
106
106
PHP_FUNCTION (random_int )
107
107
{
108
+ zend_long min = ZEND_LONG_MIN ;
108
109
zend_long max = ZEND_LONG_MAX ;
109
- zend_long limit ;
110
- zend_long result ;
110
+ zend_ulong limit ;
111
+ zend_ulong umax ;
112
+ zend_ulong result ;
111
113
112
- if (zend_parse_parameters (ZEND_NUM_ARGS (), "|l" , & max ) == FAILURE ) {
114
+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "|ll" , & min , & max ) == FAILURE ) {
113
115
return ;
114
116
}
115
117
116
- if (max <= 0 || max > ZEND_LONG_MAX ) {
117
- php_error_docref (NULL , E_WARNING , "Cannot use maximum less than 1 or greater than %d" , ZEND_LONG_MAX );
118
+ if (min >= max ) {
119
+ php_error_docref (NULL , E_WARNING , "Minimum value must be greater than the maximum value" );
118
120
RETURN_FALSE ;
119
121
}
120
122
121
- // Special case so we can return a range inclusive of the upper bound
122
- if (max == ZEND_LONG_MAX ) {
123
- if (php_random_bytes (& result , sizeof (result )) == FAILURE ) {
124
- return ;
125
- }
126
- RETURN_LONG (result & ZEND_LONG_MAX );
127
- }
123
+ umax = max - min ;
128
124
129
- // Increment the max so the range is inclusive of max
130
- max ++ ;
125
+ if (php_random_bytes (& result , sizeof (result )) == FAILURE ) {
126
+ return ;
127
+ }
131
128
132
- // Ceiling under which ZEND_LONG_MAX % max == 0
133
- limit = ZEND_LONG_MAX - (ZEND_LONG_MAX % max ) - 1 ;
129
+ // Special case where no modulus is required
130
+ if (umax == ZEND_ULONG_MAX ) {
131
+ RETURN_LONG ((zend_long )result );
132
+ }
134
133
135
- // Discard numbers over the limit to avoid modulo bias
136
- do {
137
- if (php_random_bytes (& result , sizeof (result )) == FAILURE ) {
138
- return ;
134
+ // Increment the max so the range is inclusive of max
135
+ umax ++ ;
136
+
137
+ // Powers of two are not biased
138
+ if (umax & ~umax != umax ) {
139
+ // Ceiling under which ZEND_LONG_MAX % max == 0
140
+ limit = ZEND_ULONG_MAX - (ZEND_ULONG_MAX % umax ) - 1 ;
141
+
142
+ // Discard numbers over the limit to avoid modulo bias
143
+ while (result > limit ) {
144
+ if (php_random_bytes (& result , sizeof (result )) == FAILURE ) {
145
+ return ;
146
+ }
139
147
}
140
- result &= ZEND_LONG_MAX ;
141
- } while (result > limit );
148
+ }
142
149
143
- RETURN_LONG (result % max );
150
+ RETURN_LONG (( zend_long )(( result % umax ) + min ) );
144
151
}
145
152
/* }}} */
146
153
0 commit comments