All other code caters to dereferencing array elements, except the
unserialize handler. This causes references to be present in the fixed
array even though this seems not intentional as reference assign is
otherwise impossible.
On 8.5+ this causes an assertion failure. On 8.3+ this causes references
to be present where they shouldn't be.
Closes GH-20616.
It was possible to make the heap accept unserialize data when the heap
was corrupted or under modification. This adds the necessary check to
prevent that from happening.
Also, the exception check at the bottom is pointless,
spl_heap_unserialize_internal_state() already returns FAILURE on
exception. If it *is* necessary, it should be documented why.
Closes GH-20109.
Exposing INDIRECTs to userland is not allowed and can lead to all sorts
of wrong behaviour. In this case it lead to UAF bugs.
Solve it by duplicating the properties table, which de-indirects the
elements and also decouples it for future modifications.
Closes GH-20102.
Instead of
* adding a zval on the stack
* initializing it
* copying the value to the attribute
Just initialize the value directly in the zend_attribute_arg
* Move glob to main/ from win32/
In preparation to make the Win32 reimplementation the standard
cross-platform one. Currently, it doesn't do that and just passes
through the original glob implementation. We could consider also having
an option to use the standard glob for systems that have a sufficient
one.
* Enable building with win32 glob on non-windows
Kind of broken. We're namespacing the function and struct, but not yet
the GLOB_* defines. There are a lot of places callers check if i.e.
NOMATCH is defined that would likely become redundant.
Currently it also has php_glob and #defines glob php_glob (etc.) - I
suspect doing the opposite and changing the callers would make more
sense, just doing MVP to geet it to build (even if it fails tests).
* Massive first pass at conversion to internal glob
Have not tested yet. the big things are:
- Should be invisible to userland PHP code.
- A lot of :%s/GLOB_/PHP_GLOB_/g; the diff can be noisy as a result,
especially in comments.
- Prefixes everything with PHP_ to avoid conflicts with system glob in
case it gets included transitively.
- A lot of weird shared definitions that were sprawled out to other
headers are now included in php_glob.h.
- A lot of (but not yet all cases) of HAVE_GLOB are removed, since we
can always fall back to php_glob.
- Using the system glob is not wired up yet; it'll need more shim
ifdefs for each flag type than just glob_t/glob/globfree defs.
* Fix inclusion of GLOB_ONLYDIR
This is a GNU extension, but we don't need to implement it, as the GNU
implementation is flawed enough that callers have to manually filter it
anyways; just provide a stub definition for the constant.
We could consideer implementing this properly later. For now, fixes the
basic glob constant tests.
* Remove HAVE_GLOBs
We now always have a glob implementation that works. HAVE_GLOB should
only be used to check if we have a system implementation, for if we
decide to wrap the system implementation instead.
* We don't need to care about being POSIXly correct for internal glob
* Check for reallocarray
Ideally temporary until GH-17433.
* Forgot to move this file from win32/ to main/
* Check for issetugid (BSD function)
* Allow using the system glob with --enable-system-glob
* Style fix after removing ifdef
* Remove empty case for system glob
* 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
* 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
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.
If the array is packed, then we don't have to loop to get the highest
index.
For this script:
```php
$array = range(1, 100);
for ($i=0;$i<1000000;$i++) {
SplFixedArray::fromArray($array);
}
```
On an i7-4790:
```
Benchmark 1: ./sapi/cli/php spl.php
Time (mean ± σ): 376.5 ms ± 2.0 ms [User: 372.1 ms, System: 2.6 ms]
Range (min … max): 373.7 ms … 379.5 ms 10 runs
Benchmark 2: ./sapi/cli/php_old spl.php
Time (mean ± σ): 511.6 ms ± 1.9 ms [User: 508.0 ms, System: 2.3 ms]
Range (min … max): 509.2 ms … 515.1 ms 10 runs
Summary
./sapi/cli/php spl.php ran
1.36 ± 0.01 times faster than ./sapi/cli/php_old spl.php
```
On an i7-1185G7:
```
Benchmark 1: ./sapi/cli/php spl.php
Time (mean ± σ): 250.4 ms ± 3.5 ms [User: 246.6 ms, System: 2.6 ms]
Range (min … max): 247.0 ms … 258.5 ms 11 runs
Benchmark 2: ./sapi/cli/php_old spl.php
Time (mean ± σ): 328.4 ms ± 1.0 ms [User: 324.4 ms, System: 3.8 ms]
Range (min … max): 327.5 ms … 331.0 ms 10 runs
Summary
./sapi/cli/php spl.php ran
1.31 ± 0.02 times faster than ./sapi/cli/php_old spl.php
```
Bonus: this also decreases the code size of the function.
If there is not yet a dynamic property, and there are no class properties,
then we know that we don't have to build a properties table.
For this (micro-bench) script:
```php
function x() {
$fa = new SplFixedArray(1);
$fa[0] = $fa;
}
for ($i=0;$i<1000000;$i++)
x();
```
On an i7-4790:
```
Benchmark 1: ./sapi/cli/php spl.php
Time (mean ± σ): 140.9 ms ± 1.2 ms [User: 137.5 ms, System: 2.7 ms]
Range (min … max): 138.9 ms … 144.9 ms 21 runs
Benchmark 2: ./sapi/cli/php_old spl.php
Time (mean ± σ): 162.0 ms ± 3.8 ms [User: 157.7 ms, System: 3.2 ms]
Range (min … max): 158.5 ms … 175.0 ms 17 runs
Summary
./sapi/cli/php spl.php ran
1.15 ± 0.03 times faster than ./sapi/cli/php_old spl.php
```
We can use the optimized packed filling code instead of going through
all the logic of the zend_hash update APIs.
For this script:
```php
$test = new SplFixedArray(4);
$test[0] = 0;
$test[1] = 1;
$test[2] = 2;
$test[3] = 3;
for ($i = 0 ; $i< 5000000; $i++)
$test->toArray();
```
On an i7-4790:
```
Benchmark 1: ./sapi/cli/php toarray.php
Time (mean ± σ): 170.0 ms ± 1.8 ms [User: 167.3 ms, System: 2.2 ms]
Range (min … max): 166.9 ms … 173.0 ms 17 runs
Benchmark 2: ./sapi/cli/php_old toarray.php
Time (mean ± σ): 215.7 ms ± 3.6 ms [User: 211.9 ms, System: 3.0 ms]
Range (min … max): 211.3 ms … 222.0 ms 13 runs
Summary
./sapi/cli/php toarray.php ran
1.27 ± 0.02 times faster than ./sapi/cli/php_old toarray.php
```
On an i7-1185G7:
```
Benchmark 1: ./sapi/cli/php toarray.php
Time (mean ± σ): 112.6 ms ± 1.4 ms [User: 109.6 ms, System: 2.9 ms]
Range (min … max): 111.1 ms … 116.4 ms 25 runs
Benchmark 2: ./sapi/cli/php_old toarray.php
Time (mean ± σ): 145.3 ms ± 2.8 ms [User: 141.8 ms, System: 3.4 ms]
Range (min … max): 142.6 ms … 151.8 ms 20 runs
Summary
./sapi/cli/php toarray.php ran
1.29 ± 0.03 times faster than ./sapi/cli/php_old toarray.php
```
This patch optimizes reading and writing from SplFixedArray with the
dimension operators. It accomplishes this due to the following
optimizations:
* Fast-path for long keys (inlined).
* Optimization hints (UNEXPECTED + assertion)
* Using an unsigned index so we can do a single length comparison
For the following script:
```php
$test = new SplFixedArray(4);
for ($i = 0 ; $i< 5000000; $i++)
$test[1] += $i;
```
On an i7-4790:
```
Benchmark 1: ./sapi/cli/php x.php
Time (mean ± σ): 95.4 ms ± 1.6 ms [User: 91.5 ms, System: 3.2 ms]
Range (min … max): 93.7 ms … 100.8 ms 31 runs
Benchmark 2: ./sapi/cli/php_old x.php
Time (mean ± σ): 119.1 ms ± 1.3 ms [User: 114.7 ms, System: 3.6 ms]
Range (min … max): 117.6 ms … 123.1 ms 24 runs
Summary
./sapi/cli/php x.php ran
1.25 ± 0.03 times faster than ./sapi/cli/php_old x.php
```
On an i7-1185G7:
```
Benchmark 1: ./sapi/cli/php x.php
Time (mean ± σ): 67.9 ms ± 1.1 ms [User: 64.8 ms, System: 3.2 ms]
Range (min … max): 66.6 ms … 72.8 ms 43 runs
Benchmark 2: ./sapi/cli/php_old x.php
Time (mean ± σ): 84.8 ms ± 1.1 ms [User: 81.0 ms, System: 3.9 ms]
Range (min … max): 82.6 ms … 88.0 ms 34 runs
Summary
./sapi/cli/php x.php ran
1.25 ± 0.03 times faster than ./sapi/cli/php_old x.php
```