summaryrefslogtreecommitdiff
path: root/execute_rnd.inc.c
diff options
context:
space:
mode:
authorBen Fuhrmannek2016-02-19 11:30:08 +0100
committerBen Fuhrmannek2016-02-19 11:33:55 +0100
commit123907cdea68a7f8a58437ffe5cafd02e4d60aaf (patch)
tree6c801e046cfc48e8970a0ed7d50b029da50288aa /execute_rnd.inc.c
parent477b70127027407a7957690f24d5f857ca311de9 (diff)
basic executor support - ported from suhosin 0.9.39
Diffstat (limited to 'execute_rnd.inc.c')
-rw-r--r--execute_rnd.inc.c385
1 files changed, 385 insertions, 0 deletions
diff --git a/execute_rnd.inc.c b/execute_rnd.inc.c
new file mode 100644
index 0000000..c09c467
--- /dev/null
+++ b/execute_rnd.inc.c
@@ -0,0 +1,385 @@
1/* MT RAND FUNCTIONS */
2
3/*
4 The following php_mt_...() functions are based on a C++ class MTRand by
5 Richard J. Wagner. For more information see the web page at
6 http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html
7
8 Mersenne Twister random number generator -- a C++ class MTRand
9 Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
10 Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
11
12 The Mersenne Twister is an algorithm for generating random numbers. It
13 was designed with consideration of the flaws in various other generators.
14 The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
15 are far greater. The generator is also fast; it avoids multiplication and
16 division, and it benefits from caches and pipelines. For more information
17 see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
18
19 Reference
20 M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
21 Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
22 Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
23
24 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
25 Copyright (C) 2000 - 2003, Richard J. Wagner
26 All rights reserved.
27
28 Redistribution and use in source and binary forms, with or without
29 modification, are permitted provided that the following conditions
30 are met:
31
32 1. Redistributions of source code must retain the above copyright
33 notice, this list of conditions and the following disclaimer.
34
35 2. Redistributions in binary form must reproduce the above copyright
36 notice, this list of conditions and the following disclaimer in the
37 documentation and/or other materials provided with the distribution.
38
39 3. The names of its contributors may not be used to endorse or promote
40 products derived from this software without specific prior written
41 permission.
42
43 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
47 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
48 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
51 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
52 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
53 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54
55 The original code included the following notice:
56
57 When you use this, send an email to: matumoto@math.keio.ac.jp
58 with an appropriate reference to your work.
59
60 It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
61 when you write.
62*/
63
64#define N 624 /* length of state vector */
65#define M (397) /* a period parameter */
66#define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */
67#define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */
68#define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */
69#define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */
70
71#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(v))) & 0x9908b0dfU))
72
73/* {{{ php_mt_initialize
74 */
75static inline void suhosin_mt_initialize(php_uint32 seed, php_uint32 *state)
76{
77 /* Initialize generator state with seed
78 See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
79 In previous versions, most significant bits (MSBs) of the seed affect
80 only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. */
81
82 register php_uint32 *s = state;
83 register php_uint32 *r = state;
84 register int i = 1;
85
86 *s++ = seed & 0xffffffffU;
87 for( ; i < N; ++i ) {
88 *s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU;
89 r++;
90 }
91}
92/* }}} */
93
94static inline void suhosin_mt_init_by_array(php_uint32 *key, int keylen, php_uint32 *state)
95{
96 int i, j, k;
97 suhosin_mt_initialize(19650218U, state);
98 i = 1; j = 0;
99 k = (N > keylen ? N : keylen);
100 for (; k; k--) {
101 state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525U)) + key[j] + j;
102 i++; j = (j+1) % keylen;
103 if (i >= N) { state[0] = state[N-1]; i=1; }
104 }
105 for (k=N-1; k; k--) {
106 state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941U)) - i;
107 i++;
108 if (i >= N) { state[0] = state[N-1]; i=1; }
109 }
110 state[0] = 0x80000000U;
111}
112/* }}} */
113
114
115/* {{{ suhosin_mt_reload
116 */
117static inline void suhosin_mt_reload(php_uint32 *state, php_uint32 **next, int *left)
118{
119 /* Generate N new values in state
120 Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) */
121
122 register php_uint32 *p = state;
123 register int i;
124
125 for (i = N - M; i--; ++p)
126 *p = twist(p[M], p[0], p[1]);
127 for (i = M; --i; ++p)
128 *p = twist(p[M-N], p[0], p[1]);
129 *p = twist(p[M-N], p[0], state[0]);
130 *left = N;
131 *next = state;
132}
133/* }}} */
134
135/* {{{ suhosin_mt_srand
136 */
137static void suhosin_mt_srand(php_uint32 seed TSRMLS_DC)
138{
139 /* Seed the generator with a simple uint32 */
140 suhosin_mt_initialize(seed, SUHOSIN7_G(mt_state));
141 suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left));
142
143 /* Seed only once */
144 SUHOSIN7_G(mt_is_seeded) = 1;
145}
146/* }}} */
147
148/* {{{ suhosin_mt_rand
149 */
150static php_uint32 suhosin_mt_rand(TSRMLS_D)
151{
152 /* Pull a 32-bit integer from the generator state
153 Every other access function simply transforms the numbers extracted here */
154
155 register php_uint32 s1;
156
157 if (SUHOSIN7_G(mt_left) == 0) {
158 suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left));
159 }
160 --SUHOSIN7_G(mt_left);
161
162 s1 = *SUHOSIN7_G(mt_next)++;
163 s1 ^= (s1 >> 11);
164 s1 ^= (s1 << 7) & 0x9d2c5680U;
165 s1 ^= (s1 << 15) & 0xefc60000U;
166 return ( s1 ^ (s1 >> 18) );
167}
168/* }}} */
169
170/* {{{ SUHOSIN7_Gen_entropy
171 */
172static void SUHOSIN7_Gen_entropy(php_uint32 *entropybuf TSRMLS_DC)
173{
174 php_uint32 seedbuf[20];
175 /* On a modern OS code, stack and heap base are randomized */
176 unsigned long code_value = (unsigned long)SUHOSIN7_Gen_entropy;
177 unsigned long stack_value = (unsigned long)&code_value;
178 unsigned long heap_value = (unsigned long)SUHOSIN7_G(r_state);
179 suhosin_SHA256_CTX context;
180 int fd;
181
182 code_value ^= code_value >> 32;
183 stack_value ^= stack_value >> 32;
184 heap_value ^= heap_value >> 32;
185
186 seedbuf[0] = code_value;
187 seedbuf[1] = stack_value;
188 seedbuf[2] = heap_value;
189 seedbuf[3] = time(0);
190#ifdef PHP_WIN32
191 seedbuf[4] = GetCurrentProcessId();
192#else
193 seedbuf[4] = getpid();
194#endif
195 seedbuf[5] = (php_uint32) 0x7fffffff * php_combined_lcg(TSRMLS_C);
196
197#ifndef PHP_WIN32
198 fd = VCWD_OPEN("/dev/urandom", O_RDONLY);
199 if (fd >= 0) {
200 /* ignore error case - if urandom doesn't give us any/enough random bytes */
201 read(fd, &seedbuf[6], 8 * sizeof(php_uint32));
202 close(fd);
203 }
204#else
205 /* we have to live with the possibility that this call fails */
206 php_win32_get_random_bytes((unsigned char*)&seedbuf[6], 8 * sizeof(php_uint32));
207#endif
208
209 suhosin_SHA256Init(&context);
210 /* to our friends from Debian: yes this will add unitialized stack values to the entropy DO NOT REMOVE */
211 suhosin_SHA256Update(&context, (void *) seedbuf, sizeof(seedbuf));
212 if (SUHOSIN7_G(seedingkey) != NULL && *SUHOSIN7_G(seedingkey) != 0) {
213 suhosin_SHA256Update(&context, (unsigned char*)SUHOSIN7_G(seedingkey), strlen(SUHOSIN7_G(seedingkey)));
214 }
215 suhosin_SHA256Final((void *)entropybuf, &context);
216}
217/* }}} */
218
219
220/* {{{ suhosin_srand_auto
221 */
222static void suhosin_srand_auto(TSRMLS_D)
223{
224 php_uint32 seed[8];
225 SUHOSIN7_Gen_entropy(&seed[0] TSRMLS_CC);
226
227 suhosin_mt_init_by_array(seed, 8, SUHOSIN7_G(r_state));
228 suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left));
229
230 /* Seed only once */
231 SUHOSIN7_G(r_is_seeded) = 1;
232}
233/* }}} */
234
235/* {{{ suhosin_mt_srand_auto
236 */
237static void suhosin_mt_srand_auto(TSRMLS_D)
238{
239 php_uint32 seed[8];
240 SUHOSIN7_Gen_entropy(&seed[0] TSRMLS_CC);
241
242 suhosin_mt_init_by_array(seed, 8, SUHOSIN7_G(mt_state));
243 suhosin_mt_reload(SUHOSIN7_G(mt_state), &SUHOSIN7_G(mt_next), &SUHOSIN7_G(mt_left));
244
245 /* Seed only once */
246 SUHOSIN7_G(mt_is_seeded) = 1;
247}
248/* }}} */
249
250
251/* {{{ suhosin_srand
252 */
253static void suhosin_srand(php_uint32 seed TSRMLS_DC)
254{
255 /* Seed the generator with a simple uint32 */
256 suhosin_mt_initialize(seed+0x12345, SUHOSIN7_G(r_state));
257 suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left));
258
259 /* Seed only once */
260 SUHOSIN7_G(r_is_seeded) = 1;
261}
262/* }}} */
263
264/* {{{ suhosin_mt_rand
265 */
266static php_uint32 suhosin_rand(TSRMLS_D)
267{
268 /* Pull a 32-bit integer from the generator state
269 Every other access function simply transforms the numbers extracted here */
270
271 register php_uint32 s1;
272
273 if (SUHOSIN7_G(r_left) == 0) {
274 suhosin_mt_reload(SUHOSIN7_G(r_state), &SUHOSIN7_G(r_next), &SUHOSIN7_G(r_left));
275 }
276 --SUHOSIN7_G(r_left);
277
278 s1 = *SUHOSIN7_G(r_next)++;
279 s1 ^= (s1 >> 11);
280 s1 ^= (s1 << 7) & 0x9d2c5680U;
281 s1 ^= (s1 << 15) & 0xefc60000U;
282 return ( s1 ^ (s1 >> 18) );
283}
284/* }}} */
285
286static int ih_srand(IH_HANDLER_PARAMS)
287{
288 int argc = ZEND_NUM_ARGS();
289 long seed;
290
291 if (SUHOSIN7_G(srand_ignore)) {
292 SUHOSIN7_G(r_is_seeded) = 0;
293 return 1;
294 }
295
296 if (zend_parse_parameters(argc TSRMLS_CC, "|l", &seed) == FAILURE) {
297 return 1;
298 }
299
300 if (argc) {
301 suhosin_srand(seed TSRMLS_CC);
302 } else {
303 suhosin_srand_auto(TSRMLS_C);
304 }
305 return (1);
306}
307
308static int ih_mt_srand(IH_HANDLER_PARAMS)
309{
310 int argc = ZEND_NUM_ARGS();
311 long seed;
312
313 if (SUHOSIN7_G(mt_srand_ignore)) {
314 SUHOSIN7_G(mt_is_seeded) = 0;
315 return 1;
316 }
317
318 if (zend_parse_parameters(argc TSRMLS_CC, "|l", &seed) == FAILURE) {
319 return 1;
320 }
321
322 if (argc) {
323 suhosin_mt_srand(seed TSRMLS_CC);
324 } else {
325 suhosin_mt_srand_auto(TSRMLS_C);
326 }
327 return 1;
328}
329
330static int ih_mt_rand(IH_HANDLER_PARAMS)
331{
332 int argc = ZEND_NUM_ARGS();
333 long min;
334 long max;
335 long number;
336
337 if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE) {
338 return (1);
339 }
340
341 if (!SUHOSIN7_G(mt_is_seeded)) {
342 suhosin_mt_srand_auto(TSRMLS_C);
343 }
344
345 number = (long) (suhosin_mt_rand(TSRMLS_C) >> 1);
346 if (argc == 2) {
347 RAND_RANGE(number, min, max, PHP_MT_RAND_MAX);
348 }
349
350 RETVAL_LONG(number);
351 return (1);
352}
353
354static int ih_rand(IH_HANDLER_PARAMS)
355{
356 int argc = ZEND_NUM_ARGS();
357 long min;
358 long max;
359 long number;
360
361 if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE) {
362 return (1);
363 }
364
365 if (!SUHOSIN7_G(r_is_seeded)) {
366 suhosin_srand_auto(TSRMLS_C);
367 }
368
369 number = (long) (suhosin_rand(TSRMLS_C) >> 1);
370 if (argc == 2) {
371 RAND_RANGE(number, min, max, PHP_MT_RAND_MAX);
372 }
373
374 RETVAL_LONG(number);
375 return (1);
376}
377
378static int ih_getrandmax(IH_HANDLER_PARAMS)
379{
380 if (zend_parse_parameters_none() == FAILURE) {
381 return(0);
382 }
383 RETVAL_LONG(PHP_MT_RAND_MAX);
384 return (1);
385}