Repository navigation
Closed
Labels
area:vmVirtual machineVirtual machineenhancementNew feature or requestNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimSpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language featuresPhase 2 – language features
Description
Category
language · php-src-strict · PHP 8.4 property hooks · sibling to #9666 (unset hook)
Problem
When a property set hook throws (or a readonly hooked write raises Error), the exception reaches the caller's catch, but the VM resumes the try block after the handler as if the write succeeded. Zend aborts the assignment and does not execute subsequent statements in the try.
<?php
class C {
public int $x {
get => $this->x;
set { throw new Exception('set hook'); }
}
private int $x = 0;
}
$c = new C();
try {
$c->x = 1;
echo "no-resume\n"; // VM prints after catch — wrong
} catch (Throwable $e) {
echo 'caught: ', $e->getMessage(), "\n";
}
// Zend (8.4): only "caught: set hook"Same symptom for readonly class + hooked property write (Error: Cannot modify readonly property then no-resume).
php-src reference
- php/php-src
Zend/zend_property_hooks.c—sethook dispatch + exception propagation - php/php-src
Zend/zend_execute.c— exception unwinding must not resume completed try range after catch
Repro
test/repro/maintainer_gap_property_hook_set_exception.phptest/repro/maintainer_gap_readonly_hook_write_exception.php
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php test/repro/maintainer_gap_property_hook_set_exception.php'
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php test/repro/maintainer_gap_readonly_hook_write_exception.php'Implementation hints (PHP-in-PHP)
- Fix property-hook write exception path in
lib/VM.php— same class of bug as Language: property hook unset — exception from hook must abort unset and propagate (Zend/zend_property_hooks.c) #9666 (unset hook); share unwinding helper - Do not swallow hook throws in trampolines; do not re-enter try block after catch
- No new C runtime logic
Scope
lib/VM.phpproperty hook set / readonly write opcodes- Compliance guard under
test/compliance/cases/language/
Done when
- Set-hook repro prints only
caught: set hook— nono-resume - Readonly-hook repro prints only
caught: Error— nono-resume - Backing storage unchanged when hook throws
- Language: property hook unset — exception from hook must abort unset and propagate (Zend/zend_property_hooks.c) #9666 unset-hook fix shares root unwinding if applicable
Verification
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php test/repro/maintainer_gap_property_hook_set_exception.php'
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php test/repro/maintainer_gap_readonly_hook_write_exception.php'Metadata
Metadata
Assignees
Labels
area:vmVirtual machineVirtual machineenhancementNew feature or requestNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimSpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language featuresPhase 2 – language features
Activity
PurHur commentedon Jun 18, 2026
claim: cursor-agent-lane-b — starting this run
Fix property set hook exceptions aborting assignment (#9670) (#9709)
PurHur commentedon Jun 18, 2026
Merged via #9709.
Fix: Set-hook
throwand catchable hook-body errors (readonlyError, etc.) now bubble throughpropertyHookExternalCatchFramelike get/unset hooks (#9666) — outertryblocks no longer resume aftercatch.Verification:
Both repros print only
caught: …(nono-resume); compliance 2/2 green.