Issue PHP 7.2.34 build for Debian 13 (Oct 2025): OPcache optimizer miscompiles loop comparison, causes infinite loop in WordPress core

ajeje

New Pleskian
Server operating system version
Debian 13.5
Plesk version and microupdate number
Plesk Obsidian 18.0.78 #3
Environment:
  • Plesk Obsidian 18.0.78 on Debian 13.5 (fresh install)
  • PHP 7.2.34 from Plesk packages, Build Date: Oct 22 2025 13:42:41, FPM/FastCGI handler
  • WordPress 5.5.x site migrated from Plesk Obsidian 18.0.78 on Debian 10.13 with PHP 7.2.34 (Build Date: Nov 8 2021), where the same site works correctly

Symptom:
After migrating a WordPress site (identical files and database), any wp-admin request hangs for 30s and dies with Maximum execution time exceeded or Allowed memory size exhausted. The log fills with millions of notices (hundreds of MB per request):

Code:
PHP Notice: Undefined offset: 9 in .../wp-includes/formatting.php on line 766
PHP Notice: Undefined offset: 11 in .../wp-includes/formatting.php on line 766
PHP Notice: Undefined offset: 13 in .../wp-includes/formatting.php on line 766
... (offsets keep growing by 2 up to several million until the request is killed)

Root cause analysis:
Line 766 is inside wp_replace_in_html_tags() (stock WordPress core, unmodified):

PHP:
for ( $i = 1, $c = count( $textarr ); $i < $c; $i += 2 ) {
if ( false !== strpos( $textarr[ $i ], $needle ) ) {

I instrumented the loop with a probe logging $i, $c and count($textarr) on the first missing key. Result:

Code:
i=9 c=9 realcount=9

The loop body executes with $i = 9 and $c = 9, i.e. the condition 9 < 9 evaluates as
true. The comparison never becomes false, so the loop runs forever on a 9-element array. The triggering call is harmless: a 411-byte string passed through wpautop() (Yoast SEO admin notification).

Notes for triage:
  • The bug does not reproduce with the same functions copied into a standalone script on the same server — it only manifests inside the full WordPress request, which suggests an OPcache optimization issue dependent on compilation context rather than a PCRE or data problem.
  • PCRE was ruled out: preg_split() with WordPress's get_html_split_regex() returns correct, hole-free arrays in isolated tests (JIT on and off).
  • Same files + same database on the Debian 10 build (Nov 2021) of the same PHP 7.2.34: no issue.

Workarounds verified:
  1. opcache.enable=0 in .user.ini → site works immediately (original WordPress core untouched).
  2. Switching the domain to Plesk PHP 7.4.33 with OPcache enabled → site works.

Suspected cause:
the PHP 7.2 source tree rebuilt in 2025 with Debian 13's modern toolchain (GCC 14) produces a miscompiled OPcache optimizer / VM comparison path. PHP 7.2 is EOL upstream, so this would need a fix in the Plesk build (e.g. compiling with older optimization flags or patching the optimizer).
 
Back
Top