@@ -157,13 +157,16 @@ static zend_object_handlers random_randomizer_object_handlers;
157157
158158static uint32_t rand_range32 (const php_random_engine_algo * algo , void * state , uint32_t umax ) {
159159 uint32_t result , limit ;
160- size_t generated_size = algo -> size (state );
160+ size_t generated_size ;
161+
162+ RANDOM_ENGINE_GENERATE_SIZE (algo , state , result , generated_size );
161163
162- result = algo -> generate (state );
163164 while (generated_size < sizeof (uint32_t )) {
164- size_t generate_size = algo -> size (state );
165+ uint32_t ret ;
166+ size_t generate_size ;
165167
166- result = (result << generate_size ) | algo -> generate (state );
168+ RANDOM_ENGINE_GENERATE_SIZE (algo , state , ret , generate_size );
169+ result = (result << generate_size ) | ret ;
167170
168171 generated_size += generate_size ;
169172 }
@@ -186,12 +189,14 @@ static uint32_t rand_range32(const php_random_engine_algo *algo, void *state, ui
186189
187190 /* Discard numbers over the limit to avoid modulo bias */
188191 while (UNEXPECTED (result > limit )) {
189- generated_size = algo -> size (state );
190- result = algo -> generate (state );
192+ RANDOM_ENGINE_GENERATE_SIZE (algo , state , result , generated_size );
191193 while (generated_size < sizeof (uint32_t )) {
192- size_t generate_size = algo -> size (state );
194+ uint32_t ret ;
195+ size_t generate_size ;
196+
197+ RANDOM_ENGINE_GENERATE_SIZE (algo , state , ret , generate_size );
193198
194- result = (result << generate_size ) | algo -> generate ( state ) ;
199+ result = (result << generate_size ) | ret ;
195200
196201 generated_size += generate_size ;
197202 }
@@ -203,13 +208,17 @@ static uint32_t rand_range32(const php_random_engine_algo *algo, void *state, ui
203208#if ZEND_ULONG_MAX > UINT32_MAX
204209static uint64_t rand_range64 (const php_random_engine_algo * algo , void * state , uint64_t umax ) {
205210 uint64_t result , limit ;
206- size_t generated_size = algo -> size (state );
211+ size_t generated_size ;
212+
213+ RANDOM_ENGINE_GENERATE_SIZE (algo , state , result , generated_size );
207214
208- result = algo -> generate (state );
209215 while (generated_size < sizeof (uint64_t )) {
210- size_t generate_size = algo -> size (state );
216+ uint64_t ret ;
217+ size_t generate_size ;
218+
219+ RANDOM_ENGINE_GENERATE_SIZE (algo , state , ret , generate_size );
211220
212- result = (result << generate_size ) | algo -> generate ( state ) ;
221+ result = (result << generate_size ) | ret ;
213222
214223 generated_size += generate_size ;
215224 }
@@ -232,13 +241,15 @@ static uint64_t rand_range64(const php_random_engine_algo *algo, void *state, ui
232241
233242 /* Discard numbers over the limit to avoid modulo bias */
234243 while (UNEXPECTED (result > limit )) {
235- generated_size = algo -> size (state );
236- result = algo -> generate (state );
244+ RANDOM_ENGINE_GENERATE_SIZE (algo , state , result , generated_size );
237245
238246 while (generated_size < sizeof (uint64_t )) {
239- size_t generate_size = algo -> size (state );
247+ uint64_t ret ;
248+ size_t generate_size ;
240249
241- result = (result << generate_size ) | algo -> generate (state );
250+ RANDOM_ENGINE_GENERATE_SIZE (algo , state , ret , generate_size );
251+
252+ result = (result << generate_size ) | ret ;
242253
243254 generated_size += generate_size ;
244255 }
@@ -289,7 +300,7 @@ static zend_object *php_random_engine_common_clone_obj(zend_object *old_object)
289300
290301/* XorShift128Plus begin */
291302
292- static inline size_t xorshift128plus_size (void * state ) {
303+ static inline size_t xorshift128plus_dynamic_generate_size (void * state ) {
293304 return sizeof (uint64_t );
294305}
295306
@@ -362,7 +373,7 @@ static zend_object *php_random_engine_xorshift128plus_new(zend_class_entry *ce)
362373
363374/* MersenneTwister begin */
364375
365- static inline size_t mersennetwister_size (void * state ) {
376+ static inline size_t mersennetwister_dynamic_generate__size (void * state ) {
366377 return sizeof (uint32_t );
367378}
368379
@@ -484,7 +495,7 @@ static zend_object *php_random_engine_mersennetwister_new(zend_class_entry *ce)
484495
485496/* CombinedLCG begin */
486497
487- static inline size_t combinedlcg_size (void * state ) {
498+ static inline size_t combinedlcg_dynamic_generate__size (void * state ) {
488499 return sizeof (uint32_t );
489500}
490501
@@ -581,7 +592,7 @@ static zend_object *php_random_engine_combinedlcg_new(zend_class_entry *ce) {
581592
582593/* Secure begin */
583594
584- static inline size_t secure_size (void * state ) {
595+ static inline size_t secure_dynamic_generate_size (void * state ) {
585596 return sizeof (uint64_t );
586597}
587598
@@ -601,13 +612,10 @@ static zend_object *php_random_engine_secure_new(zend_class_entry *ce) {
601612
602613/* User begin */
603614
604- static inline size_t user_size (void * state ) {
615+ static inline size_t user_dynamic_generate_size (void * state ) {
605616 php_random_engine_state_user * s = (php_random_engine_state_user * ) state ;
606- zval retval ;
607617
608- zend_call_known_instance_method_with_0_params (s -> size_method , s -> object , & retval );
609-
610- return (size_t ) zval_get_long (& retval );
618+ return s -> last_generate_size ;
611619}
612620
613621static uint64_t user_generate (void * state ) {
@@ -619,13 +627,11 @@ static uint64_t user_generate(void *state) {
619627
620628 zend_call_known_instance_method_with_0_params (s -> generate_method , s -> object , & retval );
621629
622- /* not supported over 64-bit wide currently */
623- size = user_size (state );
624- if (size > sizeof (uint64_t )) {
625- size = sizeof (uint64_t );
626- }
630+ /* Store generated size in a state */
631+ size = Z_STR (retval )-> len ;
632+ s -> last_generate_size = size ;
627633
628- /* Endianness safe */
634+ /* Endianness safe copy */
629635 char * ptr = (char * ) & result ;
630636 for (i = 0 ; i < size ; i ++ ) {
631637 ptr [i ] = Z_STR (retval )-> val [i ];
@@ -639,44 +645,49 @@ static uint64_t user_generate(void *state) {
639645/* User end */
640646
641647const php_random_engine_algo php_random_engine_algo_xorshift128plus = {
648+ sizeof (uint64_t ),
649+ xorshift128plus_dynamic_generate_size ,
642650 sizeof (php_random_engine_state_xorshift128plus ),
643- xorshift128plus_size ,
644651 xorshift128plus_generate ,
645652 xorshift128plus_seed ,
646653 xorshift128plus_serialize ,
647654 xorshift128plus_unserialize
648655};
649656
650657const php_random_engine_algo php_random_engine_algo_mersennetwister = {
658+ sizeof (uint32_t ),
659+ mersennetwister_dynamic_generate__size ,
651660 sizeof (php_random_engine_state_mersennetwister ),
652- mersennetwister_size ,
653661 mersennetwister_generate ,
654662 mersennetwister_seed ,
655663 mersennetwister_serialize ,
656664 mersennetwister_unserialize
657665};
658666
659667const php_random_engine_algo php_random_engine_algo_combinedlcg = {
668+ sizeof (uint32_t ),
669+ combinedlcg_dynamic_generate__size ,
660670 sizeof (php_random_engine_state_combinedlcg ),
661- combinedlcg_size ,
662671 combinedlcg_generate ,
663672 combinedlcg_seed ,
664673 combinedlcg_serialize ,
665674 combinedlcg_unserialize
666675};
667676
668677const php_random_engine_algo php_random_engine_algo_secure = {
678+ sizeof (uint64_t ),
679+ secure_dynamic_generate_size ,
669680 0 ,
670- secure_size ,
671681 secure_generate ,
672682 NULL ,
673683 NULL ,
674684 NULL
675685};
676686
677687const php_random_engine_algo php_random_engine_algo_user = {
688+ 0 , /* does not support static generate size */
689+ user_dynamic_generate_size , /* always use dynamic_generate_size */
678690 sizeof (php_random_engine_state_user ),
679- user_size ,
680691 user_generate ,
681692 NULL ,
682693 NULL ,
@@ -988,7 +999,7 @@ PHPAPI zend_long php_random_engine_range(const php_random_engine_algo *algo, voi
988999{
9891000 zend_ulong umax = max - min ;
9901001
991- if (algo -> size (state ) >= sizeof (uint64_t )) {
1002+ if (algo -> dynamic_generate_size (state ) >= sizeof (uint64_t )) {
9921003 return (zend_long ) rand_range64 (algo , state , umax ) + min ;
9931004 }
9941005
@@ -1169,7 +1180,7 @@ PHP_METHOD(Random_Engine_XorShift128Plus, __construct)
11691180 if (str_seed ) {
11701181 /* char (8 bit) * 16 = 128 bits */
11711182 if (str_seed -> len == 16 ) {
1172- /* Endianness safe */
1183+ /* Endianness safe copy */
11731184 int i ;
11741185 char * ptr = (char * ) & state -> s ;
11751186 for (i = 0 ; i < 16 ; i ++ ) {
@@ -1185,17 +1196,6 @@ PHP_METHOD(Random_Engine_XorShift128Plus, __construct)
11851196}
11861197/* }}} */
11871198
1188- /* {{{ Get a generate random number byte size */
1189- PHP_METHOD (Random_Engine_XorShift128Plus , nextByteSize )
1190- {
1191- php_random_engine * engine = Z_RANDOM_ENGINE_P (ZEND_THIS );
1192-
1193- ZEND_PARSE_PARAMETERS_NONE ();
1194-
1195- RETURN_LONG ((zend_long ) engine -> algo -> size (engine -> state ));
1196- }
1197- /* }}} */
1198-
11991199/* {{{ Generate a random number */
12001200PHP_METHOD (Random_Engine_XorShift128Plus , generate )
12011201{
@@ -1208,10 +1208,10 @@ PHP_METHOD(Random_Engine_XorShift128Plus, generate)
12081208 ZEND_PARSE_PARAMETERS_NONE ();
12091209
12101210 generated = engine -> algo -> generate (engine -> state );
1211- size = engine -> algo -> size (engine -> state );
1211+ size = engine -> algo -> dynamic_generate_size (engine -> state );
12121212 bytes = zend_string_alloc (size , 0 );
12131213
1214- /* Endianness safe */
1214+ /* Endianness safe copy */
12151215 for (i = 0 ; i < size ; i ++ ) {
12161216 bytes -> val [i ] = (generated >> (i * 8 )) & 0xff ;
12171217 }
@@ -1435,11 +1435,11 @@ PHP_METHOD(Random_Randomizer, getBytes)
14351435 ret = zend_string_alloc (length , 0 );
14361436
14371437 while (generated_bytes <= length ) {
1438- size_t generated_size = randomizer -> algo -> size (randomizer -> state );
1438+ size_t generated_size = randomizer -> algo -> dynamic_generate_size (randomizer -> state );
14391439
14401440 buf = randomizer -> algo -> generate (randomizer -> state );
14411441 while (generated_size < sizeof (uint64_t )) {
1442- size_t generate_size = randomizer -> algo -> size (randomizer -> state );
1442+ size_t generate_size = randomizer -> algo -> dynamic_generate_size (randomizer -> state );
14431443
14441444 buf = (buf << generate_size ) | randomizer -> algo -> generate (randomizer -> state );
14451445
0 commit comments