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.
The original calculation method for prod_arr_size allowed for some error,
which could have increased the number of simple loops without byte tricks
at the end of the calculation when converting to bc_num.
The new method calculates the size accurately, so the number of loops does
not increase unnecessarily.
The pg_encoding_to_char is available in PostgreSQL since ~7.3 where also
the --enable-multibyte option was removed. PHP minimum PostgreSQL
version at this point is 9.1, which also has the pg_encoding_to_char
declaration in libpq-fe.h.
This removes conditional usage and the HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
symbol.
The image output functions imagegif/imagepng/imagewebp/imageavif/imagejpeg
were all calling the static function _php_image_output_ctx which was basically
a big switch statement between each image type which also have different
parameters.
The only identical part was the call to create_stream_context_from_zval that
is now merged with create_output_context.
* zend_compile: Add `zend_compile_rope_finalize()`
This just extracts the implementation as-is into a dedicated function to make
it reusable in preparation of a future commit.
* zend_compile: Use clearer parameter names for `zend_compile_rope_finalize()`
* zend_compile: Fix `zend_compile_rope_finalize()` for ropes containing a single constant string
Without this Opcache will trigger a use-after-free in
`zend_optimizer_compact_literals()`.
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
* zend_compile: Optimize `sprintf()` into a rope
This optimization will compile `sprintf()` using only `%s` placeholders into a
rope at compile time, effectively making those calls equivalent to the use of
string interpolation, with the added benefit of supporting arbitrary
expressions instead of just expressions starting with a `$`.
For a synthetic test using:
<?php
$a = 'foo';
$b = 'bar';
for ($i = 0; $i < 100_000_000; $i++) {
sprintf("%s-%s", $a, $b);
}
This optimization yields a 2.1× performance improvement:
$ hyperfine 'sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php' \
'/tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php'
Benchmark 1: sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php
Time (mean ± σ): 1.869 s ± 0.033 s [User: 1.865 s, System: 0.003 s]
Range (min … max): 1.840 s … 1.945 s 10 runs
Benchmark 2: /tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php
Time (mean ± σ): 4.011 s ± 0.034 s [User: 4.006 s, System: 0.005 s]
Range (min … max): 3.964 s … 4.079 s 10 runs
Summary
sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php ran
2.15 ± 0.04 times faster than /tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php
This optimization comes with a small and probably insignificant behavioral
change: If one of the values cannot be (cleanly) converted to a string, for
example when attempting to insert an object that is not `Stringable`, the
resulting Exception will naturally not show the `sprintf()` call in the
resulting stack trace, because there is no call to `sprintf()`.
Nevertheless it will correctly point out the line of the `sprintf()` call as
the source of the Exception, pointing the user towards the correct location.
* zend_compile: Eagerly handle empty format strings in `sprintf()` optimization
* zend_compile: Add additional explanatory comments to zend_compile_func_sprintf()
* Add zero-argument test to sprintf_rope_optimization_001.phpt
---------
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
We keep track of free slots by organizing them in a linked list, with the
first word of every free slot being a pointer to the next one.
In order to make corruptions more difficult to exploit, we check the consistency
of these pointers before dereference by comparing them with a shadow. The shadow
is a copy of the pointer, stored at the end of the slot.
Before this change, an off-by-1 write is enough to produce a valid freelist
pointer. After this change, a bigger out of bound write is required for that.
The difficulty is increase further by mangling the shadow with a secret, and
byte-swapping it, which increases the minimal required out of bound write
length.
Closes GH-14054
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)
This syncs few inconsistencies between the Windows and Autotools build
systems:
- HAVE_OPENSSL_EXT is now defined in the same style on both systems
(undefined - extension is not available, defined to 1 - extension is
available)
- HAVE_OPENSSL removed as it was only defined on Windows