Skip to content

Language: isset/unset on inaccessible private props skip __isset/__unset (re-#3298, zend_object_handlers.c) #25668

Description

@PurHur

Category

Language · php-src-strict · magic property visibility (regression vs #3298)

Problem

When a property is declared private/protected but not visible from the calling scope, Zend still routes isset / empty / unset through __isset / __unset. The VM treats the declared slot as present and skips magic (and for unset, silently no-ops).

Probed 2026-07-31 on host PHP 8.2 vs php bin/vm.php (same tree):

Repro Zend 8.2 VM
isset($a->x) on private $x + __isset prints ISSET_x, then true true only (no __isset)
unset($a->x) on private $x + __unset prints UNSET_x no __unset
same class, isset from subclass method on protected $x uses real property (true) same
outside isset on protected $x + __isset returning false ISSET_x / false true (no magic)

Note: __get on the same private property does fire (parity OK) — only the has/unset paths are wrong.

php-src reference

PHP implementation target

  • lib/VM/ObjectEntry.php / lib/VM.php — TYPE_ISSET / TYPE_UNSET / empty on object dims: if property exists but is not visible from current scope, dispatch __isset/__unset instead of reading the private slot or no-op
  • Keep PHP-in-PHP; no new runtime/*.c logic
  • Compliance: test/compliance/cases/language/magic_isset_inaccessible.phpt (and unset twin)

Repro

./script/docker-exec.sh -- bash -lc 'cat > /tmp/isset_priv.php <<'"'"'PHP'"'"'
<?php
class A {
  private $x = 1;
  public function __isset($n) { echo "ISSET_$n\n"; return true; }
  public function __unset($n) { echo "UNSET_$n\n"; }
}
$a = new A();
var_export(isset($a->x)); echo "\n";
unset($a->x);
PHP
php bin/vm.php /tmp/isset_priv.php'

Done when

  • Outside-scope isset/empty on private/protected declared props call __isset with Zend truth table
  • Outside-scope unset calls __unset (no silent no-op; no private-slot leak)
  • Subclass/in-scope access still uses the real property (no spurious magic)
  • Compliance PHPT guard; php-src-strict; VM (+ JIT if in scope) match Zend

Activity

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 machinebugSomething isn't workingimplementation-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