Skip to content

[pull] master from php:master#938

Merged
pull[bot] merged 7 commits into
turkdevops:masterfrom
php:master
May 18, 2026
Merged

[pull] master from php:master#938
pull[bot] merged 7 commits into
turkdevops:masterfrom
php:master

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented May 18, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

afflerbach and others added 7 commits May 18, 2026 10:31
Co-authored-by: David CARLIER <devnexen@gmail.com>

close GH-22078
* PHP-8.5:
  ext/dom: Fix UAF in custom XPath function
reproducible normally with

```
php -r 'var_dump(new \NumberFormatter("en", \NumberFormatter::DECIMAL)->format(INF));'
```

but could not locally (asan version ?) but mostly due to uninitialised garbage.
regression from 3ed80a1
…#21787)

* [ext/standard] Specialize array_sum()/array_product() for long arrays

The per-element cost of array_sum() and array_product() is dominated by
the add_function/mul_function call dispatch. Add a specialized fast
path for the IS_LONG + IS_LONG case that inlines overflow-aware
arithmetic via fast_long_add_function() and ZEND_SIGNED_MULTIPLY_LONG()
-- the same engine helpers that add_function_fast() dispatches to
internally. The fast path applies to both packed and hash arrays.

On overflow, non-IS_LONG entries, objects, resources or strings,
execution falls through to the generic path in php_array_binop_apply(),
so the PHP 8.3 warning behavior, operator overloading and BC casts for
resources/non-numeric strings are preserved.

Benchmarks (Apple M1, -O2 -DNDEBUG release, median of 7 runs, n=10000
with ~20M total elements per case):

  array_sum, packed long                     42.24 ms ->  12.99 ms  3.25x
  array_product, packed small long (0..9)   144.63 ms ->  19.39 ms  7.46x
  array_product, packed range(1, 100)        82.94 ms ->  58.66 ms  1.41x
  array_sum, hash long                       41.95 ms ->  12.90 ms  3.25x
  array_product, hash small long (0..9)      69.90 ms ->  19.40 ms  3.60x
  packed/hash float, mixed IS_LONG/IS_DOUBLE ~            ~         ~1.00x

Tests cover the overflow transition from fast path to generic, and
the integration with array_column() together with the PHP 8.3
nested-array warning behavior.

* [ext/standard] Simplify array_sum/product iteration

* [ext/standard] Force inline array binop wrapper
…ddEmptyDir() (#22011)

Now, the .phar directory is a magic dir for phar files, and in phar::addEmptyDir(), users couldn't create a dir naming .phar

The implementation is:
```c
	if (zend_string_starts_with_literal(dir_name, ".phar")) {
		zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create a directory in magic \".phar\" directory");
		RETURN_THROWS();
```
This has two bugs.

Firstly, people can use /.phar to create the .phar dir. The leading / will be ignored. (no need to concern about ../ though, it will be ignored.)

```php
<?php
  $phar = new Phar(__DIR__ . '/test.phar', 0, 'test.phar');
  $phar->addEmptyDir('/.phar');
  var_dump(is_dir('phar://' . __DIR__ . '/test.phar/.phar'));
```
Will return true with the .phar dir created, while if the dir is .phar it will raise an error.

Secondly, it only matches the prefix. That means, /.pharxxx will not be allowed to create, which is not a magic dir.

```php
<?php
  $phar = new Phar(__DIR__ . '/test.phar', 0, 'test.phar');
  $phar->addEmptyDir('.pharx');
```
This will raise an error.
```
PHP Fatal error:  Uncaught BadMethodCallException: Cannot create a directory in magic ".phar" directory in C:\Users\admin\Desktop\bench.php:3
```
This PR fix both by 1. adding a trailing check of the path to make .pharx valid 2. adding a check to /.phar
…_domain, session.cache_limiter (#22074)

Reject null bytes in `session.cookie_path`, `session.cookie_domain`, `session.cache_limiter`.

- `cookie_path` / `cookie_domain`: When the session cookie was sent, `php_session_send_cookie()` built the Set-Cookie header including the raw null byte. The SAPI layer (sapi_header_op) emitted a generic `E_WARNING: Header may not contain NUL bytes` and returned FAILURE, but `php_session_send_cookie()` did not check that return value and returned SUCCESS — so the session cookie was silently dropped while `session_start()` still returned true.
- `cache_limiter`: The limiter name is looked up via `strcasecmp(lim->name, ZSTR_VAL(PS(cache_limiter)))`, which stops at the null byte, so "nocache\0evil" would silently behave as "nocache". The null byte was effectively ignored but still accepted without complaint.
When a named capture group is also called "MARK" and the pattern uses
the (*MARK:name) directive, populate_subpat_array() inserted two
buckets with the same string key into the matches array.
zend_hash_str_add_new skips the duplicate-key check, so the named
capture's MARK and the directive's MARK both landed in the table.

Switch to zend_hash_str_update so the directive's value overwrites
the capture's value, restoring the behavior that existed via
add_assoc_string_ex before d6cc31c.

Closes GH-22029
@pull pull Bot locked and limited conversation to collaborators May 18, 2026
@pull pull Bot added the ⤵️ pull label May 18, 2026
@pull pull Bot merged commit 0a03d10 into turkdevops:master May 18, 2026
1 of 3 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants