Skip to content

Commit b78222a

Browse files
feature #413 Polyfill the random extension's interfaces and Secure engine (TimWolla, nicolas-grekas)
This PR was merged into the 1.27-dev branch. Discussion ---------- Polyfill the random extension's interfaces and Secure engine Commits ------- ebc6b56 Improve Random polyfill a bit 930fa6c Polyfill the random extension's interfaces and Secure engine
2 parents 011cd09 + ebc6b56 commit b78222a

12 files changed

+265
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# 1.27.0
22

33
* Add PHP 8.3 polyfill for `json_validate()`
4+
* Add polyfill for PHP 8.2's `Random` interfaces, exceptions and `Secure` engine
45
* Fix `IntlDateFormatter::formatObject()` signature
56

67
# 1.26.0

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ Polyfills are provided for:
6565
- the `AllowDynamicProperties` attribute introduced in PHP 8.2;
6666
- the `SensitiveParameter` attribute introduced in PHP 8.2;
6767
- the `SensitiveParameterValue` class introduced in PHP 8.2;
68+
- the `Random\Engine` interface introduced in PHP 8.2;
69+
- the `Random\CryptoSafeEngine` interface introduced in PHP 8.2;
70+
- the `Random\Engine\Secure` class introduced in PHP 8.2 (check [arokettu/random-polyfill](https://packagist.org/packages/arokettu/random-polyfill) for more engines);
6871
- the `json_validate` function introduced in PHP 8.3;
6972

7073
It is strongly recommended to upgrade your PHP version and/or install the missing

src/Php82/NoDynamicProperties.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Polyfill\Php82;
13+
14+
/**
15+
* @internal
16+
*/
17+
trait NoDynamicProperties
18+
{
19+
public function __set(string $name, $value): void
20+
{
21+
throw new \Error('Cannot create dynamic property '.self::class.'::$'.$name);
22+
}
23+
}

src/Php82/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ This component provides features added to PHP 8.2 core:
66
- [`AllowDynamicProperties`](https://wiki.php.net/rfc/deprecate_dynamic_properties)
77
- [`SensitiveParameter`](https://wiki.php.net/rfc/redact_parameters_in_back_traces)
88
- [`SensitiveParameterValue`](https://wiki.php.net/rfc/redact_parameters_in_back_traces)
9+
- [`Random\Engine`](https://wiki.php.net/rfc/rng_extension)
10+
- [`Random\Engine\CryptoSafeEngine`](https://wiki.php.net/rfc/rng_extension)
11+
- [`Random\Engine\Secure`](https://wiki.php.net/rfc/rng_extension) (check [arokettu/random-polyfill](https://packagist.org/packages/arokettu/random-polyfill) for more engines)
912

1013
More information can be found in the
1114
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).

src/Php82/Random/Engine/Secure.php

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Polyfill\Php82\Random\Engine;
13+
14+
use Random\RandomException;
15+
use Symfony\Polyfill\Php82\NoDynamicProperties;
16+
17+
/**
18+
* @author Tim Düsterhus <[email protected]>
19+
* @author Anton Smirnov <[email protected]>
20+
*
21+
* @internal
22+
*/
23+
class Secure
24+
{
25+
use NoDynamicProperties;
26+
27+
public function generate(): string
28+
{
29+
try {
30+
return random_bytes(\PHP_INT_SIZE);
31+
} catch (\Exception $e) {
32+
throw new RandomException($e->getMessage(), $e->getCode(), $e->getPrevious());
33+
}
34+
}
35+
36+
public function __sleep(): array
37+
{
38+
throw new \Exception("Serialization of 'Random\Engine\Secure' is not allowed");
39+
}
40+
41+
public function __wakeup(): void
42+
{
43+
throw new \Exception("Unserialization of 'Random\Engine\Secure' is not allowed");
44+
}
45+
46+
public function __clone()
47+
{
48+
throw new \Error('Trying to clone an uncloneable object of class Random\Engine\Secure');
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Random;
13+
14+
if (\PHP_VERSION_ID < 80200) {
15+
class BrokenRandomEngineError extends RandomError
16+
{
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Random;
13+
14+
if (\PHP_VERSION_ID < 80200) {
15+
interface CryptoSafeEngine extends Engine
16+
{
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Random;
13+
14+
if (\PHP_VERSION_ID < 80200) {
15+
interface Engine
16+
{
17+
public function generate(): string;
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Random\Engine;
13+
14+
use Symfony\Polyfill\Php82 as p;
15+
16+
if (\PHP_VERSION_ID < 80200) {
17+
final class Secure extends p\Random\Engine\Secure implements \Random\CryptoSafeEngine
18+
{
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Random;
13+
14+
use Symfony\Polyfill\Php82\NoDynamicProperties;
15+
16+
if (\PHP_VERSION_ID < 80200) {
17+
class RandomError extends \Error
18+
{
19+
use NoDynamicProperties;
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Random;
13+
14+
use Symfony\Polyfill\Php82\NoDynamicProperties;
15+
16+
if (\PHP_VERSION_ID < 80200) {
17+
class RandomException extends \Exception
18+
{
19+
use NoDynamicProperties;
20+
}
21+
}
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Polyfill\Tests\Php82;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Polyfill\Php82\Random\Engine\Secure as SecureEnginePolyfill;
16+
17+
/**
18+
* @author Tim Düsterhus <[email protected]>
19+
*/
20+
class RandomSecureEngineTest extends TestCase
21+
{
22+
public function secureEngineProvider()
23+
{
24+
yield [new SecureEnginePolyfill()];
25+
yield [new \Random\Engine\Secure()];
26+
}
27+
28+
/**
29+
* @dataProvider secureEngineProvider
30+
*/
31+
public function testGenerateLength($v)
32+
{
33+
$this->assertSame(\PHP_INT_SIZE, \strlen($v->generate()));
34+
}
35+
36+
/**
37+
* @dataProvider secureEngineProvider
38+
*/
39+
public function testCloneIsNotAllowed($v)
40+
{
41+
$this->expectException(\Error::class);
42+
$this->expectExceptionMessage("Trying to clone an uncloneable object of class Random\Engine\Secure");
43+
44+
clone $v;
45+
}
46+
47+
/**
48+
* @dataProvider secureEngineProvider
49+
*/
50+
public function testSerializeIsNotAllowed($v)
51+
{
52+
$this->expectException(\Exception::class);
53+
$this->expectExceptionMessage("Serialization of 'Random\Engine\Secure' is not allowed");
54+
55+
serialize($v);
56+
}
57+
58+
/**
59+
* @dataProvider secureEngineProvider
60+
*/
61+
public function testUnserializeIsNotAllowed($v)
62+
{
63+
$this->expectException(\Exception::class);
64+
$this->expectExceptionMessageMatches("{Unserialization of '.*Random\\\\Engine\\\\Secure' is not allowed}");
65+
66+
unserialize(sprintf('O:%d:"%s":0:{}', \strlen(\get_class($v)), \get_class($v)));
67+
}
68+
}

0 commit comments

Comments
 (0)