Commit graph

2936 commits

Author SHA1 Message Date
Ilija Tovilo
386ab1dad2
Revert "Fix infinite recursion on deprecated attribute evaluation"
This reverts commit 272f7f75e2.

Reverts GH-17712 for the PHP-8.4 branch. This will be reapplied later
with a fix for GH-18463 (GH-18464).
2025-04-30 20:52:56 +02:00
Ilija Tovilo
272f7f75e2
Fix infinite recursion on deprecated attribute evaluation
Fixes GH-17711
Fixes GH-18022
Closes GH-17712
2025-03-26 23:39:38 +01:00
Niels Dossche
4fd9992561
Fix OSS-Fuzz #403308724
Because simple hooks can be nested without starting a new context, we
need to restore the old property info in case of nested hooks.

Closes GH-18074.
2025-03-16 13:42:40 +01:00
Daniel Scherzer
c0857e0d8a
Fix GH-17916: Final abstract properties should error
Closes GH-17917.
2025-02-24 20:17:41 +01:00
Ilija Tovilo
4f91af38cc
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix stack overflow detection for variable compilation
2025-01-29 23:28:16 +01:00
Ilija Tovilo
333f5dd848
Fix stack overflow detection for variable compilation
Closes GH-17623
2025-01-29 23:27:27 +01:00
Niels Dossche
0b12db6afa
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix may_have_extra_named_args flag for ZEND_AST_UNPACK
2025-01-21 19:27:19 +01:00
Niels Dossche
0b3e637aec
Fix may_have_extra_named_args flag for ZEND_AST_UNPACK
The check for `!fbc || (fbc->common.fn_flags & ZEND_ACC_VARIADIC)` is
performed after `fbc` is set to NULL, so this always returns true.
This results in `ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS` always being
set for unpack sends. Fix it by moving the flag updates to the point
before setting `fbc` to NULL.

Closes GH-17534.
2025-01-21 19:26:49 +01:00
Ilija Tovilo
147e9c808c
__PROPERTY__ does not work in all constant expression contexts
Fixes GH-17222
Closes GH-17378
2025-01-13 16:42:38 +01:00
Niels Dossche
71493623f4
Fix GH-17234: Numeric parent hook call fails with assertion
The current code expects the property name to be a string, but it can
also be a number via the {} syntax. Handle this consistently to a string
by using zval_get_string which will do the type coercion and refcount
update (instead of assuming string and doing an explicit string copy).

Closes GH-17236.
2025-01-07 19:21:22 +01:00
Ilija Tovilo
792f63df45
Fix unstable get_iterator pointer for hooked classes in shm on Windows
Closes GH-17034
2024-12-09 17:14:19 +01:00
Christoph M. Becker
ba7dee5676
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix potential OOB read in zend_dirname() on Windows
2024-11-29 22:11:00 +01:00
Christoph M. Becker
65070bb46c
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  Fix potential OOB read in zend_dirname() on Windows
2024-11-29 22:09:40 +01:00
Christoph M. Becker
94fa2a4ce1
Fix potential OOB read in zend_dirname() on Windows
Only on Windows `IS_SLASH_P()` may read the previous byte, and so may
in unlikely cases read one byte out of bounds.  Since `IS_SLASH_P()` is
in a public header (albeit not likely to be used by external extensions
or SAPIs), we introduce `IS_SLASH_P_EX()` which accepts a second
argument to prevent that OOB read.

It should be noted that the PHP userland function `dirname()` is not
affected by this issue, since it does not call `zend_dirname()` on
Windows.

Closes GH-16995.
2024-11-29 22:08:06 +01:00
Niels Dossche
382be923ae
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix GH-16727: Opcache bad signal 139 crash in ZTS bookworm (frankenphp)
2024-11-11 16:20:39 +01:00
Niels Dossche
fbf4cec63b
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  Fix GH-16727: Opcache bad signal 139 crash in ZTS bookworm (frankenphp)
2024-11-11 16:20:30 +01:00
Niels Dossche
02ee521e20
Fix GH-16727: Opcache bad signal 139 crash in ZTS bookworm (frankenphp)
Reproducer: https://github.com/php/php-src/issues/16727#issuecomment-2466256317

The root cause is a data race between two different threads:

1) We allocate a lower cased name for an anonymous class here:
   f97353f228/Zend/zend_compile.c (L8109)
2) This gets looked up as an interned string here:
   f97353f228/Zend/zend_compile.c (L8112)
   Assuming that there are uppercase symbols in the string and therefore
   `lcname != name` and that `lcname` is not yet in the interned string table,
   the pointer value of `lcname` won't change.
3) Here we add the string into the interned string table:
   f97353f228/Zend/zend_compile.c (L8223)
   However, in the meantime another thread could've added the string into the interned string table.
   This means that the following code will run, indirectly called via the `LITERAL_STR` macro,
   freeing `lcname`: 62e53e6f49/ext/opcache/ZendAccelerator.c (L572-L575)
