Commit graph

61 commits

Author SHA1 Message Date
Tim Düsterhus
6910167c48
random: Remove engine_combinedlcg.c (#15216)
The standalone engine cannot be usefully used for any other purpose. Remove it
and inline the implementation into the `php_combined_lcg()` function.
2024-08-04 18:26:15 +02:00
Tim Düsterhus
f5f9294153
random: Deprecate lcg_value() (#15211)
RFC: https://wiki.php.net/rfc/deprecations_php_8_4
2024-08-04 18:24:21 +02:00
Arnaud Le Blanc
d1048a0869
Add zend_random_bytes(), zend_random_bytes_insecure() functions (#14054)
Co-authored-by: Tim Düsterhus <tim@bastelstu.be>
2024-06-12 17:27:01 +02:00
Jorg Adam Sowa
45714e2cb8
random: Remove redundant assignments in php_random_rangeX() (#14536)
Co-authored-by: Tim Düsterhus <tim@bastelstu.be>
2024-06-11 21:36:02 +02:00
Peter Kokot
a82d86479c
Replace WIN32 conditions with _WIN32 or PHP_WIN32 (#14462)
* Replace WIN32 conditions with _WIN32 or PHP_WIN32

WIN32 is defined by the SDK and not defined all the time on Windows by
compilers or the environment. _WIN32 is defined as 1 when the
compilation target is 32-bit ARM, 64-bit ARM, x86, or x64. Otherwise,
undefined.

This syncs these usages one step further.

Upstream libgd has replaced WIN32 with _WIN32 via
c60d9fe577

PHP_WIN32 is added to ext/sockets/sockets.stub.php as done in other
*.stub.php files at this point.

* Use PHP_WIN32 in ext/random

* Use PHP_WIN32 in ext/sockets

* Use _WIN32 in xxhash.h as done upstream

See https://github.com/Cyan4973/xxHash/pull/931

* Update end comment with PHP_WIN32
2024-06-10 21:59:41 +02:00
Peter Kokot
84a0da1574
Sync #if/ifdef/defined (#14508)
This syncs CPP macro conditions:
- _WIN32
- _WIN64
- HAVE_ALLOCA_H
- HAVE_ALPHASORT
- HAVE_ARPA_INET_H
- HAVE_CONFIG_H
- HAVE_DIRENT_H
- HAVE_DLFCN_H
- HAVE_GETTIMEOFDAY
- HAVE_LIBDL
- HAVE_POLL_H
- HAVE_PWD_H
- HAVE_SCANDIR
- HAVE_SYS_FILE_H
- HAVE_SYS_PARAM_H
- HAVE_SYS_SOCKET_H
- HAVE_SYS_TIME_H
- HAVE_SYS_TYPES_H
- HAVE_SYS_WAIT_H
- HAVE_UNISTD_H
- PHP_WIN32
- ZEND_WIN32

These are either undefined or defined to 1 in Autotools and Windows.

Follow up of GH-5526 (-Wundef).
2024-06-09 14:23:41 +02:00
Gina Peter Banyard
8c16076dc3 ext/random: Fix signess issues 2024-06-08 17:15:01 +01:00
Arnaud Le Blanc
44c199ce6b
random: Make php_random_bytes() useable early during engine startup (#14291)
php_random_bytes() can now be used before RANDOM_G() is initialized
2024-05-30 17:24:34 +02:00
Tim Düsterhus
8cf8751533
random: Remove internal aliases for the global Mt19937 functionality (#14314)
* random: Remove `php_rand()`

This effectively is just a slim wrapper around `(zend_long)php_mt_rand()`. It
is not compatible between 32-bit and 64-bit builds of PHP, due to the use of
`zend_long`, which may result in negative integersbeing returned on 32-bit
platforms, whereas 64-bit platforms will be compatible with `php_mt_rand()`. An
example would be the `0` seed, which emits 2357136044 on 64-bit platforms and
-1937831252 on 32-bit platforms.

Users of `php_rand()` should ideally migrate to one of the more modern engines,
with extension-specific state. If drop-in compatibility is desired, they can
just cast the result of `php_mt_rand()`. But providing it out of the box does
not provide a value-add and is potentially dangerous.

* random: Remove `php_srand()`

With `php_rand()` gone, preserving its companion `php_srand()` is just
confusing. The same recommendations apply: Migrate to a modern engine if
possible and just call `php_mt_srand()` with an appropriately casted input.

* random: Remove `PHP_RAND_MAX` and `RAND_MAX`

These are the companions to `php_rand()`, which was removed in a previous
commit.

Generally speaking the maximum returnable value is not particularly useful
anyways. Attempting it to create a random float by dividing the returned
integer by the maximum value would result in a bias if the maximum value would
be larger than 2**53 and even for that case, the various `range()` helpers
allow to easily retrieve a uniformly distributed integer from a suitable range.

* UPGRADING.INTERNALS
2024-05-27 08:12:13 +02:00
Tim Düsterhus
6c59c29942
random: Add missing PHPAPI to php_random_generate_fallback_seed() in random.c
The declaration in the header had it.
2024-05-23 23:12:29 +02:00
Tim Düsterhus
6fb20cd9de
random: Simplify implementation of php_random_generate_fallback_seed() (#13761)
As all the input bits and pieces are mixed with SHA-1, cross-architecture
compatibility is not required and we can just mix in whatever they may look
like in memory, instead of going through the `write_*()` helpers that were
created for a previous in-development version that first filled a buffer that
was then hashed (allowing for easy inspection of the input data, but making it
harder to safely add values without checking for buffer overflows all the
time).

This change should also fix a build error on macOS ZTS: The thread ID is an
opaque type and not guaranteed to be arithmetic as per IEEE Std 1003.1-2017.
And indeed macOS defines it as a pointer to a structure, failing due to the
implicit pointer to integer conversion.
2024-03-20 09:41:01 +01:00
Tim Düsterhus
81744d6cf7
random: Improve the output quality of RANDOM_SEED() (#13730)
* random: Improve the output quality of RANDOM_SEED()

Previously 4 consecutive calls to `RANDOM_SEED()` each for 4 different CLI
requests resulted in:

    $ sapi/cli/php test.php
    2c13e9fde9caa
    2c13e9fd1d6b0
    2c13e9fd4de34
    2c13e9fd1610e
    $ sapi/cli/php test.php
    2c1436764fe07
    2c14367621770
    2c143676c0bf6
    2c143676e02f5
    $ sapi/cli/php test.php
    2c144995a0626
    2c14499590fe2
    2c144995c65db
    2c14499536833
    $ sapi/cli/php test.php
    2c145cb30860b
    2c145cb3ec027
    2c145cb33b4ca
    2c145cb38ff63

Now they result in:

    $ sapi/cli/php test.php
    6796973ace1b5f3d
    1913daf5c158cb4b
    255dbf24237bc8c9
    7c3ba22e60f35196
    $ sapi/cli/php test.php
    afb7cc9ba9819cd2
    3e01a71b91ad020c
    6b718364d3ef108
    bdcd17beeb4b31d2
    $ sapi/cli/php test.php
    53d36eb9b83f8788
    4381c85e816187aa
    2e9b32ee9898e71e
    31d15c946842bddb
    $ sapi/cli/php test.php
    2037a3cba88114b4
    ba0b0d93a9bb43aa
    e13d82d2421269e2
    191de474f3292240

* tree-wide: Replace GENERATE_SEED() by php_random_generate_fallback_seed()

* random: Fix NTS build

* random: Fix Windows build
2024-03-18 16:08:23 +01:00
Tim Düsterhus
bf0abd1629
random: Initialize the mode field when seeding in php_random_default_status() (#13608)
This is a follow-up fix for GH-13579. The issue was detected in the nightly
MSAN build.
2024-03-06 18:57:17 +01:00
Tim Düsterhus
650a8fb098
random: Embed the Mt19937 and CombinedLCG state within the module globals (#13579)
These are always dynamically allocated in GINIT, thus always take up memory. By
embedding them here we can avoid the dynamic allocation and additional pointer
indirection accessing them.

The test script:

    <?php
    for ($i = 0; $i < 9999999; $i++) mt_rand(1, 100);

Appears to run slightly faster with this change applied: Before this change it
always ran in just over 3 seconds, after this change I was also seeing times
below 3 seconds. Howver results are too close and too jittery to state this
performance improvement as a fact.
2024-03-04 17:51:40 +01:00
Tim Düsterhus
54079babf8
Merge branch 'PHP-8.3'
* PHP-8.3:
  random: Fix unknown `mt_srand()` compatibility for unknown modes (#13544)
  Merge branch 'PHP-8.2' into PHP-8.3
  Removed `REPORT_EXIT_STATUS=no` in libmysql tests
  Revert "Fix GH-13519: PGSQL_CONNECT_FORCE_RENEW with persistent connections." (#13546)
2024-02-29 18:15:09 +01:00
Tim Düsterhus
e6c0b09e88
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  random: Fix unknown `mt_srand()` compatibility for unknown modes (#13544)
  Removed `REPORT_EXIT_STATUS=no` in libmysql tests
  Revert "Fix GH-13519: PGSQL_CONNECT_FORCE_RENEW with persistent connections." (#13546)
2024-02-29 18:10:39 +01:00
Tim Düsterhus
e059498c04
random: Fix unknown mt_srand() compatibility for unknown modes (#13544)
PHP 8.1 and below interpreted unknown modes as `MT_RAND_MT19937`, but PHP 8.2+
interprets them as `MT_RAND_PHP`.

Align the behavior with PHP 8.1 and below, because folks should be steered
towards the standard mode.
2024-02-29 18:05:59 +01:00
Tim Düsterhus
99e7cf074b
random: Clean up seeding API (#13540)
* random: Expose xoshiro256**'s seeding functions

* random: Expose pcgoneseq128xslrr64's seeding functions

* random: Expose Mt19937's seeding functions

* random: Expose CombinedLCG's seeding functions

* random: Call php_random_mt19937_seed32 to seed the global Mt19937

This avoids the function pointer indirection and improves type safety.

* random: NULL the generic seeding function

Different engines work quite differently, it is not useful to attempt to seed
them in a generic way using a 64 bit integer. As an example Mt19937 completely
ignores the upper 32 bits.

* random: Remove the `seed` member from `php_random_algo`

See the explanation in the previous commit for the reasoning. This member is
unused since the previous commit and was not consistently available even before
that (specifically for the Secure engine).

* UPGRADING.INTERNALS

* random: Remove useless cast in `php_mt_srand()`
2024-02-29 08:03:35 +01:00
Tim Düsterhus
dce6ed3199
random: Adjust status to state (#13521)
* random: Rename `status` local to `state`

* random: Rename `php_random_algo_with_state`'s `status` member to `state`
2024-02-26 20:38:45 +01:00
Tim Düsterhus
79133df156
random: Pass algorithm and state together as php_random_algo_with_state (#13350)
* random: Remove `php_random_status`

Since 162e1dce98, the `php_random_status` struct
contains just a single `void*`, resulting in needless indirection when
accessing the engine state and thus decreasing readability because of the
additional non-meaningful `->state` references / the local helper variables.

There is also a small, but measurable performance benefit:

    <?php
    $e = new Random\Engine\Xoshiro256StarStar(0);
    $r = new Random\Randomizer($e);

    for ($i = 0; $i < 15; $i++)
    	var_dump(strlen($r->getBytes(100000000)));

goes from roughly 3.85s down to 3.60s.

The names of the `status` variables have not yet been touched to keep the diff
small. They will be renamed to the more appropriate `state` in a follow-up
cleanup commit.

* Introduce `php_random_algo_with_state`
2024-02-25 20:48:58 +01:00
Tim Düsterhus
97b3b4552d
random: Move CSPRNG API into php_random_csprng.h (#13290)
This allows consumers of just the CSPRNG to include a much smaller header. It
also allows to verify at a glance whether a source file might use non-secure
randomness.

This commit includes the new header wherever the CSPRNG is used, possibly
replacing the inclusion of php_random.h if nothing else is used, but also
includes it in the main php_random.h header for compatibility.

Somewhat related to 45f8cfaf10,
2b30f18708, and
b14dd85dca.
2024-02-01 19:09:35 +01:00
Tim Düsterhus
162e1dce98
random: Optimize data flow for the generate function of native engines (#13043)
Instead of returning the generated `uint64_t` and providing the size (i.e. the
number of bytes of the generated value) out-of-band via the
`last_generated_size` member of the `php_random_status` struct, the `generate`
function is now expected to return a new `php_random_result` struct containing
both the `size` and the `result`.

This has two benefits, one for the developer:

It's no longer possible to forget setting `last_generated_size` to the correct
value, because it now happens at the time of returning from the function.

and the other benefit is for performance:

The `php_random_result` struct will be returned as a register pair, thus the
`size` will be directly available without reloading it from main memory.

Checking a simplified version of `php_random_range64()` on Compiler Explorer
(“Godbolt”) with clang 17 shows a single change in the resulting assembly
showcasing the improvement (https://godbolt.org/z/G4WjdYxqx):

    - add     rbp, qword ptr [r14]
    + add     rbp, rdx

Empirical testing confirms a measurable performance increase for the
`Randomizer::getBytes()` method:

    <?php
    $e = new Random\Engine\Xoshiro256StarStar(0);
    $r = new Random\Randomizer($e);

    var_dump(strlen($r->getBytes(100000000)));

goes from 250ms (before the change) to 220ms (after the change). While
generating 100 MB of random data certainly is not the most common use case, it
confirms the theoretical improvement in practice.
2024-01-09 19:04:29 +01:00
Tim Düsterhus
61251093ab
Deprecate MT_RAND_PHP (#11560)
see https://wiki.php.net/rfc/deprecations_php_8_3#mt_rand_php
2023-07-07 12:16:48 +02:00
Tim Düsterhus
b14dd85dca
random: Move the CSPRNG implementation into a separate C file (#10668)
The CSPRNG is a delicate and security relevant piece of code and having it in
the giant random.c makes it much harder to verify changes to it. Split it into
a separate file.
2023-02-23 19:17:09 +01:00
Tim Düsterhus
6c8ef1d997
random: Reduce variable scopes in CSPRNG (#10426)
* random: Convert the urandom loop into a while() loop

This allows us to more easily reduce the scope of `n` in a future commit and
now matches the getrandom(2) loop.

* random: Move the errno reset immediately above the getrandom(2) call

* random: Reduce the scope of `n` in the CSPRNG

* random: Declare `n` outside of preprocessor branch
2023-01-25 09:15:48 +01:00
David Carlier
2740920a39 random disable arc4random_buf for glibc, merge mistake 2023-01-23 17:57:37 +00:00
David Carlier
948cb4702c random netbsd 10 update finally supporting getrandom syscall properly.
Close GH-10327.
2023-01-23 17:49:07 +00:00
Tim Düsterhus
a7998fda8d
random: Simplify control flow for handling /dev/urandom errors (#10392)
The only way the previous `if (read_bytes < size)` branch could be taken is
when the loop was exited by the `break;` statement. We can just merge this into
the loop to make the code more obvious.
2023-01-23 18:28:34 +01:00
Tim Düsterhus
56dc2eb3c7
Merge branch 'PHP-8.2'
* PHP-8.2:
  random: Do not trust arc4random_buf() on glibc (#10390)
2023-01-23 18:21:57 +01:00
Tim Düsterhus
57b362b7a9
random: Do not trust arc4random_buf() on glibc (#10390)
This effectively reverts #8984.

As discussed in #10327 which will enable the use of the getrandom(2) syscall on
NetBSD instead of relying on the userland arc4random_buf(), the CSPRNG should
prioritize security over speed [1] and history has shown that userland
implementations unavoidably fall short on the security side. In fact the glibc
implementation is a thin wrapper around the syscall due to security concerns
and thus does not provide any benefit over just calling getrandom(2) ourselves.

Even without any performance optimizations the CSPRNG should be plenty fast for
the vast majority of applications, because they often only need a few bytes of
randomness to generate a session ID. If speed is desired, the OO API offers
faster, but non-cryptographically secure engines.
2023-01-23 18:21:42 +01:00
Tim Düsterhus
2b395f7b6e random: Remove check for HAVE_DEV_URANDOM
It cannot be decided whether the device is available at build time, PHP might
run in a container or chroot that does not expose the device. Simply attempt to
open it, if it does not exist it will fail.

This improves readability of php_random_bytes() by removing one layer of
preprocessor conditions.
2023-01-23 17:38:50 +01:00
Máté Kocsis
1f05d6ef80
Fix GH-10292 make the default value of the first parame of srand() and mt_srand() nullable (#10380)
Co-authored-by: Tim Düsterhus <timwolla@googlemail.com>
2023-01-20 23:35:08 +01:00
Christoph M. Becker
c8955c078a
Revert GH-10220
Cf. <https://github.com/php/php-src/pull/10220#issuecomment-1383739816>.

This reverts commit ecc880f491.
This reverts commit 588a07f737.
This reverts commit f377e15751.
This reverts commit b4ba16fe18.
This reverts commit 694ec1deea.
This reverts commit 6b34de8eba.
This reverts commit aa1cd02a43.
This reverts commit 308fd311ea.
This reverts commit 16203b53e1.
This reverts commit 738fb5ca54.
This reverts commit 9fdbefacd3.
This reverts commit cd4a7c1d90.
This reverts commit 928685eba2.
This reverts commit 01e5ffc85c.
2023-01-16 12:27:33 +01:00
Tim Düsterhus
e7c0f4e816
random: Rely on free(NULL) being safe for random status freeing (#10246)
* random: Rely on `free(NULL)` being safe for random status freeing

* random: Restructure `php_random_status_free()` to not early-return
2023-01-10 18:46:57 +01:00
Max Kellermann
308fd311ea ext/{standard,json,random,...}: add missing includes 2023-01-10 14:19:03 +00:00
Tim Düsterhus
5f42a46405
Merge branch 'PHP-8.2'
* PHP-8.2:
  random: Fix check before closing `random_fd` (#10247)
2023-01-07 14:03:26 +01:00
Tim Düsterhus
32f503e4e3
random: Fix check before closing random_fd (#10247)
If, for whatever reason, the random_fd has been assigned file descriptor `0` it
previously failed to close during module shutdown, thus leaking the descriptor.
2023-01-07 14:03:13 +01:00
Tim Düsterhus
f9a1a90380
Add Randomizer::nextFloat() and Randomizer::getFloat() (#9679)
* random: Add Randomizer::nextFloat()

* random: Check that doubles are IEEE-754 in Randomizer::nextFloat()

* random: Add Randomizer::nextFloat() tests

* random: Add Randomizer::getFloat() implementing the y-section algorithm

The algorithm is published in:

Drawing Random Floating-Point Numbers from an Interval. Frédéric
Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022.
https://doi.org/10.1145/3503512

* random: Implement getFloat_gamma() optimization

see https://github.com/php/php-src/pull/9679/files#r994668327

* random: Add Random\IntervalBoundary

* random: Split the implementation of γ-section into its own file

* random: Add tests for Randomizer::getFloat()

* random: Fix γ-section for 32-bit systems

* random: Replace check for __STDC_IEC_559__ by compile-time check for DBL_MANT_DIG

* random: Drop nextFloat_spacing.phpt

* random: Optimize Randomizer::getFloat() implementation

* random: Reject non-finite parameters in Randomizer::getFloat()

* random: Add NEWS/UPGRADING for Randomizer’s float functionality
2022-12-14 17:48:47 +01:00
Joshua Rüsweg
ac3ecd03af
Add Randomizer::getBytesFromString() method (#9664)
* Add `Randomizer::getBytesFromAlphabet()` method

* Rename `getBytesFromAlphabet` to `getBytesFromString`

* [ci skip] Add NEWS/UPGRADING for Randomizer::getBytesFromString()

Co-authored-by: Tim Düsterhus <tim@bastelstu.be>
2022-12-09 17:39:13 +01:00
Tim Düsterhus
5989953efb
Merge branch 'PHP-8.2'
* PHP-8.2:
  Fix pre-PHP 8.2 compatibility for php_mt_rand_range() with MT_RAND_PHP (#9839)
2022-10-28 16:53:18 +02:00
Tim Düsterhus
7f0b228f48
Fix pre-PHP 8.2 compatibility for php_mt_rand_range() with MT_RAND_PHP (#9839)
* Fix pre-PHP 8.2 compatibility for php_mt_rand_range() with MT_RAND_PHP

As some left-over comments indicated:

> Legacy mode deliberately not inside php_mt_rand_range()
> to prevent other functions being affected

The broken scaler was only used for `php_mt_rand_common()`, not
`php_mt_rand_range()`. The former is only used for `mt_rand()`, whereas the
latter is used for `array_rand()` and others.

With the refactoring for the introduction of ext/random `php_mt_rand_common()`
and `php_mt_rand_range()` were accidentally unified, thus introducing a
behavioral change that was reported in FakerPHP/Faker#528.

This commit moves the checks for `MT_RAND_PHP` from the general-purpose
`range()` function back into `php_mt_rand_common()` and also into
`Randomizer::getInt()` for drop-in compatibility with `mt_rand()`.

* [ci skip] NEWS for `MT_RAND_PHP` compatibility
2022-10-28 16:52:43 +02:00
Tim Düsterhus
32d101b1fc
Merge branch 'PHP-8.2'
* PHP-8.2:
  Reduce scope of `r` in rand_rangeXX (#9678)
2022-10-06 12:56:02 +02:00
Tim Düsterhus
59a19d710b
Reduce scope of r in rand_rangeXX (#9678)
This variable is only accessed within a single iteration of the expansion loop.
2022-10-06 12:55:51 +02:00
Remi Collet
c398694e19
Merge branch 'PHP-8.2'
* PHP-8.2:
  declare random globals as public API
2022-09-20 13:20:51 +02:00
Remi Collet
28a4d7676a
declare random globals as public API 2022-09-20 13:20:23 +02:00
Bob Weinand
a01dd9feda Revert "Port all internally used classes to use default_object_handlers"
This reverts commit 94ee4f9834.

The commit was a bit too late to be included in PHP 8.2 RC1. Given it's a massive ABI break, we decide to postpone the change to PHP 8.3.
2022-09-14 11:13:23 +02:00
Bob Weinand
94ee4f9834 Port all internally used classes to use default_object_handlers
Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
2022-08-31 16:45:27 +02:00
Tim Düsterhus
cbb024cb3d
Select rand_rangeXX() variant only based on the requested range (#9418)
This fixes an incompatibility when wrapping native 32-bit engines with a userland
engine. The latter always used the 64-bit range function which then used two
32-bit numbers from the underlying engine to fill the 64-bit range, whereas the
native implementation used only one.

Now the selection of the range variant only depends on the requested range. A
32-bit range uses the 32-bit variant (even for 64-bit engines), whereas a
larger range uses the 64-bit variant.

This was found in https://github.com/php/php-src/pull/9410#discussion_r953213000
2022-08-25 09:42:32 +02:00
Tim Düsterhus
0f696e2934
Fix rand_range32() for umax = UINT32_MAX (#9416)
* Fix rand_range32() for umax = UINT32_MAX

This was introduced in the commit that added the random extension:
4d8dd8d258.

Resolves GH-9415

* [ci skip] Rename `$r` to `$randomizer` in gh9415.phpt

* Make gh9415.phpt deterministic

* Make gh9415.phpt compatible with 32-bit
2022-08-24 14:25:51 +02:00
Tim Düsterhus
3331832b04
Add ext/random Exception hierarchy (#9220)
* Add Random\Random{Error,Exception} and Random\BrokenRandomEngineError

* Throw BrokenRandomEngineError

* Throw RandomException on seeding failure

* Throw RandomException when CSPRNG fails

* Remove unused include from ext/random/engine_combinedlcg.c

* Remove unused include from ext/random/engine_secure.c

* Remove unused include from ext/random/random.c

* [ci skip] Add ext/random Exception hierarchy to NEWS

* [ci skip] Add the change of Exception for random_(int|bytes) to UPGRADING
2022-08-02 20:04:28 +02:00