568 Commits
Author SHA1 Message Date
Daniel Scherzer 4a51e519d7 Merge branch 'PHP-8.6'
* PHP-8.6:
  [`%pS` migration] Use `%pS` in ext/spl/spl_observer.c
  [`%pS` migration] Use `%pS` in ext/spl/spl_iterators.c
  [`%pS` migration] Use `%pS` in ext/spl/spl_heap.c
  [`%pS` migration] Use `%pS` in ext/spl/spl_directory.c
  [`%pS` migration] Use `%pS` in ext/spl/spl_array.c
  [`%pS` migration] Use `%pS` in ext/spl/php_spl.c
2026-10-23 20:34:02 -07:00
Daniel Scherzer ff85732a0e [%pS migration] Use %pS in ext/spl/spl_array.c 2026-10-23 19:38:22 -07:00
Nicolas Grekas 41ecd7c9ec ext/spl: Use fast ZPP in hot ArrayObject and ArrayIterator methods (#23946)
`return new \ArrayIterator($this->items);` is the usual getIterator() implementation of Twig nodes, Symfony bags or Doctrine collections, and profiling a foreach over such objects shows zend_parse_parameters() taking about 180 instructions per ArrayIterator::__construct() call. This switches both constructors and the ArrayAccess methods (offsetExists(), offsetGet(), offsetSet(), offsetUnset(), append()) to fast ZPP. Accepted types, error messages and deprecations don't change.

Instructions per operation (callgrind, -O2 build, arrays of 0/5/100 elements): new ArrayIterator() -181, i.e. -16.5%/-13.8%/-6.6%, and -11.4%/-4.7%/-0.4% when followed by foreach. new ArrayObject() -199, i.e. -17.8%/-14.9%/-7.2%, and -8.7%/-4.2%/-0.4% with foreach. offsetGet() and friends called as methods, e.g. via parent::offsetSet() in subclasses, are 39% to 43% cheaper. Walking Twig's node trees with foreach (17.6k nodes): -4.2% per round. The binary grows by 472 bytes of text.
2026-09-27 20:42:19 +01:00
Dmytro Kulyk 67135cb97b gen_stub: Conditionally include zend_attributes.h to arginfo based on usage (#21570)
Headers required by the generated code (zend_attributes.h, zend_constants.h, zend_enum.h) are collected during generation and emitted as includes at the top of the arginfo file, with the same preprocessor conditions and PHP version guards as the code that needs them.

Removes the manual zend_attributes.h and zend_enum.h includes from sources that only needed them for the arginfo file they include.
2026-09-06 21:25:20 +02:00
Gina Peter Banyard e95647ce36 spl: deprecate ArrayIterator methods that make little sense
RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_arrayiterator_methods_that_inherit_arrayobject_implementation
2026-08-10 18:21:19 +01:00
Gina Peter Banyard 049f7e8dd0 spl: use zend_call_known_function() when possible (#22972)
As we don't need to do function cache shenanigans on those calls.
2026-07-31 17:43:31 +01:00
Gina Peter Banyard 6f0aa11d23 ext/spl/ArrayObject: handle ZPP for each sort methods directly 2026-06-23 18:04:13 +01:00
Ilia Alshanetsky 917f3ea127 Merge branch 'PHP-8.5'
* PHP-8.5:
  Fix use-after-free when ArrayObject sort comparator replaces backing store
2026-06-15 07:39:18 -04:00
Ilia Alshanetsky 2dfc0442fd Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
  Fix use-after-free when ArrayObject sort comparator replaces backing store
2026-06-15 07:36:55 -04:00
Ilia Alshanetsky 2210fda0e1 Fix use-after-free when ArrayObject sort comparator replaces backing store
spl_array_method() caches the backing HashTable pointer across a
user-supplied comparator (uasort/uksort and the sort handlers). The
comparator can re-enter __construct() or __unserialize(), which route
through spl_array_set_array() and swap intern->array out from under the
cached pointer, leaving the post-sort cleanup to release and dereference
freed memory. Mirror the nApplyCount guard the other mutators already
use so replacing the backing store during a sort throws instead.

Closes GH-22310
2026-06-15 07:33:50 -04:00
Tim Düsterhus 69e023fd84 ext/*: Make X_from_obj(zend_object *obj) functions macros (#22183)
* ext/*: Make `X_from_obj(zend_object *obj)` functions macros

With the introduction of the `ZEND_CONTAINER_OF()` macro we can now preserve
whether or not the `zend_object *` is `const` when extracting the
class-specific struct. This change will allow to use `const zend_object *` in
more locations.

Changes performed with Coccinelle followed by some manual cleanup for comment
and whitespace formatting:

    @a@
    attribute name zend_always_inline;
    type T;
    identifier obj;
    identifier f;
    typedef zend_object;
    @@

     T* f(zend_object *obj) { return ZEND_CONTAINER_OF(obj, T, std); }
    + #define f(obj) ZEND_CONTAINER_OF(obj, T, std)

    @@
    identifier a.f;
    @@

    - f(...) { ... }

    @b@
    attribute name zend_always_inline;
    type T;
    identifier obj;
    identifier f;
    typedef zend_object;
    @@

     T* f(zend_object *obj) { return ZEND_CONTAINER_OF(obj, T, zo); }
    + #define f(obj) ZEND_CONTAINER_OF(obj, T, zo)

    @@
    identifier b.f;
    @@

    - f(...) { ... }

* sockets: Fix build

* odbc: Fix build
2026-06-01 10:21:03 +02:00
Arshid d61ff7cddd ext/spl: ArrayObject no longer accepts arbitrary Iterators during unserialization (#22090)
This aligns the behaviour with the constructor of ArrayObject.
2026-05-29 13:23:55 +01:00
Tim Düsterhus ad7cce6527 zend_portability: Add ZEND_CONTAINER_OF() (#21903)
* zend_portability: Add `ZEND_CONTAINER_OF()`

* tree-wide: Use `ZEND_CONTAINER_OF()`

Changes made with Coccinelle:

    @@
    type T_container;
    identifier member;
    expression e;
    @@

    - (T_container *)(((char *)(e)) - offsetof(T_container, member))
    + ZEND_CONTAINER_OF(e, T_container, member)

    @@
    type T_container;
    identifier member;
    expression e;
    typedef uintptr_t;
    @@

    - (T_container *)(((uintptr_t)(e)) - offsetof(T_container, member))
    + ZEND_CONTAINER_OF(e, T_container, member)

    @@
    type T_container;
    identifier member;
    expression e;
    @@

    - (const T_container *)(((char *)(e)) - offsetof(T_container, member))
    + ZEND_CONTAINER_OF(e, T_container, member)

    @@
    type T_container;
    identifier member;
    expression e;
    typedef uintptr_t;
    @@

    - (const T_container *)(((uintptr_t)(e)) - offsetof(T_container, member))
    + ZEND_CONTAINER_OF(e, T_container, member)

* bcmath: Fix `get_bcmath_number_from_obj()` const-correctness

A follow-up change to the new `ZEND_CONTAINER_OF()` macro will preserve the
`const`-ness of the input pointer. By wrapping this macro inside a macro rather
an an inline function we can preserve the `const`-ness across all layers.

* zend_portability: Keep `const`-ness in `ZEND_CONTAINER_OF()`

* zend_portability: Add C++ version to `ZEND_CONTAINER_OF()`
2026-05-19 10:47:00 +02:00
Tim Düsterhus 7114314c5a tree-wide: Replace XtOffsetOf by its definition (#21899)
`offsetof()` is in `stddef.h` and thus always available. The extra macro is an
unnecessary layer of indirection.
2026-04-28 22:12:56 +02:00
Ben Ramsey 07d3b6cf70 license-update: ext/spl source headers
RFC: https://wiki.php.net/rfc/php_license_update
2026-04-11 21:20:54 -05:00
Gina Peter Banyard b3f2a3db4e Merge branch 'PHP-8.5'
* PHP-8.5:
  Revert 49b2ff5dbb to fix bug GH-21499
2026-03-26 11:00:37 +00:00
Gina Peter Banyard 8275b522d2 Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
  Revert 49b2ff5dbb to fix bug GH-21499
2026-03-26 10:59:49 +00:00
Gina Peter Banyard e912c022fd Revert 49b2ff5dbb to fix bug GH-21499
The fix for this was to take hold of a pointer of the bucket, something that should not be done as it causes memory corruptions

Closes GH-21532, GH-21520, GH-21499
2026-03-26 10:58:13 +00:00
Gina Peter Banyard 4bfa1b64b0 ext/spl: add const qualifiers when dealing with CEs (#21512) 2026-03-25 13:30:34 +00:00
Alexandre Daubois da238e7a11 ext/spl: convert zend_parse_parameters_none() to fast ZPP (#20441) 2025-11-10 23:31:58 +00:00
Tim Düsterhus 7f1cc0ec32 spl: Use true / false instead of 1 / 0 for bool parameters
Changes done with Coccinelle:

    @r1@
    identifier F;
    identifier p;
    typedef bool;
    parameter list [n1] PL1;
    parameter list [n2] PL2;
    @@

    F(PL1, bool p, PL2) {
    ...
    }

    @r2@
    identifier r1.F;
    expression list [r1.n1] EL1;
    expression list [r1.n2] EL2;
    @@

    F(EL1,
    (
    - 1
    + true
    |
    - 0
    + false
    )
    , EL2)
2025-09-24 18:51:40 +02:00
Tim Düsterhus 60f8969f7d spl: Use return true / return false for functions returning bool
Changes done with Coccinelle:

    @r1@
    identifier fn;
    typedef bool;
    symbol false;
    symbol true;
    @@

    bool fn ( ... )
    {
    <...
    return
    (
    - 0
    + false
    |
    - 1
    + true
    )
    ;
    ...>
    }

Coccinelle patch sourced from
torvalds/linux@46b5c9b856.
2025-09-24 18:51:40 +02:00
Tim Düsterhus 15baf35cf0 spl: Use true / false instead of 1 / 0 when assigning to bool
Changes done with Coccinelle:

    @@
    bool b;
    @@

    - b = 0
    + b = false

    @@
    bool b;
    @@

    - b = 1
    + b = true
2025-09-24 18:51:40 +02:00
Alexandre Daubois 49e3956b70 core: Deprecate using null as an array offset and when calling array_key_exists() (#19511)
RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_using_values_null_as_an_array_offset_and_when_calling_array_key_exists
2025-09-04 22:12:24 +01:00
Gina Peter Banyard fb87b14b6c ext/spl: Deprecate ArrayObject and ArrayIterator with objects (#19420)
RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_arrayobject_and_arrayiterator_with_objects

This also moves tests into a subfolder.
2025-08-14 12:38:57 +01:00
Gina Peter Banyard 50ddf6a68f ext/spl: Refactor ArrayObject sort methods 2025-07-03 21:50:45 +01:00
Niels Dossche 3ba725a556 Merge branch 'PHP-8.4'
* PHP-8.4:
  Fix GH-18309: ipv6 filter integer overflow
  Fix GH-18304: Changing the properties of a DateInterval through dynamic properties triggers a SegFault
2025-04-11 23:36:42 +02:00
Niels Dossche a019fbd970 Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix GH-18309: ipv6 filter integer overflow
  Fix GH-18304: Changing the properties of a DateInterval through dynamic properties triggers a SegFault
2025-04-11 23:36:12 +02:00
Niels Dossche ba0853888d Fix GH-18304: Changing the properties of a DateInterval through dynamic properties triggers a SegFault
For dynamic fetches the cache_slot will be NULL, so we have to check for
that when resetting the cache. For zip and xmlreader this couldn't
easily be tested because of a lack of writable properties.

Closes GH-18307.
2025-04-11 23:33:58 +02:00
Niels Dossche fc047b4e00 Merge branch 'PHP-8.4'
* PHP-8.4:
  [ci skip] Fix NEWS order
  Fix GH-18018: RC1 data returned from offsetGet causes UAF in ArrayObject
2025-03-13 19:11:59 +01:00
Niels Dossche d43d4684bd Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix GH-18018: RC1 data returned from offsetGet causes UAF in ArrayObject
2025-03-13 19:11:24 +01:00
Niels Dossche 27affd8da1 Fix GH-18018: RC1 data returned from offsetGet causes UAF in ArrayObject
We should first check truthiness and only after that destroy the value.

Closes GH-18034.
2025-03-13 19:10:34 +01:00
Niels Dossche d95b9d6d32 Merge branch 'PHP-8.4'
* PHP-8.4:
  Fix GH-17736: Assertion failure zend_reference_destroy()
2025-03-02 22:41:21 +01:00
Niels Dossche ee4a9a4a7c Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Fix GH-17736: Assertion failure zend_reference_destroy()
2025-03-02 22:37:07 +01:00
Niels Dossche ce8ab5f16a Fix GH-17736: Assertion failure zend_reference_destroy()
The cache slot for FETCH_OBJ_W in function `test` is primed with the
class for C. The next call uses a simplexml instance and reuses the same
cache slot. simplexml's get_property_ptr handler does not use the cache
slot, so the old values remain in the cache slot. When
`zend_handle_fetch_obj_flags` is called this is not guarded by a check
for the class entry. So we end up using the prop_info from the property
C::$a instead of the simplexml property.

This patch adds a reset to the cache slots in the property address fetch
code and also in the extensions with a non-standard reference handler.
This keeps the run time cache consistent and avoids the issue without
complicating the fast paths.

Closes GH-17739.
2025-03-02 22:33:32 +01:00
Niels Dossche 8c443016e9 Merge branch 'PHP-8.4'
* PHP-8.4:
  Fix GH-17307: Internal closure causes JIT failure
  Generate inline frameless icall handlers only if the optimization level is set to inline
  Fix GH-15981: Segfault with frameless jumps and minimal JIT
  Fix GH-15833: Segmentation fault (access null pointer) in ext/spl/spl_array.c
2025-01-09 20:01:16 +01:00
Niels Dossche b666dc9788 Fix GH-15833: Segmentation fault (access null pointer) in ext/spl/spl_array.c
We're accessing the object properties table directly in spl, but we're
not accounting for lazy objects. Upon accessing we should trigger the
initialization as spl is doing direct manipulations on the object
property table and expects a real object.

Closes GH-17235.
2025-01-09 19:58:00 +01:00
Ilija Tovilo 0ce151b8fe Merge branch 'PHP-8.4'
* PHP-8.4:
  Add NEWS entry
  Also fix same issue in ArrayObject::exchangeArray()
  Fix use-after-free in ArrayObject::unset() with destructor
2024-11-04 17:50:37 +01:00
Ilija Tovilo 66ad4ce699 Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Add NEWS entry
  Also fix same issue in ArrayObject::exchangeArray()
  Fix use-after-free in ArrayObject::unset() with destructor
2024-11-04 17:49:08 +01:00
Ilija Tovilo dca438e6a3 Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  Add NEWS entry
  Also fix same issue in ArrayObject::exchangeArray()
  Fix use-after-free in ArrayObject::unset() with destructor
2024-11-04 17:47:49 +01:00
Ilija Tovilo f7222bd2de Also fix same issue in ArrayObject::exchangeArray() 2024-11-04 17:46:17 +01:00
Ilija Tovilo 8910ac800d Fix use-after-free in ArrayObject::unset() with destructor
Fixes GH-16646
Closes GH-16653
2024-11-04 17:45:56 +01:00
Ilija Tovilo d21bc7f1e6 Disallow enums in ArrayObject
Closes GH-15775
2024-09-26 22:21:09 +02:00
Niels Dossche 1b171bb6b4 Merge branch 'PHP-8.3'
* PHP-8.3:
  Fix GH-15918: Assertion failure in ext/spl/spl_fixedarray.c
2024-09-20 17:34:54 +02:00
Niels Dossche 9774cedb01 Fix GH-15918: Assertion failure in ext/spl/spl_fixedarray.c
SplFixedArray should've never get supported in ArrayObject because it's
overloaded, and so that breaks assumptions. This regressed in c4ecd82f.

Closes GH-15947.
2024-09-20 17:34:23 +02:00
Arnaud Le Blanc 1fbb666545 Use zend_std_build_properties() to access zend_object.properties
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
2024-07-18 22:18:38 +02:00
Gina Peter Banyard 5337172508 ext/spl: Use ArrayObject object handlers for ArrayIterator
They are the same
2024-06-15 01:33:09 +01:00
Gina Peter Banyard 809410423f ext/spl: Refactor debug handlers
Mainly to use zend_mangle_property_name() directly instead of spl_gen_private_prop_name()
2024-06-15 01:33:09 +01:00
Gina Peter Banyard 54047c1090 ext/spl: Remove some useless header includes and clarify usages 2024-06-15 01:33:09 +01:00
Gina Peter Banyard fd2d869642 Clean-up some more headers (#14416)
Remove unused headers (such as php_ini.h for extensions that don't define INI settings)
Use more specific headers when possible
2024-06-08 17:15:36 +01:00