Skip to content

Commit fd5d568

Browse files
committed
fix memory leak in Randomizer::getBytes
1 parent e6d5362 commit fd5d568

File tree

2 files changed

+48
-40
lines changed

2 files changed

+48
-40
lines changed

ext/random/random.c

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,13 @@
145145
#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(int32_t)(loBit(v))) & 0x9908b0dfU))
146146
#define twist_php(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(int32_t)(loBit(u))) & 0x9908b0dfU))
147147

148-
#define RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generate_size, rng_unsafe) \
148+
#define RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generate_size, engine_unsafe) \
149149
do { \
150150
bool _unsafe = false; \
151151
RANDOM_ENGINE_GENERATE(algo, state, result, generate_size, &_unsafe); \
152152
if (_unsafe == true) { \
153-
if (rng_unsafe != NULL) { \
154-
*rng_unsafe = true; \
153+
if (engine_unsafe != NULL) { \
154+
*engine_unsafe = true; \
155155
} \
156156
return 0; \
157157
} \
@@ -180,16 +180,16 @@ static zend_object_handlers random_engine_xorshift128plus_object_handlers;
180180
static zend_object_handlers random_engine_xoshiro256starstar_object_handlers;
181181
static zend_object_handlers random_randomizer_object_handlers;
182182

183-
static uint32_t rand_range32(const php_random_engine_algo *algo, void *state, uint32_t umax, bool *rng_unsafe) {
183+
static uint32_t rand_range32(const php_random_engine_algo *algo, void *state, uint32_t umax, bool *engine_unsafe) {
184184
uint32_t result, limit;
185185
size_t generated_size;
186186

187-
RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generated_size, rng_unsafe);
187+
RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generated_size, engine_unsafe);
188188
while (generated_size < sizeof(uint32_t)) {
189189
uint32_t ret = 0;
190190
size_t generate_size;
191191

192-
RANDOM_ENGINE_GENERATE_GUARD(algo, state, ret, generate_size, rng_unsafe);
192+
RANDOM_ENGINE_GENERATE_GUARD(algo, state, ret, generate_size, engine_unsafe);
193193
result = (result << generate_size) | ret;
194194

195195
generated_size += generate_size;
@@ -213,12 +213,12 @@ static uint32_t rand_range32(const php_random_engine_algo *algo, void *state, ui
213213

214214
/* Discard numbers over the limit to avoid modulo bias */
215215
while (UNEXPECTED(result > limit)) {
216-
RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generated_size, rng_unsafe);
216+
RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generated_size, engine_unsafe);
217217
while (generated_size < sizeof(uint32_t)) {
218218
uint32_t ret;
219219
size_t generate_size;
220220

221-
RANDOM_ENGINE_GENERATE_GUARD(algo, state, ret, generate_size, rng_unsafe);
221+
RANDOM_ENGINE_GENERATE_GUARD(algo, state, ret, generate_size, engine_unsafe);
222222

223223
result = (result << generate_size) | ret;
224224

@@ -230,17 +230,17 @@ static uint32_t rand_range32(const php_random_engine_algo *algo, void *state, ui
230230
}
231231

232232
#if ZEND_ULONG_MAX > UINT32_MAX
233-
static uint64_t rand_range64(const php_random_engine_algo *algo, void *state, uint64_t umax, bool *rng_unsafe) {
233+
static uint64_t rand_range64(const php_random_engine_algo *algo, void *state, uint64_t umax, bool *engine_unsafe) {
234234
uint64_t result, limit;
235235
size_t generated_size;
236236

237-
RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generated_size, rng_unsafe);
237+
RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generated_size, engine_unsafe);
238238

239239
while (generated_size < sizeof(uint64_t)) {
240240
uint64_t ret = 0;
241241
size_t generate_size = 0;
242242

243-
RANDOM_ENGINE_GENERATE_GUARD(algo, state, ret, generate_size, rng_unsafe);
243+
RANDOM_ENGINE_GENERATE_GUARD(algo, state, ret, generate_size, engine_unsafe);
244244

245245
result = (result << generate_size) | ret;
246246

@@ -265,13 +265,13 @@ static uint64_t rand_range64(const php_random_engine_algo *algo, void *state, ui
265265

266266
/* Discard numbers over the limit to avoid modulo bias */
267267
while (UNEXPECTED(result > limit)) {
268-
RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generated_size, rng_unsafe);
268+
RANDOM_ENGINE_GENERATE_GUARD(algo, state, result, generated_size, engine_unsafe);
269269

270270
while (generated_size < sizeof(uint64_t)) {
271271
uint64_t ret = 0;
272272
size_t generate_size = 0;
273273

274-
RANDOM_ENGINE_GENERATE_GUARD(algo, state, ret, generate_size, rng_unsafe);
274+
RANDOM_ENGINE_GENERATE_GUARD(algo, state, ret, generate_size, engine_unsafe);
275275

276276
result = (result << generate_size) | ret;
277277

@@ -341,7 +341,7 @@ static inline size_t combinedlcg_dynamic_generate_size(void *state) {
341341
return sizeof(uint32_t);
342342
}
343343

344-
static uint64_t combinedlcg_generate(void *state, bool *rng_unsafe) {
344+
static uint64_t combinedlcg_generate(void *state, bool *engine_unsafe) {
345345
int32_t q, z;
346346
php_random_engine_state_combinedlcg *s = state;
347347

@@ -456,7 +456,7 @@ static inline void pcg64_step(php_random_engine_state_pcg64 *s) {
456456
UINT128_ADD(s->s, s->inc, s->s);
457457
}
458458

459-
static uint64_t pcg64_generate(void *state, bool *rng_unsafe) {
459+
static uint64_t pcg64_generate(void *state, bool *engine_unsafe) {
460460
php_random_engine_state_pcg64 *s = state;
461461
uint64_t result;
462462

@@ -575,7 +575,7 @@ static inline void mersennetwister_reload(php_random_engine_state_mersennetwiste
575575
state->cnt = 0;
576576
}
577577

578-
static uint64_t mersennetwister_generate(void *state, bool *rng_unsafe) {
578+
static uint64_t mersennetwister_generate(void *state, bool *engine_unsafe) {
579579
php_random_engine_state_mersennetwister *s = state;
580580
uint32_t s1;
581581

@@ -689,11 +689,11 @@ static inline size_t secure_dynamic_generate_size(void *state) {
689689
return sizeof(uint64_t);
690690
}
691691

692-
static uint64_t secure_generate(void *state, bool *rng_unsafe) {
692+
static uint64_t secure_generate(void *state, bool *engine_unsafe) {
693693
uint64_t ret = 0;
694694

695-
if (php_random_bytes_silent(&ret, sizeof(uint64_t)) == FAILURE && rng_unsafe != NULL) {
696-
*rng_unsafe = true;
695+
if (php_random_bytes_silent(&ret, sizeof(uint64_t)) == FAILURE && engine_unsafe != NULL) {
696+
*engine_unsafe = true;
697697
}
698698

699699
return ret;
@@ -723,7 +723,7 @@ static inline size_t user_dynamic_generate_size(void *state) {
723723
return s->last_generate_size;
724724
}
725725

726-
static uint64_t user_generate(void *state, bool *rng_unsafe) {
726+
static uint64_t user_generate(void *state, bool *engine_unsafe) {
727727
php_random_engine_state_user *s = state;
728728
uint64_t result = 0;
729729
size_t size;
@@ -747,8 +747,8 @@ static uint64_t user_generate(void *state, bool *rng_unsafe) {
747747
result += ((uint64_t) (unsigned char) Z_STRVAL(retval)[i]) << (8 * i);
748748
}
749749
} else {
750-
if (rng_unsafe != NULL) {
751-
*rng_unsafe = true;
750+
if (engine_unsafe != NULL) {
751+
*engine_unsafe = true;
752752
}
753753
}
754754

@@ -775,7 +775,7 @@ static inline size_t xorshift128plus_dynamic_generate_size(void *state) {
775775
return sizeof(uint64_t);
776776
}
777777

778-
static uint64_t xorshift128plus_generate(void *state, bool *rng_unsafe) {
778+
static uint64_t xorshift128plus_generate(void *state, bool *engine_unsafe) {
779779
php_random_engine_state_xorshift128plus *s = state;
780780
uint64_t s0, s1, r;
781781

@@ -849,7 +849,7 @@ static inline size_t xoshiro256starstar_dynamic_generate_size(void *state) {
849849
return sizeof(uint64_t);
850850
}
851851

852-
static uint64_t xoshiro256starstar_generate(void *state, bool *rng_unsafe) {
852+
static uint64_t xoshiro256starstar_generate(void *state, bool *engine_unsafe) {
853853
php_random_engine_state_xoshiro256starstar *s = state;
854854
const uint64_t result = rotl(s->s[1] * 5, 7) * 9;
855855
const uint64_t t = s->s[1] << 17;
@@ -1219,18 +1219,18 @@ PHPAPI void *php_random_engine_get_default_state(void)
12191219
/* }}} */
12201220

12211221
/* {{{ php_random_engine_range */
1222-
PHPAPI zend_long php_random_engine_range(const php_random_engine_algo *algo, void *state, zend_long min, zend_long max, bool *rng_unsafe)
1222+
PHPAPI zend_long php_random_engine_range(const php_random_engine_algo *algo, void *state, zend_long min, zend_long max, bool *engine_unsafe)
12231223
{
12241224
zend_ulong umax = max - min;
12251225

12261226
#if ZEND_ULONG_MAX > UINT32_MAX
12271227
/* user-land OR 64-bit RNG OR umax over 32-bit */
12281228
if (algo->static_generate_size == 0 || algo->static_generate_size > sizeof(uint32_t) || umax > UINT32_MAX) {
1229-
return (zend_long) rand_range64(algo, state, umax, rng_unsafe) + min;
1229+
return (zend_long) rand_range64(algo, state, umax, engine_unsafe) + min;
12301230
}
12311231
#endif
12321232

1233-
return (zend_long) (rand_range32(algo, state, umax, rng_unsafe) + min);
1233+
return (zend_long) (rand_range32(algo, state, umax, engine_unsafe) + min);
12341234
}
12351235
/* }}} */
12361236

@@ -1422,14 +1422,14 @@ PHP_METHOD(Random_Engine_CombinedLCG, generate)
14221422
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
14231423
uint64_t generated;
14241424
size_t size;
1425-
bool rng_unsafe = false;
1425+
bool engine_unsafe = false;
14261426
zend_string *bytes;
14271427
int i;
14281428

14291429
ZEND_PARSE_PARAMETERS_NONE();
14301430

1431-
RANDOM_ENGINE_GENERATE(engine->algo, engine->state, generated, size, &rng_unsafe);
1432-
if (rng_unsafe) {
1431+
RANDOM_ENGINE_GENERATE(engine->algo, engine->state, generated, size, &engine_unsafe);
1432+
if (engine_unsafe) {
14331433
zend_throw_exception(spl_ce_RuntimeException, "Random number generate failed", 0);
14341434
RETURN_THROWS();
14351435
}
@@ -1791,7 +1791,7 @@ PHP_METHOD(Random_Engine_Xoshiro256StarStar, jump)
17911791
PHP_METHOD(Random_Engine_Xoshiro256StarStar, jumpLong)
17921792
{
17931793
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
1794-
php_random_engine_state_xoshiro256starstar *s = (php_random_engine_state_xoshiro256starstar *) engine->state;
1794+
php_random_engine_state_xoshiro256starstar *s = engine->state;
17951795
static const uint64_t jmp[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 };
17961796
uint64_t s0 = 0, s1 = 0, s2 = 0, s3 = 0;
17971797
int i, j;
@@ -1855,12 +1855,12 @@ PHP_METHOD(Random_Randomizer, getInt)
18551855
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
18561856
zend_long min, max, result;
18571857
int argc = ZEND_NUM_ARGS();
1858-
bool rng_unsafe = false;
1858+
bool engine_unsafe = false;
18591859

18601860
if (argc == 0) {
18611861
// right shift for compatibility
1862-
result = (zend_long) randomizer->algo->generate(randomizer->state, &rng_unsafe);
1863-
if (rng_unsafe) {
1862+
result = (zend_long) randomizer->algo->generate(randomizer->state, &engine_unsafe);
1863+
if (engine_unsafe) {
18641864
zend_throw_exception(spl_ce_RuntimeException, "Random number generate failed", 0);
18651865
RETURN_THROWS();
18661866
}
@@ -1877,8 +1877,8 @@ PHP_METHOD(Random_Randomizer, getInt)
18771877
RETURN_THROWS();
18781878
}
18791879

1880-
result = php_random_engine_range(randomizer->algo, randomizer->state, min, max, &rng_unsafe);
1881-
if (rng_unsafe) {
1880+
result = php_random_engine_range(randomizer->algo, randomizer->state, min, max, &engine_unsafe);
1881+
if (engine_unsafe) {
18821882
zend_throw_exception(spl_ce_RuntimeException, "Random number generate failed", 0);
18831883
RETURN_THROWS();
18841884
}
@@ -1895,7 +1895,7 @@ PHP_METHOD(Random_Randomizer, getBytes)
18951895
zend_long length;
18961896
uint64_t result;
18971897
size_t total_size = 0, required_size, generated_size;
1898-
bool rng_unsafe = false;
1898+
bool engine_unsafe = false;
18991899
int i;
19001900

19011901
ZEND_PARSE_PARAMETERS_START(1, 1)
@@ -1911,8 +1911,9 @@ PHP_METHOD(Random_Randomizer, getBytes)
19111911
required_size = length;
19121912

19131913
while (total_size < required_size) {
1914-
RANDOM_ENGINE_GENERATE(randomizer->algo, randomizer->state, result, generated_size, &rng_unsafe);
1915-
if (rng_unsafe) {
1914+
RANDOM_ENGINE_GENERATE(randomizer->algo, randomizer->state, result, generated_size, &engine_unsafe);
1915+
if (engine_unsafe) {
1916+
zend_string_free(retval);
19161917
zend_throw_exception(spl_ce_RuntimeException, "Random number generate failed", 0);
19171918
RETURN_THROWS();
19181919
}

ext/random/tests/03_randomizer/user_unsafe.phpt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Random: Randomizer: User: RNG unsafe
2+
Random: Randomizer: User: Engine unsafe
33
--FILE--
44
<?php
55

@@ -18,6 +18,12 @@ try {
1818
echo "catched\n";
1919
}
2020

21+
try {
22+
$randomizer->getBytes(1);
23+
} catch (\RuntimeException $e) {
24+
echo "catched\n";
25+
}
26+
2127
try {
2228
$randomizer->shuffleArray(\range(1, 10));
2329
} catch (\RuntimeException $e) {
@@ -35,3 +41,4 @@ try {
3541
catched
3642
catched
3743
catched
44+
catched

0 commit comments

Comments
 (0)