Skip to content

Commit c2ea950

Browse files
committed
Remove ext/random dependency
1 parent 5c29ad5 commit c2ea950

File tree

10 files changed

+414
-57
lines changed

10 files changed

+414
-57
lines changed

Zend/zend.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ ZEND_API char *(*zend_getenv)(const char *name, size_t name_len);
9494
ZEND_API zend_string *(*zend_resolve_path)(zend_string *filename);
9595
ZEND_API zend_result (*zend_post_startup_cb)(void) = NULL;
9696
ZEND_API void (*zend_post_shutdown_cb)(void) = NULL;
97+
ZEND_API zend_result (*zend_os_csprng_random_bytes)(void *bytes, size_t size, char *errstr, size_t errstr_size) = NULL;
9798

9899
/* This callback must be signal handler safe! */
99100
void (*zend_on_timeout)(int seconds);
@@ -912,6 +913,10 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */
912913
php_win32_cp_set_by_id(65001);
913914
#endif
914915

916+
/* Set up early utility functions. zend_mm depends on
917+
* zend_os_csprng_random_bytes */
918+
zend_os_csprng_random_bytes = utility_functions->os_csprng_randomn_bytes_function;
919+
915920
start_memory_manager();
916921

917922
virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */

Zend/zend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ typedef struct _zend_utility_functions {
248248
void (*printf_to_smart_str_function)(smart_str *buf, const char *format, va_list ap);
249249
char *(*getenv_function)(const char *name, size_t name_len);
250250
zend_string *(*resolve_path_function)(zend_string *filename);
251+
zend_result (*os_csprng_randomn_bytes_function)(void *bytes, size_t size, char *errstr, size_t errstr_size);
251252
} zend_utility_functions;
252253

