ajeje
New Pleskian
- Server operating system version
- Debian 13.5
- Plesk version and microupdate number
- Plesk Obsidian 18.0.78 #3
Environment:
Symptom:
After migrating a WordPress site (identical files and database), any wp-admin request hangs for 30s and dies with
Root cause analysis:
Line 766 is inside
I instrumented the loop with a probe logging
The loop body executes with
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
Notes for triage:
Workarounds verified:
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).
- 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 astrue. 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'sget_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:
opcache.enable=0in.user.ini→ site works immediately (original WordPress core untouched).- 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).