1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Sammy Kaye Powers <me@sammyk.me> |
14 | Go Kudo <zeriyoshi@php.net> |
15 +----------------------------------------------------------------------+
16 */
17
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21
22 #include <stdlib.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <math.h>
26
27 #include "php.h"
28
29 #include "Zend/zend_enum.h"
30 #include "Zend/zend_exceptions.h"
31
32 #include "php_random.h"
33 #include "php_random_csprng.h"
34
35 #if HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38
39 #ifdef PHP_WIN32
40 # include "win32/time.h"
41 # include "win32/winutil.h"
42 # include <process.h>
43 #else
44 # include <sys/time.h>
45 #endif
46
47 #if HAVE_SYS_PARAM_H
48 # include <sys/param.h>
49 #endif
50
51 #include "random_arginfo.h"
52
53 PHPAPI ZEND_DECLARE_MODULE_GLOBALS(random)
54
55 PHPAPI zend_class_entry *random_ce_Random_Engine;
56 PHPAPI zend_class_entry *random_ce_Random_CryptoSafeEngine;
57
58 PHPAPI zend_class_entry *random_ce_Random_Engine_Mt19937;
59 PHPAPI zend_class_entry *random_ce_Random_Engine_PcgOneseq128XslRr64;
60 PHPAPI zend_class_entry *random_ce_Random_Engine_Xoshiro256StarStar;
61 PHPAPI zend_class_entry *random_ce_Random_Engine_Secure;
62
63 PHPAPI zend_class_entry *random_ce_Random_Randomizer;
64
65 PHPAPI zend_class_entry *random_ce_Random_IntervalBoundary;
66
67 PHPAPI zend_class_entry *random_ce_Random_RandomError;
68 PHPAPI zend_class_entry *random_ce_Random_BrokenRandomEngineError;
69 PHPAPI zend_class_entry *random_ce_Random_RandomException;
70
71 static zend_object_handlers random_engine_mt19937_object_handlers;
72 static zend_object_handlers random_engine_pcgoneseq128xslrr64_object_handlers;
73 static zend_object_handlers random_engine_xoshiro256starstar_object_handlers;
74 static zend_object_handlers random_engine_secure_object_handlers;
75 static zend_object_handlers random_randomizer_object_handlers;
76
php_random_range32(const php_random_algo * algo,php_random_status * status,uint32_t umax)77 PHPAPI uint32_t php_random_range32(const php_random_algo *algo, php_random_status *status, uint32_t umax)
78 {
79 uint32_t result, limit;
80 size_t total_size = 0;
81 uint32_t count = 0;
82
83 result = 0;
84 total_size = 0;
85 do {
86 php_random_result r = algo->generate(status);
87 result = result | (((uint32_t) r.result) << (total_size * 8));
88 total_size += r.size;
89 if (EG(exception)) {
90 return 0;
91 }
92 } while (total_size < sizeof(uint32_t));
93
94 /* Special case where no modulus is required */
95 if (UNEXPECTED(umax == UINT32_MAX)) {
96 return result;
97 }
98
99 /* Increment the max so range is inclusive of max */
100 umax++;
101
102 /* Powers of two are not biased */
103 if ((umax & (umax - 1)) == 0) {
104 return result & (umax - 1);
105 }
106
107 /* Ceiling under which UINT32_MAX % max == 0 */
108 limit = UINT32_MAX - (UINT32_MAX % umax) - 1;
109
110 /* Discard numbers over the limit to avoid modulo bias */
111 while (UNEXPECTED(result > limit)) {
112 /* If the requirements cannot be met in a cycles, return fail */
113 if (++count > PHP_RANDOM_RANGE_ATTEMPTS) {
114 zend_throw_error(random_ce_Random_BrokenRandomEngineError, "Failed to generate an acceptable random number in %d attempts", PHP_RANDOM_RANGE_ATTEMPTS);
115 return 0;
116 }
117
118 result = 0;
119 total_size = 0;
120 do {
121 php_random_result r = algo->generate(status);
122 result = result | (((uint32_t) r.result) << (total_size * 8));
123 total_size += r.size;
124 if (EG(exception)) {
125 return 0;
126 }
127 } while (total_size < sizeof(uint32_t));
128 }
129
130 return result % umax;
131 }
132
php_random_range64(const php_random_algo * algo,php_random_status * status,uint64_t umax)133 PHPAPI uint64_t php_random_range64(const php_random_algo *algo, php_random_status *status, uint64_t umax)
134 {
135 uint64_t result, limit;
136 size_t total_size = 0;
137 uint32_t count = 0;
138
139 result = 0;
140 total_size = 0;
141 do {
142 php_random_result r = algo->generate(status);
143 result = result | (r.result << (total_size * 8));
144 total_size += r.size;
145 if (EG(exception)) {
146 return 0;
147 }
148 } while (total_size < sizeof(uint64_t));
149
150 /* Special case where no modulus is required */
151 if (UNEXPECTED(umax == UINT64_MAX)) {
152 return result;
153 }
154
155 /* Increment the max so range is inclusive of max */
156 umax++;
157
158 /* Powers of two are not biased */
159 if ((umax & (umax - 1)) == 0) {
160 return result & (umax - 1);
161 }
162
163 /* Ceiling under which UINT64_MAX % max == 0 */
164 limit = UINT64_MAX - (UINT64_MAX % umax) - 1;
165
166 /* Discard numbers over the limit to avoid modulo bias */
167 while (UNEXPECTED(result > limit)) {
168 /* If the requirements cannot be met in a cycles, return fail */
169 if (++count > PHP_RANDOM_RANGE_ATTEMPTS) {
170 zend_throw_error(random_ce_Random_BrokenRandomEngineError, "Failed to generate an acceptable random number in %d attempts", PHP_RANDOM_RANGE_ATTEMPTS);
171 return 0;
172 }
173
174 result = 0;
175 total_size = 0;
176 do {
177 php_random_result r = algo->generate(status);
178 result = result | (r.result << (total_size * 8));
179 total_size += r.size;
180 if (EG(exception)) {
181 return 0;
182 }
183 } while (total_size < sizeof(uint64_t));
184 }
185
186 return result % umax;
187 }
188
php_random_engine_mt19937_new(zend_class_entry * ce)189 static zend_object *php_random_engine_mt19937_new(zend_class_entry *ce)
190 {
191 return &php_random_engine_common_init(ce, &random_engine_mt19937_object_handlers, &php_random_algo_mt19937)->std;
192 }
193
php_random_engine_pcgoneseq128xslrr64_new(zend_class_entry * ce)194 static zend_object *php_random_engine_pcgoneseq128xslrr64_new(zend_class_entry *ce)
195 {
196 return &php_random_engine_common_init(ce, &random_engine_pcgoneseq128xslrr64_object_handlers, &php_random_algo_pcgoneseq128xslrr64)->std;
197 }
198
php_random_engine_xoshiro256starstar_new(zend_class_entry * ce)199 static zend_object *php_random_engine_xoshiro256starstar_new(zend_class_entry *ce)
200 {
201 return &php_random_engine_common_init(ce, &random_engine_xoshiro256starstar_object_handlers, &php_random_algo_xoshiro256starstar)->std;
202 }
203
php_random_engine_secure_new(zend_class_entry * ce)204 static zend_object *php_random_engine_secure_new(zend_class_entry *ce)
205 {
206 return &php_random_engine_common_init(ce, &random_engine_secure_object_handlers, &php_random_algo_secure)->std;
207 }
208
php_random_randomizer_new(zend_class_entry * ce)209 static zend_object *php_random_randomizer_new(zend_class_entry *ce)
210 {
211 php_random_randomizer *randomizer = zend_object_alloc(sizeof(php_random_randomizer), ce);
212
213 zend_object_std_init(&randomizer->std, ce);
214 object_properties_init(&randomizer->std, ce);
215
216 return &randomizer->std;
217 }
218
randomizer_free_obj(zend_object * object)219 static void randomizer_free_obj(zend_object *object) {
220 php_random_randomizer *randomizer = php_random_randomizer_from_obj(object);
221
222 if (randomizer->is_userland_algo) {
223 php_random_status_free(randomizer->status, false);
224 }
225
226 zend_object_std_dtor(&randomizer->std);
227 }
228
php_random_status_alloc(const php_random_algo * algo,const bool persistent)229 PHPAPI php_random_status *php_random_status_alloc(const php_random_algo *algo, const bool persistent)
230 {
231 php_random_status *status = pecalloc(1, sizeof(php_random_status), persistent);
232
233 status->state = algo->state_size > 0 ? pecalloc(1, algo->state_size, persistent) : NULL;
234
235 return status;
236 }
237
php_random_status_copy(const php_random_algo * algo,php_random_status * old_status,php_random_status * new_status)238 PHPAPI php_random_status *php_random_status_copy(const php_random_algo *algo, php_random_status *old_status, php_random_status *new_status)
239 {
240 new_status->state = memcpy(new_status->state, old_status->state, algo->state_size);
241
242 return new_status;
243 }
244
php_random_status_free(php_random_status * status,const bool persistent)245 PHPAPI void php_random_status_free(php_random_status *status, const bool persistent)
246 {
247 if (status != NULL) {
248 pefree(status->state, persistent);
249 }
250
251 pefree(status, persistent);
252 }
253
php_random_engine_common_init(zend_class_entry * ce,zend_object_handlers * handlers,const php_random_algo * algo)254 PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, zend_object_handlers *handlers, const php_random_algo *algo)
255 {
256 php_random_engine *engine = zend_object_alloc(sizeof(php_random_engine), ce);
257
258 zend_object_std_init(&engine->std, ce);
259 object_properties_init(&engine->std, ce);
260
261 engine->algo = algo;
262 engine->status = php_random_status_alloc(engine->algo, false);
263 engine->std.handlers = handlers;
264
265 return engine;
266 }
267
php_random_engine_common_free_object(zend_object * object)268 PHPAPI void php_random_engine_common_free_object(zend_object *object)
269 {
270 php_random_engine *engine = php_random_engine_from_obj(object);
271
272 php_random_status_free(engine->status, false);
273 zend_object_std_dtor(object);
274 }
275
php_random_engine_common_clone_object(zend_object * object)276 PHPAPI zend_object *php_random_engine_common_clone_object(zend_object *object)
277 {
278 php_random_engine *old_engine = php_random_engine_from_obj(object);
279 php_random_engine *new_engine = php_random_engine_from_obj(old_engine->std.ce->create_object(old_engine->std.ce));
280
281 new_engine->algo = old_engine->algo;
282 if (old_engine->status) {
283 new_engine->status = php_random_status_copy(old_engine->algo, old_engine->status, new_engine->status);
284 }
285
286 zend_objects_clone_members(&new_engine->std, &old_engine->std);
287
288 return &new_engine->std;
289 }
290
291 /* {{{ php_random_range */
php_random_range(const php_random_algo * algo,php_random_status * status,zend_long min,zend_long max)292 PHPAPI zend_long php_random_range(const php_random_algo *algo, php_random_status *status, zend_long min, zend_long max)
293 {
294 zend_ulong umax = (zend_ulong) max - (zend_ulong) min;
295
296 if (umax > UINT32_MAX) {
297 return (zend_long) (php_random_range64(algo, status, umax) + min);
298 }
299
300 return (zend_long) (php_random_range32(algo, status, umax) + min);
301 }
302 /* }}} */
303
304 /* {{{ php_random_default_algo */
php_random_default_algo(void)305 PHPAPI const php_random_algo *php_random_default_algo(void)
306 {
307 return &php_random_algo_mt19937;
308 }
309 /* }}} */
310
311 /* {{{ php_random_default_status */
php_random_default_status(void)312 PHPAPI php_random_status *php_random_default_status(void)
313 {
314 php_random_status *status = RANDOM_G(mt19937);
315
316 if (!RANDOM_G(mt19937_seeded)) {
317 php_random_mt19937_seed_default(status->state);
318 RANDOM_G(mt19937_seeded) = true;
319 }
320
321 return status;
322 }
323 /* }}} */
324
325 /* this is read-only, so it's ok */
326 ZEND_SET_ALIGNED(16, static const char hexconvtab[]) = "0123456789abcdef";
327
328 /* {{{ php_random_bin2hex_le */
329 /* stolen from standard/string.c */
php_random_bin2hex_le(const void * ptr,const size_t len)330 PHPAPI zend_string *php_random_bin2hex_le(const void *ptr, const size_t len)
331 {
332 zend_string *str;
333 size_t i;
334
335 str = zend_string_safe_alloc(len, 2 * sizeof(char), 0, 0);
336
337 i = 0;
338 #ifdef WORDS_BIGENDIAN
339 /* force little endian */
340 for (zend_long j = (len - 1); 0 <= j; j--) {
341 #else
342 for (zend_long j = 0; j < len; j++) {
343 #endif
344 ZSTR_VAL(str)[i++] = hexconvtab[((unsigned char *) ptr)[j] >> 4];
345 ZSTR_VAL(str)[i++] = hexconvtab[((unsigned char *) ptr)[j] & 15];
346 }
347 ZSTR_VAL(str)[i] = '\0';
348
349 return str;
350 }
351 /* }}} */
352
353 /* {{{ php_random_hex2bin_le */
354 /* stolen from standard/string.c */
355 PHPAPI bool php_random_hex2bin_le(zend_string *hexstr, void *dest)
356 {
357 size_t len = hexstr->len >> 1;
358 unsigned char *str = (unsigned char *) hexstr->val, c, l, d;
359 unsigned char *ptr = (unsigned char *) dest;
360 int is_letter, i = 0;
361
362 #ifdef WORDS_BIGENDIAN
363 /* force little endian */
364 for (zend_long j = (len - 1); 0 <= j; j--) {
365 #else
366 for (zend_long j = 0; j < len; j++) {
367 #endif
368 c = str[i++];
369 l = c & ~0x20;
370 is_letter = ((uint32_t) ((l - 'A') ^ (l - 'F' - 1))) >> (8 * sizeof(uint32_t) - 1);
371
372 /* basically (c >= '0' && c <= '9') || (l >= 'A' && l <= 'F') */
373 if (EXPECTED((((c ^ '0') - 10) >> (8 * sizeof(uint32_t) - 1)) | is_letter)) {
374 d = (l - 0x10 - 0x27 * is_letter) << 4;
375 } else {
376 return false;
377 }
378 c = str[i++];
379 l = c & ~0x20;
380 is_letter = ((uint32_t) ((l - 'A') ^ (l - 'F' - 1))) >> (8 * sizeof(uint32_t) - 1);
381 if (EXPECTED((((c ^ '0') - 10) >> (8 * sizeof(uint32_t) - 1)) | is_letter)) {
382 d |= l - 0x10 - 0x27 * is_letter;
383 } else {
384 return false;
385 }
386 ptr[j] = d;
387 }
388 return true;
389 }
390 /* }}} */
391
392 /* {{{ php_combined_lcg */
393 PHPAPI double php_combined_lcg(void)
394 {
395 php_random_status *status = RANDOM_G(combined_lcg);
396
397 if (!RANDOM_G(combined_lcg_seeded)) {
398 php_random_combinedlcg_seed_default(status->state);
399 RANDOM_G(combined_lcg_seeded) = true;
400 }
401
402 return php_random_algo_combinedlcg.generate(status).result * 4.656613e-10;
403 }
404 /* }}} */
405
406 /* {{{ php_mt_srand */
407 PHPAPI void php_mt_srand(uint32_t seed)
408 {
409 /* Seed the generator with a simple uint32 */
410 php_random_algo_mt19937.seed(php_random_default_status(), (zend_long) seed);
411 }
412 /* }}} */
413
414 /* {{{ php_mt_rand */
415 PHPAPI uint32_t php_mt_rand(void)
416 {
417 return (uint32_t) php_random_algo_mt19937.generate(php_random_default_status()).result;
418 }
419 /* }}} */
420
421 /* {{{ php_mt_rand_range */
422 PHPAPI zend_long php_mt_rand_range(zend_long min, zend_long max)
423 {
424 return php_random_algo_mt19937.range(php_random_default_status(), min, max);
425 }
426 /* }}} */
427
428 /* {{{ php_mt_rand_common
429 * rand() allows min > max, mt_rand does not */
430 PHPAPI zend_long php_mt_rand_common(zend_long min, zend_long max)
431 {
432 php_random_status *status = php_random_default_status();
433 php_random_status_state_mt19937 *s = status->state;
434
435 if (s->mode == MT_RAND_MT19937) {
436 return php_mt_rand_range(min, max);
437 }
438
439 uint64_t r = php_random_algo_mt19937.generate(php_random_default_status()).result >> 1;
440
441 /* This is an inlined version of the RAND_RANGE_BADSCALING macro that does not invoke UB when encountering
442 * (max - min) > ZEND_LONG_MAX.
443 */
444 zend_ulong offset = (double) ( (double) max - min + 1.0) * (r / (PHP_MT_RAND_MAX + 1.0));
445
446 return (zend_long) (offset + min);
447 }
448 /* }}} */
449
450 /* {{{ php_srand */
451 PHPAPI void php_srand(zend_long seed)
452 {
453 php_mt_srand((uint32_t) seed);
454 }
455 /* }}} */
456
457 /* {{{ php_rand */
458 PHPAPI zend_long php_rand(void)
459 {
460 return php_mt_rand();
461 }
462 /* }}} */
463
464 /* {{{ Returns a value from the combined linear congruential generator */
465 PHP_FUNCTION(lcg_value)
466 {
467 ZEND_PARSE_PARAMETERS_NONE();
468
469 RETURN_DOUBLE(php_combined_lcg());
470 }
471 /* }}} */
472
473 /* {{{ Seeds Mersenne Twister random number generator */
474 PHP_FUNCTION(mt_srand)
475 {
476 zend_long seed = 0;
477 bool seed_is_null = true;
478 zend_long mode = MT_RAND_MT19937;
479 php_random_status *status = RANDOM_G(mt19937);
480 php_random_status_state_mt19937 *state = status->state;
481
482 ZEND_PARSE_PARAMETERS_START(0, 2)
483 Z_PARAM_OPTIONAL
484 Z_PARAM_LONG_OR_NULL(seed, seed_is_null)
485 Z_PARAM_LONG(mode)
486 ZEND_PARSE_PARAMETERS_END();
487
488 state->mode = mode;
489
490 /* Anything that is not MT_RAND_MT19937 was interpreted as MT_RAND_PHP. */
491 if (state->mode != MT_RAND_MT19937) {
492 zend_error(E_DEPRECATED, "The MT_RAND_PHP variant of Mt19937 is deprecated");
493 }
494
495 if (seed_is_null) {
496 php_random_mt19937_seed_default(status->state);
497 } else {
498 php_random_algo_mt19937.seed(status, (uint64_t) seed);
499 }
500 RANDOM_G(mt19937_seeded) = true;
501 }
502 /* }}} */
503
504 /* {{{ Returns a random number from Mersenne Twister */
505 PHP_FUNCTION(mt_rand)
506 {
507 zend_long min, max;
508 int argc = ZEND_NUM_ARGS();
509
510 if (argc == 0) {
511 /* genrand_int31 in mt19937ar.c performs a right shift */
512 RETURN_LONG(php_mt_rand() >> 1);
513 }
514
515 ZEND_PARSE_PARAMETERS_START(2, 2)
516 Z_PARAM_LONG(min)
517 Z_PARAM_LONG(max)
518 ZEND_PARSE_PARAMETERS_END();
519
520 if (UNEXPECTED(max < min)) {
521 zend_argument_value_error(2, "must be greater than or equal to argument #1 ($min)");
522 RETURN_THROWS();
523 }
524
525 RETURN_LONG(php_mt_rand_common(min, max));
526 }
527 /* }}} */
528
529 /* {{{ Returns the maximum value a random number from Mersenne Twister can have */
530 PHP_FUNCTION(mt_getrandmax)
531 {
532 ZEND_PARSE_PARAMETERS_NONE();
533
534 /*
535 * Melo: it could be 2^^32 but we only use 2^^31 to maintain
536 * compatibility with the previous php_rand
537 */
538 RETURN_LONG(PHP_MT_RAND_MAX); /* 2^^31 */
539 }
540 /* }}} */
541
542 /* {{{ Returns a random number from Mersenne Twister */
543 PHP_FUNCTION(rand)
544 {
545 zend_long min, max;
546 int argc = ZEND_NUM_ARGS();
547
548 if (argc == 0) {
549 /* genrand_int31 in mt19937ar.c performs a right shift */
550 RETURN_LONG(php_mt_rand() >> 1);
551 }
552
553 ZEND_PARSE_PARAMETERS_START(2, 2)
554 Z_PARAM_LONG(min)
555 Z_PARAM_LONG(max)
556 ZEND_PARSE_PARAMETERS_END();
557
558 if (max < min) {
559 RETURN_LONG(php_mt_rand_common(max, min));
560 }
561
562 RETURN_LONG(php_mt_rand_common(min, max));
563 }
564 /* }}} */
565
566 /* {{{ Return an arbitrary length of pseudo-random bytes as binary string */
567 PHP_FUNCTION(random_bytes)
568 {
569 zend_long size;
570 zend_string *bytes;
571
572 ZEND_PARSE_PARAMETERS_START(1, 1)
573 Z_PARAM_LONG(size)
574 ZEND_PARSE_PARAMETERS_END();
575
576 if (size < 1) {
577 zend_argument_value_error(1, "must be greater than 0");
578 RETURN_THROWS();
579 }
580
581 bytes = zend_string_alloc(size, 0);
582
583 if (php_random_bytes_throw(ZSTR_VAL(bytes), size) == FAILURE) {
584 zend_string_release_ex(bytes, 0);
585 RETURN_THROWS();
586 }
587
588 ZSTR_VAL(bytes)[size] = '\0';
589
590 RETURN_STR(bytes);
591 }
592 /* }}} */
593
594 /* {{{ Return an arbitrary pseudo-random integer */
595 PHP_FUNCTION(random_int)
596 {
597 zend_long min, max, result;
598
599 ZEND_PARSE_PARAMETERS_START(2, 2)
600 Z_PARAM_LONG(min)
601 Z_PARAM_LONG(max)
602 ZEND_PARSE_PARAMETERS_END();
603
604 if (min > max) {
605 zend_argument_value_error(1, "must be less than or equal to argument #2 ($max)");
606 RETURN_THROWS();
607 }
608
609 if (php_random_int_throw(min, max, &result) == FAILURE) {
610 RETURN_THROWS();
611 }
612
613 RETURN_LONG(result);
614 }
615 /* }}} */
616
617 /* {{{ PHP_GINIT_FUNCTION */
618 static PHP_GINIT_FUNCTION(random)
619 {
620 random_globals->random_fd = -1;
621
622 random_globals->combined_lcg = php_random_status_alloc(&php_random_algo_combinedlcg, true);
623 random_globals->combined_lcg_seeded = false;
624
625 random_globals->mt19937 = php_random_status_alloc(&php_random_algo_mt19937, true);
626 random_globals->mt19937_seeded = false;
627 }
628 /* }}} */
629
630 /* {{{ PHP_GSHUTDOWN_FUNCTION */
631 static PHP_GSHUTDOWN_FUNCTION(random)
632 {
633 if (random_globals->random_fd >= 0) {
634 close(random_globals->random_fd);
635 random_globals->random_fd = -1;
636 }
637
638 php_random_status_free(random_globals->combined_lcg, true);
639 random_globals->combined_lcg = NULL;
640
641 php_random_status_free(random_globals->mt19937, true);
642 random_globals->mt19937 = NULL;
643 }
644 /* }}} */
645
646 /* {{{ PHP_MINIT_FUNCTION */
647 PHP_MINIT_FUNCTION(random)
648 {
649 /* Random\Engine */
650 random_ce_Random_Engine = register_class_Random_Engine();
651
652 /* Random\CryptoSafeEngine */
653 random_ce_Random_CryptoSafeEngine = register_class_Random_CryptoSafeEngine(random_ce_Random_Engine);
654
655 /* Random\RandomError */
656 random_ce_Random_RandomError = register_class_Random_RandomError(zend_ce_error);
657
658 /* Random\BrokenRandomEngineError */
659 random_ce_Random_BrokenRandomEngineError = register_class_Random_BrokenRandomEngineError(random_ce_Random_RandomError);
660
661 /* Random\RandomException */
662 random_ce_Random_RandomException = register_class_Random_RandomException(zend_ce_exception);
663
664 /* Random\Engine\Mt19937 */
665 random_ce_Random_Engine_Mt19937 = register_class_Random_Engine_Mt19937(random_ce_Random_Engine);
666 random_ce_Random_Engine_Mt19937->create_object = php_random_engine_mt19937_new;
667 memcpy(&random_engine_mt19937_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
668 random_engine_mt19937_object_handlers.offset = XtOffsetOf(php_random_engine, std);
669 random_engine_mt19937_object_handlers.free_obj = php_random_engine_common_free_object;
670 random_engine_mt19937_object_handlers.clone_obj = php_random_engine_common_clone_object;
671
672 /* Random\Engine\PcgOnseq128XslRr64 */
673 random_ce_Random_Engine_PcgOneseq128XslRr64 = register_class_Random_Engine_PcgOneseq128XslRr64(random_ce_Random_Engine);
674 random_ce_Random_Engine_PcgOneseq128XslRr64->create_object = php_random_engine_pcgoneseq128xslrr64_new;
675 memcpy(&random_engine_pcgoneseq128xslrr64_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
676 random_engine_pcgoneseq128xslrr64_object_handlers.offset = XtOffsetOf(php_random_engine, std);
677 random_engine_pcgoneseq128xslrr64_object_handlers.free_obj = php_random_engine_common_free_object;
678 random_engine_pcgoneseq128xslrr64_object_handlers.clone_obj = php_random_engine_common_clone_object;
679
680 /* Random\Engine\Xoshiro256StarStar */
681 random_ce_Random_Engine_Xoshiro256StarStar = register_class_Random_Engine_Xoshiro256StarStar(random_ce_Random_Engine);
682 random_ce_Random_Engine_Xoshiro256StarStar->create_object = php_random_engine_xoshiro256starstar_new;
683 memcpy(&random_engine_xoshiro256starstar_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
684 random_engine_xoshiro256starstar_object_handlers.offset = XtOffsetOf(php_random_engine, std);
685 random_engine_xoshiro256starstar_object_handlers.free_obj = php_random_engine_common_free_object;
686 random_engine_xoshiro256starstar_object_handlers.clone_obj = php_random_engine_common_clone_object;
687
688 /* Random\Engine\Secure */
689 random_ce_Random_Engine_Secure = register_class_Random_Engine_Secure(random_ce_Random_CryptoSafeEngine);
690 random_ce_Random_Engine_Secure->create_object = php_random_engine_secure_new;
691 memcpy(&random_engine_secure_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
692 random_engine_secure_object_handlers.offset = XtOffsetOf(php_random_engine, std);
693 random_engine_secure_object_handlers.free_obj = php_random_engine_common_free_object;
694 random_engine_secure_object_handlers.clone_obj = NULL;
695
696 /* Random\Randomizer */
697 random_ce_Random_Randomizer = register_class_Random_Randomizer();
698 random_ce_Random_Randomizer->create_object = php_random_randomizer_new;
699 random_ce_Random_Randomizer->default_object_handlers = &random_randomizer_object_handlers;
700 memcpy(&random_randomizer_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
701 random_randomizer_object_handlers.offset = XtOffsetOf(php_random_randomizer, std);
702 random_randomizer_object_handlers.free_obj = randomizer_free_obj;
703 random_randomizer_object_handlers.clone_obj = NULL;
704
705 /* Random\IntervalBoundary */
706 random_ce_Random_IntervalBoundary = register_class_Random_IntervalBoundary();
707
708 register_random_symbols(module_number);
709
710 return SUCCESS;
711 }
712 /* }}} */
713
714 /* {{{ PHP_RINIT_FUNCTION */
715 PHP_RINIT_FUNCTION(random)
716 {
717 RANDOM_G(combined_lcg_seeded) = false;
718 RANDOM_G(mt19937_seeded) = false;
719
720 return SUCCESS;
721 }
722 /* }}} */
723
724 /* {{{ random_module_entry */
725 zend_module_entry random_module_entry = {
726 STANDARD_MODULE_HEADER,
727 "random", /* Extension name */
728 ext_functions, /* zend_function_entry */
729 PHP_MINIT(random), /* PHP_MINIT - Module initialization */
730 NULL, /* PHP_MSHUTDOWN - Module shutdown */
731 PHP_RINIT(random), /* PHP_RINIT - Request initialization */
732 NULL, /* PHP_RSHUTDOWN - Request shutdown */
733 NULL, /* PHP_MINFO - Module info */
734 PHP_VERSION, /* Version */
735 PHP_MODULE_GLOBALS(random), /* ZTS Module globals */
736 PHP_GINIT(random), /* PHP_GINIT - Global initialization */
737 PHP_GSHUTDOWN(random), /* PHP_GSHUTDOWN - Global shutdown */
738 NULL, /* Post deactivate */
739 STANDARD_MODULE_PROPERTIES_EX
740 };
741 /* }}} */
742