[php-src] PR #24592: Fix GH-24280: enforce asymmetric setter visibility in foreach by reference
| From: | Xauele | Date: | Fri, 23 Oct 2026 09:36:15 +0000 |
| Subject: | [php-src] PR #24592: Fix GH-24280: enforce asymmetric setter visibility in foreach by reference | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39757@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24592
Author: Xauele
Fixes #24280: object
foreach ($object as &$value) currently permits acquiring
references to private(set) and protected(set) properties from forbidden
scopes, including properties already held in a reference. Check setter visibility before exposing
the reference, while retaining readonly checks and typed-reference tracking.
The existing setter-access helper handles protected scopes and fake scopes. A same-class fast path
avoids the helper only when EG(fake_scope) is null and the executing function belongs to the
declaring class.
Candidate: cf991cbe0f1d19c4e44041c6095b7fce534ebac1, based on PHP-8.4
f6852befa34b1107da57d26ead79e575ccd73e2a. Six files: VM source, regenerated executor, three PHPTs,
NEWS. No CI harness is included.
Fresh native qualification: https://github.com/Xauele/php-src/actions/runs/39931975656
(source e15cea8f5cc1d6900003e195f22399756c137715; identical VM and PHPT blobs to this candidate;
candidate additionally has NEWS).
- PHP 8.4 NTS and ZTS: 4918 Zend tests passed per build, zero unexpected failures.
- PHP 8.5: 5263 passed, zero unexpected failures.
- PHP 8.6: 5523 passed, zero unexpected failures.
- master (8.7-dev): 5530 passed, zero unexpected failures.
- Every build reproduced four forbidden-scope bypasses before patching, then passed all three new
PHPTs under the interpreter, OPcache, tracing JIT and function JIT. OPcache and JIT activation were
asserted.
- Each suite also has one pre-existing expected failure and version-dependent skips. These are
pinned development branch builds, not a claim about every released patch version. PHP 8.3 and older
do not support this setter syntax.
Tests cover fresh and retained references, forbidden global/child access, allowed owner/protected
child writes, partial writes before an error, readonly/typed/dynamic/hooked properties, bound
closure scopes, traits, global callees, lazy ghosts/proxies and 3000 repeated attempts.
Performance limitation: a release-build alternating A/B benchmark (20 samples per binary per case,
same pinned base/configuration, interpreter, checked checksum) measured array -0.49%, stdClass
+1.64%, plain declared properties +4.01%, typed +5.23%, retained references +1.97%, same-class
restricted properties +6.35%. These are microbenchmark timings, not application-level estimates. The
simpler helper-only variant repeatedly cost 11–12% in the last case. Raw samples are attached to
the run as an artifact. The remaining cost needs maintainer assessment.
Full platform CI on this exact candidate: https://github.com/Xauele/php-src/actions/runs/39932513648
(pending). This is a draft for maintainer review, including assessment of the remaining measured
hot-path overhead. Full platform CI is still pending; no merge readiness is claimed.