php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
engine_xoshiro256starstar.c
Go to the documentation of this file.
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 | Author: Go Kudo <zeriyoshi@php.net> |
14 | |
15 | Based on code from: David Blackman |
16 | Sebastiano Vigna <vigna@acm.org> |
17 +----------------------------------------------------------------------+
18*/
19
20#ifdef HAVE_CONFIG_H
21# include "config.h"
22#endif
23
24#include "php.h"
25#include "php_random.h"
26#include "php_random_csprng.h"
27
29
30static inline uint64_t splitmix64(uint64_t *seed)
31{
32 uint64_t r;
33
34 r = (*seed += 0x9e3779b97f4a7c15ULL);
35 r = (r ^ (r >> 30)) * 0xbf58476d1ce4e5b9ULL;
36 r = (r ^ (r >> 27)) * 0x94d049bb133111ebULL;
37 return (r ^ (r >> 31));
38}
39
40ZEND_ATTRIBUTE_CONST static inline uint64_t rotl(const uint64_t x, int k)
41{
42 return (x << k) | (x >> (64 - k));
43}
44
45static inline uint64_t generate_state(php_random_status_state_xoshiro256starstar *s)
46{
47 const uint64_t r = rotl(s->state[1] * 5, 7) * 9;
48 const uint64_t t = s->state[1] << 17;
49
50 s->state[2] ^= s->state[0];
51 s->state[3] ^= s->state[1];
52 s->state[1] ^= s->state[2];
53 s->state[0] ^= s->state[3];
54
55 s->state[2] ^= t;
56
57 s->state[3] = rotl(s->state[3], 45);
58
59 return r;
60}
61
62static inline void jump(php_random_status_state_xoshiro256starstar *state, const uint64_t *jmp)
63{
64 uint64_t s0 = 0, s1 = 0, s2 = 0, s3 = 0;
65
66 for (uint32_t i = 0; i < 4; i++) {
67 for (uint32_t j = 0; j < 64; j++) {
68 if (jmp[i] & 1ULL << j) {
69 s0 ^= state->state[0];
70 s1 ^= state->state[1];
71 s2 ^= state->state[2];
72 s3 ^= state->state[3];
73 }
74
75 generate_state(state);
76 }
77 }
78
79 state->state[0] = s0;
80 state->state[1] = s1;
81 state->state[2] = s2;
82 state->state[3] = s3;
83}
84
85PHPAPI inline void php_random_xoshiro256starstar_seed256(php_random_status_state_xoshiro256starstar *state, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3)
86{
87 state->state[0] = s0;
88 state->state[1] = s1;
89 state->state[2] = s2;
90 state->state[3] = s3;
91}
92
94{
95 uint64_t s[4];
96
97 s[0] = splitmix64(&seed);
98 s[1] = splitmix64(&seed);
99 s[2] = splitmix64(&seed);
100 s[3] = splitmix64(&seed);
101
103}
104
105static php_random_result generate(void *state)
106{
107 return (php_random_result){
108 .size = sizeof(uint64_t),
109 .result = generate_state(state),
110 };
111}
112
113static zend_long range(void *state, zend_long min, zend_long max)
114{
117 .state = state,
118 }, min, max);
119}
120
121static bool serialize(void *state, HashTable *data)
122{
124 zval t;
125
126 for (uint32_t i = 0; i < 4; i++) {
127 ZVAL_STR(&t, php_random_bin2hex_le(&s->state[i], sizeof(uint64_t)));
129 }
130
131 return true;
132}
133
134static bool unserialize(void *state, HashTable *data)
135{
137 zval *t;
138
139 /* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */
140 if (zend_hash_num_elements(data) != 4) {
141 return false;
142 }
143
144 for (uint32_t i = 0; i < 4; i++) {
146 if (!t || Z_TYPE_P(t) != IS_STRING || Z_STRLEN_P(t) != (2 * sizeof(uint64_t))) {
147 return false;
148 }
149 if (!php_random_hex2bin_le(Z_STR_P(t), &s->state[i])) {
150 return false;
151 }
152 }
153
154 return true;
155}
156
159 generate,
160 range,
161 serialize,
162 unserialize
163};
164
166{
167 static const uint64_t jmp[] = {0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c};
168 jump(state, jmp);
169}
170
172{
173 static const uint64_t jmp[] = {0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635};
174 jump(state, jmp);
175}
176
177/* {{{ Random\Engine\Xoshiro256StarStar::jump() */
178PHP_METHOD(Random_Engine_Xoshiro256StarStar, jump)
179{
182
184
186}
187/* }}} */
188
189/* {{{ Random\Engine\Xoshiro256StarStar::jumpLong() */
190PHP_METHOD(Random_Engine_Xoshiro256StarStar, jumpLong)
191{
194
196
198}
199/* }}} */
200
201/* {{{ Random\Engine\Xoshiro256StarStar::__construct */
202PHP_METHOD(Random_Engine_Xoshiro256StarStar, __construct)
203{
206 zend_string *str_seed = NULL;
207 zend_long int_seed = 0;
208 bool seed_is_null = true;
209
212 Z_PARAM_STR_OR_LONG_OR_NULL(str_seed, int_seed, seed_is_null);
214
215 if (seed_is_null) {
216 uint64_t t[4];
217
218 do {
219 if (php_random_bytes_throw(&t, sizeof(t)) == FAILURE) {
220 zend_throw_exception(random_ce_Random_RandomException, "Failed to generate a random seed", 0);
222 }
223 } while (UNEXPECTED(t[0] == 0 && t[1] == 0 && t[2] == 0 && t[3] == 0));
224
225 php_random_xoshiro256starstar_seed256(state, t[0], t[1], t[2], t[3]);
226 } else {
227 if (str_seed) {
228 /* char (byte: 8 bit) * 32 = 256 bits */
229 if (ZSTR_LEN(str_seed) == 32) {
230 uint64_t t[4];
231
232 /* Endianness safe copy */
233 for (uint32_t i = 0; i < 4; i++) {
234 t[i] = 0;
235 for (uint32_t j = 0; j < 8; j++) {
236 t[i] += ((uint64_t) (unsigned char) ZSTR_VAL(str_seed)[(i * 8) + j]) << (j * 8);
237 }
238 }
239
240 if (UNEXPECTED(t[0] == 0 && t[1] == 0 && t[2] == 0 && t[3] == 0)) {
241 zend_argument_value_error(1, "must not consist entirely of NUL bytes");
243 }
244
245 php_random_xoshiro256starstar_seed256(state, t[0], t[1], t[2], t[3]);
246 } else {
247 zend_argument_value_error(1, "must be a 32 byte (256 bit) string");
249 }
250 } else {
251 php_random_xoshiro256starstar_seed64(state, (uint64_t) int_seed);
252 }
253 }
254}
255/* }}} */
char s[4]
Definition cdf.c:77
PHPAPI void php_random_xoshiro256starstar_seed64(php_random_status_state_xoshiro256starstar *state, uint64_t seed)
PHPAPI void php_random_xoshiro256starstar_jump_long(php_random_status_state_xoshiro256starstar *state)
PHPAPI void php_random_xoshiro256starstar_jump(php_random_status_state_xoshiro256starstar *state)
PHPAPI const php_random_algo php_random_algo_xoshiro256starstar
PHPAPI void php_random_xoshiro256starstar_seed256(php_random_status_state_xoshiro256starstar *state, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3)
#define max(a, b)
Definition exif.c:60
#define NULL
Definition gdcache.h:45
again j
#define PHP_METHOD
Definition php.h:365
#define PHPAPI
Definition php.h:71
#define min(a, b)
PHPAPI zend_string * php_random_bin2hex_le(const void *ptr, const size_t len)
Definition random.c:332
PHPAPI bool php_random_hex2bin_le(zend_string *hexstr, void *dest)
Definition random.c:358
struct _php_random_algo_with_state php_random_algo_with_state
PHPAPI zend_class_entry * random_ce_Random_RandomException
#define Z_RANDOM_ENGINE_P(zval)
Definition php_random.h:147
PHPAPI zend_long php_random_range(php_random_algo_with_state engine, zend_long min, zend_long max)
Definition random.c:293
struct _php_random_algo php_random_algo
struct _php_random_status_state_xoshiro256starstar php_random_status_state_xoshiro256starstar
struct _php_random_result php_random_result
zend_constant * data
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define ZEND_PARSE_PARAMETERS_NONE()
Definition zend_API.h:1623
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define Z_PARAM_STR_OR_LONG_OR_NULL(dest_str, dest_long, is_null)
Definition zend_API.h:2168
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define RETURN_THROWS()
Definition zend_API.h:1060
#define ZEND_THIS
Definition zend_API.h:523
struct _zval_struct zval
ZEND_API ZEND_COLD zend_object * zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code)
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData)
Definition zend_hash.c:1224
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
#define ZEND_ATTRIBUTE_CONST
#define UNEXPECTED(condition)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZVAL_STR(z, s)
#define IS_STRING
Definition zend_types.h:606
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
@ FAILURE
Definition zend_types.h:61
bool result