To match other capitalized strings like `ZEND_STR_UNKNOWN_CAPITALIZED` and
`ZEND_STR_ARRAY_CAPITALIZED`. Since this known string was only added in PHP
8.4, no backwards compatibility alias is needed.
When a class (or enum) has no methods, rather than using an array that only
contains `ZEND_FE_END`, use `NULL` for the functions. The implementation of
class registration for internal classes, `do_register_internal_class()` in
zend_API.c, already skips classes where the functions are `NULL`. By removing
these unneeded arrays, we can reduce the size of the header files, while also
removing an unneeded call to zend_register_functions() for each internal class
with no extra methods.
Currently, internal classes are registered with the following code:
INIT_CLASS_ENTRY(ce, "InternalClass", class_InternalClass_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
class_entry->ce_flags |= ...;
This has worked well so far, except if InternalClass is readonly. It is because some inheritance checks are run by zend_register_internal_class_ex before ZEND_ACC_READONLY_CLASS is added to ce_flags.
The issue is fixed by adding a zend_register_internal_class_with_flags() zend API function that stubs can use from now on. This function makes sure to add the flags before running any checks. Since the new API is not available in lower PHP versions, gen_stub.php has to keep support for the existing API for PHP 8.3 and below.
To fix part of GH-15381.
gcc nor clang provides a constant to distinguish illumos and solaris
not the system provides a kernel version stamp like the BSD.
thus, we simply check the symbol and remaing purposely conservative in
the existing logic, using it only for solaris to avoid unexpected
breakages for other systems. would need a different fix for higher
branches.
Close GH-15390
This patch greatly improves the performance for the common case of using a
64-bit engine and requesting a length that is a multiple of 8.
It does so by providing a fast path that will just `memcpy()` (which will be
optimized out) the returned uint64_t directly into the output buffer,
byteswapping it for big endian architectures.
The existing byte-wise copying logic was mostly left alone. It only received an
optimization of the shifting and masking that was previously applied to
`Randomizer::getBytesFromString()` in 1fc2ddc996.
Co-authored-by: Saki Takamachi <saki@php.net>
Using compound literals is conforming to C99 (and up), but not with any
C++ standard. Since the code is in a public header, it might be used
by C++ extensions. Unfortunately, we cannot even used designated
initializers, because these are a C++20 feature, so we stick with
classic C/C++ code.
Closes GH-15100.
The zend_object.properties HashTable needs to be built just in time by calling
rebuild_object_properties() on the object before accessing it. Normally this is
done automatically in zend_std_get_properties(), but we do it manually in a few
places.
In this change I introduce an inline variant of zend_std_build_properties(), and
refactor these places to use it instead of calling rebuild_object_properties()
manually.
rebuild_object_properties() renamed as rebuild_object_properties_internal(), to
enforce usage of zend_std_get_properties() or zend_std_build_properties_ex().
Closes GH-14996
The m4_normalize is for Autoconf < 2.70 (on 2.70 and later versions a
blank-or-newline separated items can be expanded without using
backslash-newline). The order of headers in configure.ac is left as is
because the first few headers depend on checking other headers (for
those includes the 4th argument).
AC_CHECK_DECLS defines HAVE_DECL_ARC4RANDOM_BUF to 0 or 1. On Windows
this isn't defined to 0. To avoid the undefined state, the AC_CHECK_DECL
is used to manually define the HAVE_ARC4RANDOM_BUF to 1 if declaration
is found, otherwise undefined.
In the future on current platforms, also AC_CHECK_FUNCS can be used
instead since the arc4random_buf is located in default libraries (C)
with declaration available in headers.
These are either undefined or defined (to value 1):
- __DragonFly__
- __FreeBSD__
- HAS_MCAST_EXT
- HAVE_GETCWD
- HAVE_GETWD
- HAVE_GLIBC_ICONV
- HAVE_JIT
- HAVE_LCHOWN
- HAVE_NL_LANGINFO
- HAVE_RL_CALLBACK_READ_CHAR
- HAVE_RL_ON_NEW_LINE
- HAVE_SQL_EXTENDED_FETCH
- HAVE_UTIME
Follow up of GH-5526 (-Wundef)
* 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
These are either undefined or defined to value 1 in Autotools and
Windows:
- HAVE_COMMONCRYPTO_COMMONRANDOM_H
- HAVE_EXIF
- HAVE_FOPENCOOKIE
- HAVE_IF_NAMETOINDEX
- HAVE_LIBICONV
- HAVE_SOCKETS
- HAVE_STRUCT_STAT_ST_RDEV
- HAVE_STRUCT_TM_TM_GMTOFF
- HAVE_STRUCT_TM_TM_ZONE
Follow up of GH-5526 (-Wundef)
* 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
The php_random.h header already defines them as `PHPAPI` and they actually are
part of the public API.
Co-authored-by: Arnaud Le Blanc <arnaud.lb@gmail.com>
The implementation is needlessly obfuscated. It's not immediately clear that
MODMULT is a simple modular multiplication, despite its name. Specifically it's
not clear which of the parameters is the second factor.
Furthermore the stated period is off-by-one: A value of `0` is part of its own
chain, thus it may not be included in the period of the underlying generators.
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.
Now that the CombinedLCG is no longer used within GENERATE_SEED(), we can
safely use the CSPRNG with a php_random_generate_fallback_seed() fallback to
seed the CombinedLCG.
This is not just an issue due to missing initialization since moving the state
struct directly into the module globals. In earlier versions changing the mode
to `MT_RAND_PHP` within a single request would also affect the mode for
subsequent requests.
Original commit message follows:
This is a follow-up fix for GH-13579. The issue was detected in the nightly
MSAN build.
(cherry picked from commit bf0abd1629)
* random: Make Mt19937's `mode` field an enum
* random: Reorder the `php_random_status_state_mt19937` struct
Empirical testing did not show any differences in performance, but it makes
sense to me to put the `count` field (which is accessed for every invocation of
Mt19937) at the beginning of the struct, keeping it near the values from the
state array that are returned first, resulting in only a single cache line load
if only a small amount of numbers are requested.
It naturally follows to also put the `mode` field there and move the
humongous state array to the end.
* random: Remove the `MT_N` constant
`MT_N` is an awfully generic name that bleeds into every file including
`php_random.h`. As it's an implementation detail, remove it entirely to keep
`php_random.h` clean.
To prevent the state struct from diverging from the implementation, the size of
the state vector is statically verified. Furthermore there are phpt tests
verifying the Mt19937 output across a reload, revealing when the state vector
is reloaded too early or too late.
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.
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.
* 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()`
* 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`
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.