4) In the reproducer we then access the freed `lcname` string here:
   f97353f228/Zend/zend_compile.c (L8229)

This is solved in my patch by retrieving the interned string pointer
and putting it in `lcname`.

Closes GH-16748.
2024-11-11 16:20:05 +01:00
Ilija Tovilo
cd8ee4dad1
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix lineno in function redeclaration error
2024-10-22 15:06:06 +02:00
Ilija Tovilo
381e020edb
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  Fix lineno in function redeclaration error
2024-10-22 15:05:29 +02:00
Ilija Tovilo
de7ef3fa66
Fix lineno in function redeclaration error
We were previously using the lineno of the first instruction, rather than the
start of the function itself.

Fixes GH-16509
Closes GH-16531
2024-10-22 15:04:20 +02:00
Ilija Tovilo
a8bbc84551
Disallow asymmetric visibility on static properties
This check was forgotten in the original implementation. Relaxing this
restriction shouldn't be hard, but needs some work. We either need to prevent
merging of cache slots for R/RW/W, or we need to introduce an additional check
when writing to the property indirectly. This check is currently present only
for direct writes.

Closes GH-16462
2024-10-16 23:00:11 +02:00
DanielEScherzer
702fb31894
zend_resolve_const_class_name_reference(): use double quotes around names (#15998)
This is a follow-up to #15990, as it turns out there was a second place that emits this kind of error message.
2024-09-23 09:59:48 +01:00
DanielEScherzer
34325c5e3a
zend_assert_valid_class_name(): use double quotes around names (#15990) 2024-09-23 00:44:16 +01:00
Daniel Scherzer
79d708cfca GH-15976: clarify error messages for enum/trait/interface/alias names
Instead of always saying that a name is reserved or deprecated and
cannot/should not be used as a class name, take the usage into account and say
the name cannot be used as an enum name, trait name, etc. In the process, for
class names add a missing "a".
2024-09-22 19:14:57 +01:00
Jorg Adam Sowa
2a30f2ffc4
Add type indicator to array/arg unpack error messages (GH-15448) 2024-09-01 22:57:12 +02:00
Ilija Tovilo
8df557ac42
[RFC] Asymmetric visibility v2 (GH-15063)
Co-authored-by: Larry Garfield <larry@garfieldtech.com>
2024-08-27 02:04:48 +02:00
Gina Peter Bnayard
5853cdb73d Use "must not" instead of "cannot" wording 2024-08-21 21:12:17 +01:00
Ilija Tovilo
36b1977415
Fix missing compile error when declaring hooked props on readonly classes (GH-15439)
Fixes GH-15419
2024-08-19 14:58:55 +02:00
Ilija Tovilo
770616b823
Fix param with hooks but no visibility not treated as cpp (GH-15442)
Fixes GH-15438
2024-08-19 14:53:54 +02:00
Gina Peter Banyard
a79c70f574
[RFC] Convert exit (and die) from language constructs to functions (#13483)
RFC: https://wiki.php.net/rfc/exit-as-function
2024-08-14 12:44:12 +01:00
Ilija Tovilo
be6dee3c5d
Reset seen symbols when ending namespace (GH-15244)
Previously, seen symbols were never cleaned during the compilation of a single
file. This makes it impossible to use a class or function from a different
namespace if such a symbol is also declared within the same file. This is
inconsistent with how it would work when split into different files.
2024-08-13 15:47:14 +02:00
Ilija Tovilo
a4772a0c47
[skip ci] Remove unclosed vim code folding 2024-08-12 18:50:38 +02:00
Gina Peter Banyard
0a23b0678d
Deprecate using "_" as a class name (#15360)
RFC: https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_using_a_single_underscore_as_a_class_name
2024-08-12 16:10:30 +01:00
Ilija Tovilo
50217b35ea
Remove IS_STATIC_VAR_UNINITIALIZED (#15227)
This flag was never necessary. We know a static variable is uninitialized (i.e.
the initializer has never been called) iff the zval in the static variable array
does not contain a reference.

Prompted by a related issue in ext-uopz reported by Christoph.
2024-08-05 11:19:13 +02:00
Tim Düsterhus
551038bb16
zend_compile: Fully remove ZEND_DIM_ALTERNATIVE_SYNTAX (#14974)
This flag is longer set since the merge of property hooks in
780a8280d2. This patch removes it completely,
because the corresponding error messages are unreachable.
2024-07-16 16:27:46 +02:00
Ilija Tovilo
780a8280d2
[RFC] Property hooks (#13455)
RFC: https://wiki.php.net/rfc/property-hooks

Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>
2024-07-14 11:55:03 +02:00
Arnaud Le Blanc
0bd260218b
Fix stack limit on ASAN/MSAN (#14771)
Increase the reserved stack size in ASAN builds, as instrumentation use more stack.
Increase the max allowed stack size in some tests, and enable these tests under ASAN.
Use __builtin_frame_address(0), instead of some stack variable, when we need a stack address, as ASAN may store local variables outside of the real stack.
2024-07-03 19:23:34 +02:00
Benjamin Eberlei
72c874691b
RFC: Add #[\Deprecated] Attribute (#11293)
see https://wiki.php.net/rfc/deprecated_attribute

Co-authored-by: Tim Düsterhus <tim@tideways-gmbh.com>
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
2024-07-02 09:44:25 +02:00
Niels Dossche
c97885b3cc
Merge branch 'PHP-8.3'
* PHP-8.3:
  Factor out common check for short-circuited ast
  Fix OSS-Fuzz #69765: Yield reference to nullsafe chain
2024-06-30 13:38:58 +02:00
Niels Dossche
015b5195ae
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  Factor out common check for short-circuited ast
  Fix OSS-Fuzz #69765: Yield reference to nullsafe chain
2024-06-30 13:38:44 +02:00
Niels Dossche
8fd095669a
Factor out common check for short-circuited ast 2024-06-30 13:38:14 +02:00
Niels Dossche
d568337680
Fix OSS-Fuzz #69765: Yield reference to nullsafe chain
You cannot return or yield a reference to a nullsafe chain. This was
checked already in zend_compile_return but not yet in
zend_compile_yield.

Closes GH-14716.
2024-06-30 13:38:06 +02:00
Derick Rethans
9b5c15ba98 Remove superfluous whitespace 2024-06-26 08:06:41 -05:00
Derick Rethans
df7d304b62 Emit opcode for frameless functions at line number where the function call starts 2024-06-26 08:06:41 -05:00
Tim Düsterhus
2c5ed50d5c
zend_compile: Add support for %d to sprintf() optimization (#14561)
* zend_compile: Rename `string_placeholder_count` to `placeholder_count` in `zend_compile_func_sprintf()`

This is intended to make the diff of a follow-up commit smaller.

* zend_compile: Add support for `%d` to `sprintf()` optimization

This extends the existing `sprintf()` optimization by support for the `%d`
placeholder, which effectively equivalent to an `(int)` cast followed by a
`(string)` cast.

For a synthetic test using:

    <?php

    $a = 'foo';
    $b = 42;

    for ($i = 0; $i < 100_000_000; $i++) {
        sprintf("%s-%d", $a, $b);
    }

This optimization yields a 1.3× 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 ± σ):      3.296 s ±  0.094 s    [User: 3.287 s, System: 0.005 s]
      Range (min … max):    3.213 s …  3.527 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.300 s ±  0.025 s    [User: 4.290 s, System: 0.007 s]
      Range (min … max):    4.266 s …  4.334 s    10 runs

    Summary
      sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php ran
        1.30 ± 0.04 times faster than /tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php

* Fix sprintf_rope_optimization_003.phpt test expecation for 32-bit integers

* zend_compile: Indent switch-case labels in zend_compile_func_sprintf()

* Add GMP test to sprintf() rope optimization

* Add `%s` test case to sprintf() GMP test
2024-06-17 17:07:50 +02:00
Bob Weinand
6a2c5318f9
Optimize observers (#13649)
Inline the lookup whether a function is observed at all.
This strategy is also used for FRAMELESS calls. If the frameless call is observed, we instead allocate a call frame and push the arguments, to call the the function afterwards.
Doing so is still a performance benefit as opposed to executing individual INIT_FCALL+SEND_VAL ops. Thus, even if the frameless call turns out to be observed, the call overhead is slightly lower than before.
If the internal function is not observed at all, the unavoidable overhead is fetching the FLF zend_function pointer and the run-time cache needs to be inspected.

As part of this work, it turned out to be most viable to put the result operand on the ZEND_OP_DATA instead of ZEND_FRAMELESS_ICALL_3, allowing seamless interoperability with the DO_ICALL opcode.
This is a bit unusual in comparison to all other ZEND_OP_DATA usages, but seems to not pose problems overall.

There is also a small issue resolved: trampolines would always use the ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER function due to zend_observer_fcall_op_array_extension being set to -1 too late.
2024-06-15 14:42:27 +02:00
Tim Düsterhus
1e7aac315e
zend_compile: Optimize sprintf() into a rope (#14546)
* 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>
2024-06-13 10:41:45 +02:00
Peter Kokot
5d3fab9334
Sync #if/ifdef/defined (#14520)
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)
2024-06-11 22:47:05 +02:00
Ilija Tovilo
2c91b7364b
Also use zval_get_double for op1 in pow comp time check
Mostly for consistency, but this will also allow evaluating more expressions at
compile time.
2024-05-22 16:30:03 +02:00
Jorg Sowa
23afe57f01
Added deprecation Division by zero when using power with zero as base and negative exponent
RFC: https://wiki.php.net/rfc/raising_zero_to_power_of_negative_number

Closes GH-13128
2024-05-22 15:05:47 +02:00