1374 Commits
Author SHA1 Message Date
Weilin Du c47875f47b Merge branch 'PHP-8.6'
* PHP-8.6:
  Fix GH-24552: Use ASCII case folding in string comparisons (#24558)
2026-10-27 21:23:26 +08:00
Weilin Du 04a5da0ab6 Merge branch 'PHP-8.5' into PHP-8.6
* PHP-8.5:
  Fix GH-24552: Use ASCII case folding in string comparisons (#24558)
2026-10-27 21:23:12 +08:00
Weilin Du 6a020d606e Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
  Fix GH-24552: Use ASCII case folding in string comparisons (#24558)
2026-10-27 21:22:44 +08:00
lazergandJon Surrell 872c6e19c4 Fix GH-24552: Use ASCII case folding in string comparisons (#24558)
PHP 8.2 made case-insensitive comparisons ASCII-only, but ksort() and
krsort() with SORT_STRING | SORT_FLAG_CASE and substr_compare() with
case_insensitive=true still used the locale-sensitive _l variants.
These call tolower() and depend on LC_CTYPE.

Use zend_binary_strcasecmp() and zend_binary_strncasecmp(), consistent
with sort() and strncasecmp(), so these comparisons also use ASCII case
folding regardless of the current locale.

Fixes #24552

Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com>

Closes #24558
2026-10-27 21:21:44 +08:00
Ilija Tovilo 9705fda1bb Merge branch 'PHP-8.6' into master
* PHP-8.6:
  Add NEWS entry
  Avoid state corruption via bailout
2026-10-21 16:34:56 +02:00
Ilija Tovilo d6373dfe15 Merge branch 'PHP-8.5' into PHP-8.6
* PHP-8.5:
  Add NEWS entry
  Avoid state corruption via bailout
2026-10-21 16:33:23 +02:00
Ilija Tovilo c7273b9ba8 Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
  Add NEWS entry
  Avoid state corruption via bailout
2026-10-21 16:30:04 +02:00
Ilija Tovilo 8a94bb3822 Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3:
  Add NEWS entry
  Avoid state corruption via bailout
2026-10-21 16:27:03 +02:00
Ilija Tovilo c1a5f468d0 Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2:
  Add NEWS entry
  Avoid state corruption via bailout
2026-10-21 16:12:35 +02:00
3584a98bda Avoid state corruption via bailout
- Replace bailout on OOM with UnwindExit
- Properly reset various globals that may be accessed during startup

Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)

Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
Co-authored-by: Jakub Zelenka <bukka@php.net>
Co-authored-by: Nora Dossche <7771979+ndossche@users.noreply.github.com>
Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
2026-10-21 16:06:22 +02:00
divinity76andXinchen Hui f40a84cd61 Optimize str_repeat (#23128)
* Optimize str_repeat

The memmove got me thinking "can src and dst actually overlap?", and it turns out no:
- e always points to populated data + 1
- l may reach the end of populated data, but will never exceed it

memcpy is safe here, and faster (unless the compiler already spotted it in an optimization pass and replaced it internally, entirely possible)

* comment pinning the non-overlap invariant

Co-authored-by: Xinchen Hui <laruence@gmail.com>

---------

Co-authored-by: Xinchen Hui <laruence@gmail.com>
2026-10-18 11:31:25 +02:00
Arnaud Le Blanc 6903d8c6e9 Merge branch 'PHP-8.6'
* PHP-8.6:
  Fix wordwrap() ignoring an existing break at the end of the string (#24116)
2026-10-05 19:46:15 +02:00
Arnaud Le Blanc dcd6e8006f Merge branch 'PHP-8.5' into PHP-8.6
* PHP-8.5:
  Fix wordwrap() ignoring an existing break at the end of the string (#24116)
2026-10-05 19:46:05 +02:00
Arnaud Le Blanc a0ed6cc298 Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
  Fix wordwrap() ignoring an existing break at the end of the string (#24116)
2026-10-05 19:45:33 +02:00
Nicolas Grekas f817996280 Fix wordwrap() ignoring an existing break at the end of the string (#24116)
When a multi-character break or $cut_long_words is used, an existing
break was only recognized when at least one character followed it. A
trailing break was handled as regular text, so wordwrap("abc\n", 3,
"\n", true) returned "abc\n\n" and wordwrap("ab cd\n", 5, "\n", true)
returned "ab\ncd\n". The single-character fast path was not affected.
2026-10-05 19:44:36 +02:00
Weilin Du c33572a7ee ext/standard: Optimize single-character searches in strcspn() and strpbrk() (#24087) 2026-10-04 01:21:09 +08:00
Weilin Du 68301c0df8 ext/standard: Remove redundant if-branch in rot13 (#23795) 2026-09-30 00:02:36 +08:00
Tim Düsterhus a4bb03a84b standard: Take HashTable* instead of zval* in php_explode() (#23910) 2026-09-26 09:44:28 +02:00
Marc dc7962c43e perf: use nl_langinfo for the decimal point on glibc ZTS instead of mutex-protected localeconv (#22728) 2026-09-24 17:26:05 +02:00
Weilin Du c9e2bc0683 ext/standard: Optimize & Refactor pathinfo() (#23726)
- Reuse the basename string for PATHINFO_BASENAME
and extensionless PATHINFO_FILENAME results.
- Share the last-dot lookup for extension and filename
when returning PATHINFO_ALL.
- (From my perspective) cleaner code.
2026-09-18 10:45:09 +08:00
Weilin DuandNora Dossche 93fd714daa ext/standard: Optimize str_repeat() when the multiplier is one (#23681)
Just reuse the input string when the multiplier is one :)

Co-authored-by: Nora Dossche <7771979+ndossche@users.noreply.github.com>
2026-09-15 00:03:28 +08:00
Weilin Du 2101993133 ext/standard: Optimize octal escape generation in addcslashes() (#23680)
This hack is slightly faster than the original one.
My local benchmarks show approximately 39% lower
runtime for a single NUL byte.
2026-09-14 00:03:40 +08:00
Weilin Du 74e3a69df1 ext/standard: Optimize str_pad() using doubling copies (#23661)
This PR optimizes the user-visible `str_pad()` by reducing repeated small
copy operations during padding. In `php_str_pad_fill()`, the algorithm now uses
doubling copies to grow the written region exponentially. This lowers memcpy counts
and improves throughput for large repeated-pattern padding workloads.

Added `str_pad_repeated_pattern.phpt` to validate repeated pattern and partial-tail
boundaries, including multi-byte patterns and all pad directions. Behavior is
unchanged; this is a performance-only change and is now recorded in the PHP 8.6
performance changelog.
2026-09-12 13:28:03 +08:00
Weilin Du ac53f14223 ext/standard: Use ZVAL_STRINGL_FAST() in php_explode_negative_limit() (#23631)
Ideally this save a emalloc + memcpy + free.
2026-09-11 00:03:56 +08:00
Weilin Du 66c98704e2 ext/standard: Make ltrim() and rtrim() frameless 2026-09-05 18:13:39 +08:00
Weilin Du 027a5f8536 ext/standard: Make str_ends_with frameless (#23510)
Since str_starts_with is frameless, str_ends_with also
should be frameless.
2026-08-31 00:19:57 +08:00
Ondrej Mirtes 89a17252a4 Make strtolower()/strtoupper() frameless
Both are single-argument wrappers around zend_string_tolower/upper;
static analyzers and general string handling call them at very high
frequency. The frameless call convention removes the call frame setup
and argument copying.

Co-authored-by: Markus Staab <maggus.staab@googlemail.com>
Closes GH-23084
2026-08-12 15:56:24 +02:00
David Carlier a5f9571d6e Merge branch 'PHP-8.5'
* PHP-8.5:
  Fix GH-23204: use-after-free when __toString() destroys an array argument
2026-08-11 18:05:44 +01:00
David Carlier 281738e57f Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
  Fix GH-23204: use-after-free when __toString() destroys an array argument
2026-08-11 18:05:42 +01:00
Lazizbek Ergashev 8ce7f7f5e9 Fix GH-23204: use-after-free when __toString() destroys an array argument
implode() walks the array with ZEND_HASH_FOREACH_VAL while holding no
reference on it. Converting a Stringable element runs user code, and if
that code drops the last remaining reference to the array (`$a = null;`
from __toString()), arData is freed and the next iteration reads freed
memory. strtr() and str_replace() read their array arguments the same
way and crash the same way, so they are fixed here too.

Taking a reference on the table for the duration of the read keeps it
alive and turns an in-place mutation into a separation instead, same as
zend_compare_symbol_tables() does around zend_hash_compare(). In
implode() the reference is released after the pieces have been
concatenated, since the collected zend_strings are still owned by the
array until then.

Close GH-23207
2026-08-11 18:02:05 +01:00
Weilin Du 1fd0c64beb ext/standard: Fix setlocale() NUL byte truncation (#22843)
This reject NUL byte in the setlocale() function in the standard extension.
2026-07-28 00:03:52 +08:00
Tim Düsterhus d37a820d59 zend_string: Add zend_string_ends_with*() (#22819) 2026-07-20 12:58:40 +02:00
Weilin Du 6bc7c26cf6 Replace dependencies on /ext/hash in various extensions (#21832)
Followup-PR for #21724. Using the new API in #21724 to replace dependencies
on /ext/hash in

- ext/opcache/ZendAccelerator/
- ext/soap/php_http.c
- Zend/zend_system_id.c

In the following ext, there are independent implementation of bin2hex. This PR
also change them to directly using the new Zend API.

- ext/standard/string.c
- ext/hash/php_hash.h
2026-07-09 20:03:34 +08:00
Peter Kokot 5ff2a95341 Remove redundant <libintl.h> include (#22477)
The HAVE_LIBINTL macro is defined only when the ext/gettext is enabled
during the build. Also, LC_MESSAGES have been moved to other places
since this header was initially included.
2026-06-27 18:36:21 +02:00
Diego Sales 72244e6b20 ext/standard: improve explode() error message for empty separator (GH-21906) 2026-06-02 19:16:40 +02:00
Ilija Tovilo 529b145511 Merge branch 'PHP-8.5'
* PHP-8.5:
  GHSA-m8rr-4c36-8gq4: Consistently pass unsigned char to ctype.h functions
2026-05-06 13:11:01 +02:00
Ilija Tovilo b8dad9314c GHSA-m8rr-4c36-8gq4: Consistently pass unsigned char to ctype.h functions
Fixes GHSA-m8rr-4c36-8gq4
Fixes CVE-2026-7258
2026-05-06 13:10:12 +02:00
Ilija Tovilo dc9e21b81c GHSA-m8rr-4c36-8gq4: Consistently pass unsigned char to ctype.h functions
Fixes GHSA-m8rr-4c36-8gq4
Fixes CVE-2026-7258
2026-05-06 13:09:23 +02:00
Ilija Tovilo 398b7dabfb GHSA-m8rr-4c36-8gq4: Consistently pass unsigned char to ctype.h functions
Fixes GHSA-m8rr-4c36-8gq4
Fixes CVE-2026-7258
2026-05-06 13:08:17 +02:00
Ilija Tovilo a38418777f GHSA-m8rr-4c36-8gq4: Consistently pass unsigned char to ctype.h functions
Fixes GHSA-m8rr-4c36-8gq4
Fixes CVE-2026-7258
2026-05-06 13:07:20 +02:00
Weilin Du 2f4a214e5d ext/standard: Reject null bytes in parse_str() (#21942) 2026-05-04 19:19:07 +02:00
Ben Ramsey 5164621436 license-update: ext/standard source headers
RFC: https://wiki.php.net/rfc/php_license_update
2026-04-11 21:20:54 -05:00
David Carlier 4843327a90 ext/standard: pathinfo() check flags argument validity.
close GH-17859
2026-04-06 20:53:19 +01:00
Arshid 465ecaabf1 ext/standard: zend_string_concat2() instead of manual memcpy (#21567) 2026-03-28 16:31:43 +01:00
Weilin Du da1e89fd3d RFC: Add Form Feed in Trim Functions (#20788)
RFC: https://wiki.php.net/rfc/trim_form_feed

Resolves GH-20783.
2026-03-09 22:28:50 +01:00
Ilija Tovilo a83c025730 Use zend_always_inline for frameless function template functions (GH-21316) 2026-03-03 00:20:34 +01:00
Alexandre Daubois 1fb4e573ff Merge branch 'PHP-8.5'
* PHP-8.5:
  Fix TypeError message of `setlocale()` (#20625)
2025-12-06 18:06:53 +01:00
Takuya Aramaki 5528df1a20 Fix TypeError message of setlocale() (#20625) 2025-12-06 18:06:19 +01:00
Tim Düsterhus db8d35e7eb tree-wide: Replace ZEND_WRONG_PARAM_COUNT() by its definition (#20066)
* tree-wide: Replace `WRONG_PARAM_COUNT` by `ZEND_WRONG_PARAM_COUNT()`

This is a direct alias.

* tree-wide: Replace `ZEND_WRONG_PARAM_COUNT()` by its definition

This macro was hiding control flow (the return statement) and thus was
particularly unhygienic.
2025-11-12 21:28:56 +01:00
Niels Dossche a09cc6ede6 standard: Optimize str_split() (#20419)
Three optimizations:
- If the entire string is returned, we don't need to duplicate it.
- Use packed filling logic.
- Use fast construction of strings. This is useful when splitting
  strings on length=1. In that case I get a 6x speedup in the code
  below.

Bench:
```php
$x = str_repeat('A', 100);
for ($i = 0; $i < 1000000; $i++)
    str_split($x, 10);
```

On an i7-4790:
```
Benchmark 1: ./sapi/cli/php x.php
  Time (mean ± σ):     160.1 ms ±   6.4 ms    [User: 157.3 ms, System: 1.8 ms]
  Range (min … max):   155.6 ms … 184.7 ms    18 runs

Benchmark 2: ./sapi/cli/php_old x.php
  Time (mean ± σ):     202.6 ms ±   4.0 ms    [User: 199.1 ms, System: 1.9 ms]
  Range (min … max):   197.4 ms … 209.2 ms    14 runs

Summary
  ./sapi/cli/php x.php  ran
    1.27 ± 0.06 times faster than ./sapi/cli/php_old x.php
```

The performance gain increases with smaller lengths.
2025-11-08 23:02:00 +01:00