Skip to content

Commit b83a8d5

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3: Fix reference type confusion and leak in user random engine
2 parents b2d107d + 75cea65 commit b83a8d5

File tree

4 files changed

+42
-3
lines changed

4 files changed

+42
-3
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ PHP NEWS
3333
. Fix warning not being emitted when failure to cancel a query with
3434
pg_cancel_query(). (Girgias)
3535

36+
- Random:
37+
. Fix reference type confusion and leak in user random engine.
38+
(nielsdos, timwolla)
39+
3640
- Readline:
3741
. Fix memory leak when calloc() fails in php_readline_completion_cb().
3842
(nielsdos)

ext/random/engine_user.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static php_random_result generate(void *state)
2727
uint64_t result = 0;
2828
size_t size;
2929
zval retval;
30+
zend_string *zstr;
3031

3132
zend_call_known_instance_method_with_0_params(s->generate_method, s->object, &retval);
3233

@@ -37,7 +38,14 @@ static php_random_result generate(void *state)
3738
};
3839
}
3940

40-
size = Z_STRLEN(retval);
41+
if (UNEXPECTED(Z_ISREF(retval))) {
42+
zstr = Z_STR_P(Z_REFVAL(retval));
43+
} else {
44+
zstr = Z_STR(retval);
45+
}
46+
47+
/* Store generated size in a state */
48+
size = ZSTR_LEN(zstr);
4149

4250
/* Guard for over 64-bit results */
4351
if (size > sizeof(uint64_t)) {
@@ -47,10 +55,11 @@ static php_random_result generate(void *state)
4755
if (size > 0) {
4856
/* Endianness safe copy */
4957
for (size_t i = 0; i < size; i++) {
50-
result += ((uint64_t) (unsigned char) Z_STRVAL(retval)[i]) << (8 * i);
58+
result += ((uint64_t) (unsigned char) ZSTR_VAL(zstr)[i]) << (8 * i);
5159
}
5260
} else {
5361
zend_throw_error(random_ce_Random_BrokenRandomEngineError, "A random engine must return a non-empty string");
62+
zval_ptr_dtor(&retval);
5463
return (php_random_result){
5564
.size = sizeof(uint64_t),
5665
.result = 0,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Random: Engine: User: Returning by reference works
3+
--FILE--
4+
<?php
5+
6+
use Random\Engine;
7+
use Random\Randomizer;
8+
9+
final class ReferenceEngine implements Engine
10+
{
11+
private $field = 'abcdef';
12+
13+
public function &generate(): string
14+
{
15+
return $this->field;
16+
}
17+
}
18+
19+
$randomizer = new Randomizer(new ReferenceEngine());
20+
21+
var_dump($randomizer->getBytes(64));
22+
23+
?>
24+
--EXPECT--
25+
string(64) "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ final class EmptyStringEngine implements Engine
1010
{
1111
public function generate(): string
1212
{
13-
return '';
13+
// Create a non-interned empty string.
14+
return preg_replace('/./', '', random_bytes(4));
1415
}
1516
}
1617

0 commit comments

Comments
 (0)