253254
typedef struct _zend_utility_values {
@@ -340,6 +341,7 @@ extern void (*zend_printf_to_smart_string)(smart_string *buf, const char *format
340341
extern void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap);
341342
extern ZEND_API char *(*zend_getenv)(const char *name, size_t name_len);
342343
extern ZEND_API zend_string *(*zend_resolve_path)(zend_string *filename);
344+
extern ZEND_API zend_result (*zend_os_csprng_random_bytes)(void *bytes, size_t size, char *errstr, size_t errstr_size);
343345

344346
/* These two callbacks are especially for opcache */
345347
extern ZEND_API zend_result (*zend_post_startup_cb)(void);

Zend/zend_alloc.c

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,12 @@
5454
#include "zend.h"
5555
#include "zend_alloc.h"
5656
#include "zend_globals.h"
57+
#include "zend_hrtime.h"
5758
#include "zend_operators.h"
5859
#include "zend_multiply.h"
5960
#include "zend_bitset.h"
6061
#include "zend_mmap.h"
6162
#include "zend_portability.h"
62-
#include "ext/random/php_random_csprng.h"
63-
#include "ext/random/php_random.h"
6463
#include <signal.h>
6564

6665
#ifdef HAVE_UNISTD_H
@@ -248,6 +247,10 @@ typedef struct _zend_mm_huge_list zend_mm_huge_list;
248247

249248
static bool zend_mm_use_huge_pages = false;
250249

250+
typedef struct _zend_mm_rand_state {
251+
uint32_t state[4];
252+
} zend_mm_rand_state;
253+
251254
/*
252255
* Memory is retrieved from OS by chunks of fixed size 2MB.
253256
* Inside chunk it's managed by pages of fixed size 4096B.
@@ -323,7 +326,7 @@ struct _zend_mm_heap {
323326
HashTable *tracked_allocs;
324327
#endif
325328
pid_t pid;
326-
php_random_status_state_xoshiro256starstar random_state;
329+
zend_mm_rand_state rand_state;
327330
};
328331

329332
struct _zend_mm_chunk {
@@ -2024,30 +2027,105 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE
20242027
#endif
20252028
}
20262029

2030+
/********/
2031+
/* Rand */
2032+
/********/
2033+
2034+
/* Xoshiro256** PRNG based on implementation from Go Kudo in
2035+
* ext/random/engine_xoshiro256starstar.c, based on code from David Blackman,
2036+
* Sebastiano Vigna. */
2037+
2038+
static inline uint64_t splitmix64(uint64_t *seed)
2039+
{
2040+
uint64_t r;
2041+
2042+
r = (*seed += 0x9e3779b97f4a7c15ULL);
2043+
r = (r ^ (r >> 30)) * 0xbf58476d1ce4e5b9ULL;
2044+
r = (r ^ (r >> 27)) * 0x94d049bb133111ebULL;
2045+
return (r ^ (r >> 31));
2046+
}
2047+
2048+
ZEND_ATTRIBUTE_CONST static inline uint64_t rotl(const uint64_t x, int k)
2049+
{
2050+
return (x << k) | (x >> (64 - k));
2051+
}
2052+
2053+
static inline uint64_t zend_mm_rand_generate(zend_mm_rand_state *s)
2054+
{
2055+
const uint64_t r = rotl(s->state[1] * 5, 7) * 9;
2056+
const uint64_t t = s->state[1] << 17;
2057+
2058+
s->state[2] ^= s->state[0];
2059+
s->state[3] ^= s->state[1];
2060+
s->state[1] ^= s->state[2];
2061+
s->state[0] ^= s->state[3];
2062+
2063+
s->state[2] ^= t;
2064+
2065+
s->state[3] = rotl(s->state[3], 45);
2066+
2067+
return r;
2068+
}
2069+
2070+
static inline void zend_mm_rand_seed256(zend_mm_rand_state *state, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3)
2071+
{
2072+
state->state[0] = s0;
2073+
state->state[1] = s1;
2074+
state->state[2] = s2;
2075+
state->state[3] = s3;
2076+
}
2077+
2078+
static inline void zend_mm_rand_seed64(zend_mm_rand_state *state, uint64_t seed)
2079+
{
2080+
uint64_t s[4];
2081+
2082+
s[0] = splitmix64(&seed);
2083+
s[1] = splitmix64(&seed);
2084+
s[2] = splitmix64(&seed);
2085+
s[3] = splitmix64(&seed);
2086+
2087+
zend_mm_rand_seed256(state, s[0], s[1], s[2], s[3]);
2088+
}
2089+
20272090
/******************/
20282091
/* Initialization */
20292092
/******************/
20302093

20312094
static zend_result zend_mm_refresh_key(zend_mm_heap *heap)
20322095
{
2033-
php_random_result result = php_random_algo_xoshiro256starstar.generate(&heap->random_state);
2034-
ZEND_ASSERT(result.size == sizeof(uint64_t));
2035-
heap->shadow_key = (uintptr_t) result.result;
2096+
heap->shadow_key = (uintptr_t) zend_mm_rand_generate(&heap->rand_state);
2097+
20362098
return SUCCESS;
20372099
}
20382100

20392101
static zend_result zend_mm_init_key(zend_mm_heap *heap)
20402102
{
20412103
uint64_t seed[4];
2042-
if (php_random_bytes_silent(&seed, sizeof(seed)) != SUCCESS) {
2043-
for (int i = 0; i < sizeof(seed)/sizeof(seed[0]); i++) {
2044-
seed[i] = php_random_generate_fallback_seed();
2045-
}
2104+
char errstr[128];
2105+
if (zend_os_csprng_random_bytes(&seed, sizeof(seed), errstr, sizeof(errstr)) == SUCCESS) {
2106+
zend_mm_rand_seed256(&heap->rand_state,
2107+
seed[0], seed[1], seed[2], seed[3]);
2108+
} else {
2109+
/* Fallback to weak seed generation */
2110+
#if ZEND_MM_ERROR
2111+
fprintf(stderr, "Could not generate secure random seed: %s\n", errstr);
2112+
#endif
2113+
zend_hrtime_t nanotime = zend_hrtime();
2114+
uint64_t v = 0;
2115+
v ^= (uint64_t) nanotime;
2116+
splitmix64(&v);
2117+
v ^= (uint64_t) getpid();
2118+
splitmix64(&v);
2119+
#ifdef ZTS
2120+
THREAD_T tid = tsrm_thread_id();
2121+
uint64_t tmp = 0;
2122+
memcpy(&tmp, tid, MIN(sizeof(tmp), sizeof(tid)));
2123+
v ^= tmp;
2124+
splitmix64(&v);
2125+
#endif
2126+
zend_mm_rand_seed64(&heap->rand_state, v);
20462127
}
20472128

2048-
php_random_xoshiro256starstar_seed256(&heap->random_state,
2049-
seed[0], seed[1], seed[2], seed[3]);
2050-
20512129
return zend_mm_refresh_key(heap);
20522130
}
20532131

Zend/zend_atomic.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,56 @@
2020
* is also where the code will go.
2121
*/
2222

23-
/* Defined for FFI users; everyone else use ZEND_ATOMIC_BOOL_INIT.
23+
/* Defined for FFI users; everyone else use ZEND_ATOMIC_*_INIT.
2424
* This is NOT ATOMIC as it is meant for initialization.
2525
*/
2626
ZEND_API void zend_atomic_bool_init(zend_atomic_bool *obj, bool desired) {
2727
ZEND_ATOMIC_BOOL_INIT(obj, desired);
2828
}
2929

30+
ZEND_API void zend_atomic_int_init(zend_atomic_int *obj, int desired) {
31+
ZEND_ATOMIC_INT_INIT(obj, desired);
32+
}
33+
3034
ZEND_API bool zend_atomic_bool_exchange(zend_atomic_bool *obj, bool desired) {
3135
return zend_atomic_bool_exchange_ex(obj, desired);
3236
}
3337

38+
ZEND_API int zend_atomic_int_exchange(zend_atomic_int *obj, int desired) {
39+
return zend_atomic_int_exchange_ex(obj, desired);
40+
}
41+
42+
ZEND_API bool zend_atomic_bool_compare_exchange(zend_atomic_bool *obj, bool *expected, bool desired)
43+
{
44+
return zend_atomic_bool_compare_exchange_ex(obj, expected, desired);
45+
}
46+
47+
ZEND_API bool zend_atomic_int_compare_exchange(zend_atomic_int *obj, int *expected, int desired)
48+
{
49+
return zend_atomic_int_compare_exchange_ex(obj, expected, desired);
50+
}
51+
3452
ZEND_API void zend_atomic_bool_store(zend_atomic_bool *obj, bool desired) {
3553
zend_atomic_bool_store_ex(obj, desired);
3654
}
3755

56+
ZEND_API void zend_atomic_int_store(zend_atomic_int *obj, int desired) {
57+
zend_atomic_int_store_ex(obj, desired);
58+
}
59+
3860
#if defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS)
3961
/* On these platforms it is non-const due to underlying APIs. */
4062
ZEND_API bool zend_atomic_bool_load(zend_atomic_bool *obj) {
4163
return zend_atomic_bool_load_ex(obj);
4264
}
65+
ZEND_API int zend_atomic_int_load(zend_atomic_int *obj) {
66+
return zend_atomic_int_load_ex(obj);
67+
}
4368
#else
4469
ZEND_API bool zend_atomic_bool_load(const zend_atomic_bool *obj) {
4570
return zend_atomic_bool_load_ex(obj);
4671
}
72+
ZEND_API int zend_atomic_int_load(const zend_atomic_int *obj) {
73+
return zend_atomic_int_load_ex(obj);
74+
}
4775
#endif

0 commit comments

Comments
 (0)