Commit graph

470 commits

Author SHA1 Message Date
Tim Düsterhus
45d1acf916
Zend: Fix reference counting for Closures in const-expr (#17853)
* Clean up closure static variable handling

* Zend: Fix reference counting for Closures in const-expr

Fixes php/php-src#17851

---------

Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
2025-03-27 10:11:44 +01:00
Jakub Zelenka
6976fb6ba7
Merge branch 'PHP-8.3' into PHP-8.4 2025-03-11 22:23:09 +01:00
Ilija Tovilo
ef2c459941
Use-after-free for ??= due to incorrect live-range calculation
Fixes GHSA-rwp7-7vc6-8477
2025-03-11 22:10:21 +01:00
Ilija Tovilo
901ce61105
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix ZEND_MATCH_ERROR misoptimization
2024-12-12 13:11:29 +01:00
Ilija Tovilo
cdfd960150
Fix ZEND_MATCH_ERROR misoptimization
op1 of ZEND_MATCH_ERROR, which refers to the match expression, is not freed by
MATCH_ERROR itself. Instead, it is freed by ZEND_HANDLE_EXCEPTION. For normal
control flow, a FREE is placed at the end of the match expression.

Since FREE may appear after MATCH_ERROR in the opcode sequence, we need to
correctly handle op1 of MATCH_ERROR as alive.

Fixes GH-17106
Closes GH-17108
2024-12-12 13:10:34 +01: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
Máté Kocsis
f2e199e878
Implement "support doc comments for internal classes and functions" (#13266)
Fixes #13130
2024-02-25 08:41:31 +01:00
Ilija Tovilo
631bc81607
Implement stackless internal function calls
Co-authored-by: Dmitry Stogov <dmitry@zend.com>

Closes GH-12461
2024-02-06 17:42:28 +01:00
Dmitry Stogov
fd58f61a22 Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  Fix assertion
2023-12-25 13:22:39 +03:00
Dmitry Stogov
5350952a37 Fix assertion
Fixes oss-fuzz #65233
2023-12-25 13:22:03 +03:00
ju1ius
3e0e7e3f90
releases property attributes of internal classes (#11980)
* adds test case for internal class property attribute

* releases property attributes of internal classes
2023-08-24 16:07:00 +02:00
George Peter Banyard
82972f448f Merge branch 'PHP-8.2'
* PHP-8.2:
  Fix various bugs related to DNF types
2023-08-15 17:01:51 +01:00
George Peter Banyard
02a80c5b82 Fix various bugs related to DNF types
- GH-11958: DNF types in trait properties do not get bound properly
 - GH-11883: Memory leak in zend_type_release() for non-arena allocated DNF types
 - Internal trait bound to userland class would not be arena allocated
 - Property DNF types were not properly deep copied during lazy loading

Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
Co-authored-by: ju1ius <jules.bernable@gmail.com>
2023-08-15 15:34:33 +01:00
Ilija Tovilo
0b1d750d91
Allow arbitrary expressions in static variable initializer
Closes GH-9301
2023-05-24 20:17:31 +02:00
Max Kellermann
d5c649b36b
zend_compiler, ...: use uint8_t instead of zend_uchar (#10621)
`zend_uchar` suggests that the value is an ASCII character, but here,
it's about very small integers.  This is misleading, so let's use a
C99 integer instead.

On all architectures currently supported by PHP, `zend_uchar` and
`uint8_t` are identical.  This change is only about code readability.
2023-02-23 14:56:54 +00:00
Niels Dossche
821fc55a68
Implement GH-9826: Make class_alias() work with internal classes (#10483)
We can't increase the refcount of internal classes during request time.
To work around this problem we simply don't refcount aliases anymore and
add a check in the destruction to skip aliases entirely.
There were also some checks which checked for an alias implicitly by
comparing the refcount, these have been replaced by checking the type of
the zval instead.
2023-02-22 11:47:32 +01:00
Dmitry Stogov
482ae71fda Fix memory leak 2022-10-31 12:20:28 +03:00
Ilija Tovilo
fe0eaf107a
Fix UB pointer arithmetics on NULL
Closes GH-9559
2022-09-16 18:24:39 +02:00
Bob Weinand
dc5475c191 Save previous observer on the VM stack
This avoids a possible significant performance penalty, when some leaf function was observed, deep in the stack.
As a side effect, we are not iterating over prev_execute_data anymore and thus, non-observed fake frames, possibly on stack, cannot have any impact on the observer anymore (especially within zend_observer_fcall_end_all).

Saving the previous observer happens now directly on the VM stack. If there is any observer, function frames are allocated an extra zval (the last temporary), which will, on observed frames, contain the previous observed frame address.
2022-08-04 17:16:27 +02:00
Ilija Tovilo
76fcd70c13
Fix enum preloading again (#8859) 2022-06-25 14:55:46 +02:00
Ilija Tovilo
ddc0b490f7
Allow arbitrary const expressions in backed enums
Closes GH-7821
Closes GH-8190
Closes GH-8418
2022-06-12 22:56:05 +02:00
Dmitry Stogov
f135ed9a8a Fix memory leak
This fixes oss-fuzz #47527
2022-05-23 13:33:20 +03:00
Dmitry Stogov
f080a90a88 Merge branch 'PHP-8.1'
* PHP-8.1:
  Fix memory leak
2022-05-11 11:47:38 +03:00
Dmitry Stogov
b1b79c74fb Fix memory leak
This fixes oss-fuzz #47088
2022-05-11 11:43:01 +03:00
Nikita Popov
fbb7393997 Handle other DO_FCALL opcodes in NEW live range calculation
Make this robust against the case where NEW is terminated by
something other than DO_FCALL, e.g. DO_UCALL. This can't currently
happen.
2022-04-17 22:56:23 +02:00
Bob Weinand
185a14685d Merge branch 'PHP-8.1' 2022-03-07 22:17:35 +01:00
Bob Weinand
a44d99fe23 Merge branch 'PHP-8.0' into PHP-8.1 2022-03-07 22:06:58 +01:00
Tim Düsterhus
0d7e10c1a9 Fix memory leak of function attribute hash table (#8070)
==109253== 280 (56 direct, 224 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
    ==109253==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==109253==    by 0x6D9FA2: __zend_malloc (zend_alloc.c:3068)
    ==109253==    by 0x745138: zend_add_attribute (zend_attributes.c:226)
    ==109253==    by 0x6680D1: zend_add_parameter_attribute (zend_attributes.h:102)
    ==109253==    by 0x66B787: zm_startup_zend_test (test.c:478)
    ==109253==    by 0x7224CD: zend_startup_module_ex (zend_API.c:2202)
    ==109253==    by 0x72252C: zend_startup_module_zval (zend_API.c:2217)
    ==109253==    by 0x734288: zend_hash_apply (zend_hash.c:2011)
    ==109253==    by 0x722C30: zend_startup_modules (zend_API.c:2328)
    ==109253==    by 0x67409B: php_module_startup (main.c:2256)
    ==109253==    by 0x88EDDE: php_cli_startup (php_cli.c:409)
    ==109253==    by 0x890F61: main (php_cli.c:1334)
2022-03-07 22:05:40 +01:00
Nikita Popov
4543cd32ae Remove JMPZNZ opcode
While JMPZNZ can avoid execution of a separate JMP opcode in some
cases, it also prevents smart branch optimization, so creating
JMPZNZ may actually have a negative effect. It also adds additional
complexity for optimizations.

Drop JMPZNZ in favor of JMPZ+JMP or JMPNZ+JMP.

Closes GH-7857.
2022-01-10 22:07:10 +01:00
Tyson Andre
024d5f4b63 Cache method overrides of ArrayAccess in zend_class_entry
Previously, code such as subclasses of SplFixedArray would check for method
overrides when instantiating the objects.

This optimization was mentioned as a followup to GH-6552
2021-12-04 11:35:38 -05:00
Nikita Popov
24485aa343 Merge branch 'PHP-8.1'
* PHP-8.1:
  Fix inheritance of class constants if mutable data used
2021-11-17 12:24:25 +01:00
Nikita Popov
44e5d25300 Fix inheritance of class constants if mutable data used
Class constants from parents should always be directly reused,
rather than re-evaluated as a separate copy. Previously this used
to happen automatically, as we'd just inherit the class constant
entry from the parent class. With mutable data there may now be
a separate copy of the constant, so we need to use that copy
when updating constants. Otherwise we may evaluate the same
constant multiple times.

Closes GH-7658.
2021-11-17 12:23:47 +01:00
Nikita Popov
b6b820e532 Merge branch 'PHP-8.1'
* PHP-8.1:
  Fix COPY_TMP live range construction with optimization
2021-11-11 10:36:54 +01:00
Nikita Popov
1039852fec Merge branch 'PHP-8.0' into PHP-8.1
* PHP-8.0:
  Fix COPY_TMP live range construction with optimization
2021-11-11 10:36:45 +01:00
Nikita Popov
8c4a7f20f5 Fix COPY_TMP live range construction with optimization
The use may be optimized away, leaving us only with the free use.
Also fix off-by-one error in the other optimization case.
2021-11-11 10:35:34 +01:00
Dmitry Stogov
90b7bde615 Use more compact representation for packed arrays.
- for packed arrays we store just an array of zvals without keys.
- the elements of packed array are accessible throuf as ht->arPacked[i]
  instead of ht->arData[i]
- in addition to general ZEND_HASH_FOREACH_* macros, we introduced similar
  familied for packed (ZEND_HASH_PACKED_FORECH_*) and real hashes
  (ZEND_HASH_MAP_FOREACH_*)
- introduced an additional family of macros to access elements of array
  (packed or real hashes) ZEND_ARRAY_ELEMET_SIZE, ZEND_ARRAY_ELEMET_EX,
  ZEND_ARRAY_ELEMET, ZEND_ARRAY_NEXT_ELEMENT, ZEND_ARRAY_PREV_ELEMENT
- zend_hash_minmax() prototype was changed to compare only values

Because of smaller data set, this patch may show performance improvement
on some apps and benchmarks that use packed arrays. (~1% on PHP-Parser)

TODO:
    - sapi/phpdbg needs special support for packed arrays (WATCH_ON_BUCKET).
    - zend_hash_sort_ex() may require converting packed arrays to hash.
2021-11-03 15:18:26 +03:00
Nikita Popov
8360e9d6d1 Merge branch 'PHP-8.0' into PHP-8.1
* PHP-8.0:
  Fix COPY_TMP live range construction after optimization
2021-10-05 11:28:41 +02:00
Nikita Popov
bbd3f714d7 Fix COPY_TMP live range construction after optimization
If we optimize the FREE away, we should switch to constructing
a normal live range, rather than a split live range.

Fixes oss-fuzz #39548.
2021-10-05 11:28:16 +02:00
Nikita Popov
7879544022 Merge branch 'PHP-8.0' into PHP-8.1
* PHP-8.0:
  Handle SWITCH_STRING with optimized away FREE
2021-09-16 11:33:08 +02:00
Nikita Popov
7257e7e5aa Handle SWITCH_STRING with optimized away FREE
This can happen in degenerate cases where we know that the
SWITCH_STRING argument is not refcounted. We should be treating it
in the same way as SWITCH_LONG here.
2021-09-16 11:31:06 +02:00
Nikita Popov
e011952576
Preload unlinked classes, remove preload autoload (#7311)
Currently, classes that can't be linked get moved back into the original script
and are not preloaded. As such classes may be referenced from functions that
did get preloaded, there is a preload autoload mechanism to load them at
runtime.

Since PHP 8.1, we can safely preload unlinked classes, which will then go
through usual lazy loading. This means that we no longer need the preload
autoload mechanism. However, we need to be careful not to modify any hash
table buckets in-place, and should create new buckets for lazy loaded classes.
2021-07-28 14:27:58 +02:00
Nikita Popov
a374230c15 Add support for internal enums
This adds support for internal enums with the same basic approach
as userland enums. Enum values are stored as CONSTANT_AST and
objects created during constant updating at runtime. This means
that we need to use mutable_data for internal enums.

This just adds basic support and APIs, it does not include the
stubs integration from #7212.

Closes GH-7302.
2021-07-27 09:19:14 +02:00
Nikita Popov
36d2dd087a Remove redundant static_members/mutable_data cleanup
static_members, mutable_data and static vars in methods are cleaned
up during an earlier shutdown phase (because this has to happen
before we destroy the object store). There is no need to repeat
this cleanup when destroying the classes.
2021-07-23 13:01:40 +02:00
Nikita Popov
3eb97a4566 Always use separate static_members_table
When running without opcache, static_members_table is shared with
default_static_members_table. This is visible in reflection output,
because ReflectionProperty::getDefaultValue() will return the
current value, rather than the default value.

Address this by never sharing the table, which matches the behavior
we already see under opcache.

Fixes bug #80821.

Closes GH-7299.
2021-07-23 09:29:32 +02:00
Nikita Popov
79071d5e3e
Don't duplicate internal prop info (#6929)
Userland property infos are no longer duplicated since PHP 7.4, when we
stopped setting SHADOW flags on inherited private properties. Stop duplicating
internal property infos as well.

This requires switching class destruction to work in reverse order, as child
classes may be reusing structures from parent classes, and as such should be
destroyed first.
2021-04-29 20:31:24 +02:00
George Peter Banyard
5caaf40b43
Introduce pseudo-keyword ZEND_FALLTHROUGH
And use it instead of comments
2021-04-07 00:46:29 +01:00
Ilija Tovilo
269c8dac1d
Implement enums
RFC: https://wiki.php.net/rfc/enumerations

Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>

Closes GH-6489.
2021-03-17 19:08:03 +01:00
Nikita Popov
47a2e5c785 Reference dynamic functions through dynamic_defs
Currently, dynamically declared functions and closures are inserted
into the function table under a runtime definition key, and then later
possibly renamed. When opcache is not used and a file containing a
closure is repeatedly included, this leads to a very large memory leak,
as the no longer needed closure declarations will never be freed
(https://bugs.php.net/bug.php?id=76982).

With this patch, dynamic functions are instead stored in a
dynamic_func_defs member on the op_array, which opcodes reference
by index. When the parent op_array is destroyed, the dynamic_func_defs
it contains are also destroyed (unless they are stilled used elsewhere,
e.g. because they have been bound, or are used by a live closure). This
resolves the fundamental part of the leak, though doesn't completely
fix it yet due to some arena allocations.

The main non-obvious change here is to static variable handling:
We can't destroy static_variables_ptr in destroy_op_array, as e.g.
that would clear the static variables in a dynamic function when
the op_array containing it is destroyed. Static variable destruction
is separated out for this reason (we already do static variable
destruction separately for normal functions, so we only need to
handle main scripts).

Closes GH-5595.
2021-03-01 11:35:54 +01:00
Nikita Popov
5d160e309e Fix static variable behavior with inheritance
When a method is inherited, the static variables will now always
use the initial values, rather than the values at the time of
inheritance. As such, behavior no longer depends on whether
inheritance happens before or after a method has been called.

This is implemented by always keeping static_variables as the
original values, and static_variables_ptr as the modified copy.

Closes GH-6705.
2021-02-18 11:18:19 +01:00
Dmitry Stogov
4b79dba932 Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.

PHP  classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.

Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).

The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 22:53:57 +03:00