1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 16:22:37 +01:00
Commit Graph

101 Commits

Author SHA1 Message Date
Tim Düsterhus
ce2d26363f random: Reuse the seed128/seed256 helpers when seeding using the CSPRNG (#13311)
Instead of writing to the engine's state struct directly, use the helpers for
consistency.
2024-02-05 17:00:33 +01:00
Tim Düsterhus
7ed21e66fa random: Do not hardcode the target type when invoking the CSPRNG (#13308)
Instead derive the number of bytes to retrieve from the variable that is being
filled.
2024-02-02 20:10:19 +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
f39357b07b random: Call int-seeding functions directly
As the `__construct()` implementation is engine-specific anyway, we know what
engine were dealing with and can just call the seeding function directly
instead of going through a function pointer.

This likely improves construction performance a little, but I did not measure.
2024-01-31 08:49:17 +01:00
Tim Düsterhus
304c9c3db1 random: Add explicitly named seed64() helper for xoshiro256** 2024-01-31 08:49:17 +01:00
Tim Düsterhus
79f648ace2 random: Narrow the parameter types of seed128/seed256
These internal-only functions accepted a `php_random_status`, just to extract
the internal state from the `state` pointer. Make them take the state struct
directly to improve type safety.
2024-01-31 08:49:17 +01:00
Tim Düsterhus
45f8cfaf10 random: Split the uint128 implementation into its own header (#13132)
The implementation of `php_random_uint128_*` exists specifically for
pcgoneseq128xslrr66 and takes up a third of php_random.h. Split it into its own
header to keep php_random.h focused on the functionality directly related to
randomness.
2024-01-17 16:07:45 +01:00
Tim Düsterhus
0b7587feae Merge branch 'PHP-8.3'
* PHP-8.3:
  random/standard: Adjust #13138 for PHP 8.3
  random/standard: Correctly handle broken engines in php_array_pick_keys (#13138)
2024-01-14 13:07:18 +01:00
Tim Düsterhus
00ea756c93 random/standard: Adjust #13138 for PHP 8.3 2024-01-14 13:05:44 +01:00
Tim Düsterhus
f2f070a897 Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  random/standard: Correctly handle broken engines in php_array_pick_keys (#13138)
2024-01-14 13:03:33 +01:00
Tim Düsterhus
97c6da1dec random/standard: Correctly handle broken engines in php_array_pick_keys (#13138) 2024-01-14 13:01:29 +01:00
Tim Düsterhus
db68565d03 random: Dynamically calculate the state size when seeding with CSPRNG
Instead of hardcoding struct names, or even sizes, we can just determine the
actual size of the target structure using sizeof().
2024-01-11 08:54:18 +01:00
Tim Düsterhus
62aa8fa375 random: Reduce variable scope in Random\Engine\PcgOneseq128XslRr64::__construct()
This is for consistency with xoshiro256**'s constructor.
2024-01-11 08:54:18 +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
6b1d0606d0 Merge branch 'PHP-8.3'
* PHP-8.3:
  random: Add additional test for Randomizer::getFloat() (#12436)
2023-10-14 18:38:43 +02:00
Tim Düsterhus
ac0b9bff97 random: Add additional test for Randomizer::getFloat() (#12436) 2023-10-14 18:38:11 +02:00
Tim Düsterhus
82c2143ddb Merge branch 'PHP-8.3'
* PHP-8.3:
  random: Fix γ-section implementation for Randomizer::getFloat() (#12402)
2023-10-13 18:04:40 +02:00
Tim Düsterhus
582b724c35 random: Fix γ-section implementation for Randomizer::getFloat() (#12402)
The reference implementation of the "Drawing Random Floating-Point Numbers from
an Interval" paper contains two mistakes that will result in erroneous values
being returned under certain circumstances:

- For large values of `g` the multiplication of `k * g` might overflow to
  infinity.
- The value of `ceilint()` might exceed 2^53, possibly leading to a rounding
  error when promoting `k` to double within the multiplication of `k * g`.

This commit updates the implementation based on Prof. Goualard suggestions
after reaching out to him. It will correctly handle inputs larger than 2^-1020
in absolute values. This limitation will be documented and those inputs
possibly be rejected in a follow-up commit depending on performance concerns.
2023-10-13 17:55:14 +02:00
Tim Düsterhus
3bc63a37a3 random: Remove RAND_RANGE_BADSCALING (#12374)
This macro is no longer used within php-src since
60ace13f9c, it invokes undefined behavior
depending on the input and the corresponding MT_RAND_PHP mode was deprecated in
PHP 8.3.

Thus remove this macro. Any remaining non-php-src user should just inline it
into their code, but should ideally migrate to a non-biased scaler. In any case
the undefined behavior of the original implementation should be accounted for.
2023-10-07 13:19:54 +01:00
divinity76
ab30f27ce3 random: Perform fewer iterations if SKIP_SLOW_TESTS is set (#12279)
Co-authored-by: Tim Düsterhus <tim@bastelstu.be>
2023-09-23 14:48:33 +02: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
Máté Kocsis
3906bccc00 Add support for typed class constants in stubs 2023-07-01 11:50:04 +02:00
Dmitry Stogov
d5484bf115 Remove includes 2023-04-04 22:48:26 +03:00
Niels Dossche
0b212ab5ab Merge branch 'PHP-8.2'
* PHP-8.2:
  Fix undefined behaviour in GENERATE_SEED()
  Fix undefined behaviour when writing 32-bit values in phar/tar.c
2023-03-26 16:16:26 +02:00
Niels Dossche
22040f5a8f Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1:
  Fix undefined behaviour in GENERATE_SEED()
  Fix undefined behaviour when writing 32-bit values in phar/tar.c
2023-03-26 16:15:57 +02:00
Ilija Tovilo
9d5f2f1343 Use new ZSTR_INIT_LITERAL macro (#10879) 2023-03-20 16:19:05 +01:00
Tim Düsterhus
08bae7f370 Merge branch 'PHP-8.2'
* PHP-8.2:
  random: Add missing `php.h` include to php_random.h (#10764)
2023-03-06 17:34:24 +01:00
Tim Düsterhus
5087931963 random: Add missing php.h include to php_random.h (#10764)
`PHPAPI` is defined in `php.h`. It appears that without the explicit include,
recent versions of Visual Studio Code’s intellisense (rightfully) no longer
detect `PHPAPI`. This will then lead to a misparsing of the file, because
`PHPAPI` is assumed to be the return type and the actual return type is assumed
to be the function name, thus expecting a semicolon after the actual return
type. This in turn colors the entire header in red due to the detected syntax
error(s), making development very hard / impossible.

This did not cause issues outside of the IDE use case, because apparently all
users of `php_random.h` include `php.h` before including `php_random.h`.
2023-03-06 17:33:52 +01:00
Tim Düsterhus
8abea1b3c2 random: Convert php_random_(bytes|int)_(silent|throw) into inline functions (#10763)
Compared to macros, inline functions are more robust and easier to debug.

Also, use true/false at the same time instead of 1 and 0.
2023-03-04 03:33:22 +00:00
Tim Düsterhus
f079aa2e24 random: Fix return type of php_random_(bytes|int) (#10687)
These return a `zend_result`, not `int`.
2023-02-24 15:10:44 +01: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
0cfc45b667 random: Use branchless implementation for mask generation in Randomizer::getBytesFromString() (#10522)
* random: Add `max_offset` local to Randomizer::getBytesFromString()

* random: Use branchless implementation for mask generation in Randomizer::getBytesFromString()

This was benchmarked against clzl with a standalone script with random inputs
and is slightly faster. clzl requires an additional branch to handle the
source_length = 1 / max_offset = 0 case.

* Improve comment for masking in Randomizer::getBytesFromString()
2023-02-08 09:36:12 +01:00
Tim Düsterhus
64d9080534 random: Fix off-by-one in fast path selection of Randomizer::getBytesFromString() (#10449)
With a single byte we can choose offsets between 0x00 and 0xff, thus 0x100
different offsets. We only need to use the slow path for sources of more than
0x100 bytes.

The previous version was correct with regard to the output expectations, it was
just slower than necessary. Better fix this now while we still can before being
bound by our BC guarantees with regard to emitted sequences.

This also adds a test to verify the behavior: For powers of two we never reject
any values during rejection sampling, we just need to mask off the unneeded
bits. Thus we can specifically verify that the number of calls to the engine
match the expected amount. We also verify that all the possible values are
emitted to make sure the masking does not remove any required bits. For inputs
longer than 0x100 bytes we need trust the `range()` implementation to be
unbiased, but still verify the number of engine calls and perform a basic
output check.
2023-01-26 23:28:34 +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
Máté Kocsis
7517cf3b97 Merge branch 'PHP-8.1' into PHP-8.2
- PHP-8.1:
  Fix GH-10292 1st param of mt_srand() has UNKNOWN default on PHP <8.3
2023-01-24 19:53:09 +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
Tim Düsterhus
3ed5264414 [ci skip] random: Fix whitespace errors in randomizer.c 2023-01-21 00:11:22 +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
13b82eef84 random: Randomizer::getFloat(): Fix check for empty open intervals (#10185)
* random: Randomizer::getFloat(): Fix check for empty open intervals

The check for invalid parameters for the IntervalBoundary::OpenOpen variant was
not correct: If two consecutive doubles are passed as parameters, the resulting
interval is empty, resulting in an uint64 underflow in the γ-section
implementation.

Instead of checking whether `$min < $max`, we must check that there is at least
one more double between `$min` and `$max`, i.e. it must hold that:

	nextafter($min, $max) != $max

Instead of duplicating the comparatively complicated and expensive `nextafter`
logic for a rare error case we instead return `NAN` from the γ-section
implementation when the parameters result in an empty interval and thus underflow.

This allows us to reliably detect this specific error case *after* the fact,
but without modifying the engine state. It also provides reliable error
reporting for other internal functions that might use the γ-section
implementation.

* random: γ-section: Also check that that min is smaller than max

This extends the empty-interval check in the γ-section implementation with a
check that min is actually the smaller of the two parameters.

* random: Use PHP_FLOAT_EPSILON in getFloat_error.phpt

Co-authored-by: Christoph M. Becker <cmbecker69@gmx.de>
2023-01-10 10:16:33 +01: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