[GIT-PULLS] [php-src] PR #23103: opcache: set ZEND_ACC_PRELOADED for compile-only preloaded enums

[email protected] (Nibbler999)
Newsgroups php.git-pulls
Message-ID <[email protected]>
Pull Request: https://github.com/php/php-src/pull/23103
Author: Nibbler999

> **Disclosure: this description, the patch and its test were drafted with an LLM.**

### Summary

GH-17835 fixed [GH-17715](https://github.com/php/php-src/issues/17715) for enums that preload **declares**. It does not cover enums that preload only **compiles**, and those still crash on 8.4 and 8.5.

```php
// preload.php
opcache_compile_file(__DIR__ . '/e.php');

// e.php
enum E { case Foo; }

// request
E::cases();   // SIGSEGV with any Observer API extension loaded
```

### Cause

`zend_enum_register_func()` sets `ZEND_ACC_PRELOADED` inside the `if (EG(active))` branch. `zend_persist_class_method()` keys on that flag to choose `ZEND_MAP_PTR_NEW_STATIC()` over `ZEND_MAP_PTR_NEW()`, i.e. a run_time_cache slot that survives into every request — which is what a class living in SHM permanently needs.

An enum that preload reaches via `opcache_compile_file()` is not linked while the preload script executes. It is linked from `preload_link()`, which runs after the preload request has ended, so `EG(active)` is already false, the `else` branch is taken and the flag is never set.

gdb on the crash, on an unpatched 8.5.9:

```
Program received signal SIGSEGV, Segmentation fault.
#0  zend_observer_fcall_begin_specialized (...) at Zend/zend_observer.h:92
#1  ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER ()   at Zend/zend_vm_execute.h:2281
#2  execute_ex (...)                         at Zend/zend_vm_execute.h:116541

function : cases        type: 1 (internal)     T: 1
fn_flags : 0x2002011  = PUBLIC|STATIC|HAS_RETURN_TYPE|ARENA_ALLOCATED
                        ZEND_ACC_PRELOADED (1<<10) absent
run_time_cache : 0
```

`ZEND_OBSERVER_DATA()` computes `RUN_TIME_CACHE(...) + handle` = `NULL + 0` and dereferences it — the same null deref, and the same `Zend/zend_observer.h:92`, that GH-17715's UBSAN output reports.

### Fix

Move the tag out of the `EG(active)` branch so both linking paths set it. The compile-only case then follows the identical, already-proven route as the declared case; no new mechanism is introduced.

### Test

`ext/opcache/tests/preload_enum_observed_compile_only.phpt` mirrors the existing `preload_enum_observed.phpt` and reuses its `preload_enum.inc` fixture, changing only how preload reaches it.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.