Commit Graph

83 Commits

Author SHA1 Message Date
Tim Düsterhus
ac0b9bff97
random: Add additional test for Randomizer::getFloat() (#12436) 2023-10-14 18:38:11 +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
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
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
50e32015ae
Merge branch 'PHP-8.2'
* PHP-8.2:
  [ci skip] random: Trim trailing whitespace in randomizer.c
2022-11-27 19:11:32 +01:00
Tim Düsterhus
350883db06
[ci skip] random: Trim trailing whitespace in randomizer.c
To keep the diff cleaner for future changes, such as #9664.
2022-11-27 19:10:45 +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
Tim Düsterhus
2ba4747ebd
Merge branch 'PHP-8.2'
* PHP-8.2:
  [ci skip] Trim trailing whitespace in php_random.h
2022-10-03 20:33:30 +02:00
Tim Düsterhus
1e9280e035
[ci skip] Trim trailing whitespace in php_random.h 2022-10-03 20:32:37 +02:00
Tim Düsterhus
3ba7756376
Merge branch 'PHP-8.2'
* PHP-8.2:
  Remove superfluous helper variable in `Randomizer::getBytes()` (#9563)
2022-09-20 17:42:03 +02:00
Joshua Rüsweg
ca399841ad
Remove superfluous helper variable in Randomizer::getBytes() (#9563)
* Remove superfluous helper variable in Randomizer::getBytes()

* Reduce the scope of `result` in Randomizer::getBytes()

Co-authored-by: Tim Düsterhus <tim@bastelstu.be>
2022-09-20 17:41:31 +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
Tim Düsterhus
ddf7a5d4d9
random: Validate that the arrays do not contain extra elements when unserializing (#9458)
* Apply `var_dump()` in 02_engine/all_serialize_error.phpt

This ensures that an undetected serialization error is clear identifiable in the output.

* random: Validate that the arrays do not contain extra elements when unserializing
2022-09-05 17:33:36 +02:00
David Bohman
f098193d15 GH-9464: Fix build on older macOs releases.
A simple check for CommonCrypto/CommonRandom.h does not work on earlier macOS.
Must also pull in sys/types.h for size_t, Availability.h for __OSX_AVAILABLE_STARTING,
and CommonCrypto/CommonCryptoError.h for CCCryptorStatus.

Closes GH-9479.
2022-09-04 02:12:28 +01:00
Tim Düsterhus
f7d426cca6
Unify structure for ext/random's randomizer tests (#9410)
* Unify structure for ext/random's engine tests (2)

This makes adjustments that were missed in
2d6a883b3a.

* Add `engines.inc` for ext/random tests

* Unify structure for ext/random's randomizer tests
2022-08-31 19:22:39 +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