Skip to content

Language: property hook set — exception from hook must abort assignment, try block must not resume (Zend/zend_property_hooks.c) #9670

Closed

Description

@PurHur

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

Repro

  • test/repro/maintainer_gap_property_hook_set_exception.php
  • test/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)

Scope

  • lib/VM.php property hook set / readonly write opcodes
  • Compliance guard under test/compliance/cases/language/

Done when

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'

Activity

  1. added
    enhancementNew feature or request
    area:vmVirtual machine
    implementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claim
    on Jun 18, 2026
  2. PurHur commented on Jun 18, 2026

    @PurHur
    OwnerAuthor

    claim: cursor-agent-lane-b — starting this run

  3. PurHur commented on Jun 18, 2026

    @PurHur
    OwnerAuthor

    Merged via #9709.

    Fix: Set-hook throw and catchable hook-body errors (readonly Error, etc.) now bubble through propertyHookExternalCatchFrame like get/unset hooks (#9666) — outer try blocks no longer resume after catch.

    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
    php bin/vm.php test/repro/maintainer_gap_readonly_hook_write_exception.php
    php vendor/bin/phpunit --filter "property_hook_set_throw|property_hook_readonly_write_throw" test/compliance/VMTest.php
    '

    Both repros print only caught: … (no no-resume); compliance 2/2 green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:vmVirtual machineenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language features

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions