Skip to content

Language: object used as array key accepted — Zend TypeError Illegal offset type (zend_execute.c / zend_hash.c) #29532

Closed

Description

@PurHur

Category

language · php-src-strict · array offset / hash key · pillar 4

Problem

Using an object as an array key must throw TypeError: Illegal offset type (objects are never valid hash keys; __toString is not consulted). VM/JIT accept the write: with a Stringable object the key becomes '' (empty string) after a failed/ignored conversion path; without __toString the write still succeeds and AFTER runs.

Probed 2026-08-09 @ 95c9b7659b vs Zend 8.2.32. JIT matches VM.

Repro Zend 8.2.32 VM / JIT
$a[new T()] = 1 (T has no __toString) TypeError: Illegal offset type write succeeds; AFTER prints
$a[new T()] = 1 (T::__toString → \"k\") TypeError: Illegal offset type (no TOSTRING) keys=['']; AFTER prints

php-src reference

PHP implementation target

  • VM + JIT array dim write/fetch: reject IS_OBJECT keys with TypeError: Illegal offset type before any __toString coercion
  • Prefer PHP-in-PHP in lib/VM / lib/JIT offset helpers; no new runtime/*.c

Repro

./script/docker-exec.sh -- bash -lc 'cat > /tmp/obj_key.php <<'"'"'PHP'"'"'
<?php
error_reporting(E_ALL);
class T {}
$a = [];
try {
  $a[new T()] = 1;
  echo "AFTER\n";
} catch (Throwable $e) {
  echo get_class($e), ": ", $e->getMessage(), "\n";
}
echo "done\n";
PHP
php /tmp/obj_key.php
php bin/vm.php /tmp/obj_key.php
php bin/jit.php /tmp/obj_key.php'

Done when

  • VM + JIT: object as array key throws TypeError: Illegal offset type like Zend (with or without __toString)
  • __toString is not invoked for array-key conversion
  • Compliance/.phpt or test/repro/ guard
  • php-src-strict; no php-compiler-strict shortcut

Activity

  1. added
    bugSomething isn't working
    area:vmVirtual machine
    implementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claim
    on Aug 9, 2026
  2. PurHur commented on Aug 9, 2026

    @PurHur
    OwnerAuthor

    claim: lane-A language worker — starting this run (released #29533; verified fixed by #29521). Repro still red: $a[new T()]=1 prints AFTER on VM/JIT; Zend TypeError Illegal offset type.

  3. PurHur commented on Aug 9, 2026

    @PurHur
    OwnerAuthor

    Merged #29539

    Fix: when a dim key Temporary (e.g. new T() result) collides with a merge-echo phi slot, copy into a fresh temp instead of forceFreshVarSlot remapping the live TYPE_NEW operand (which left null→"" and skipped Illegal offset type).

    Verify: Zend / VM / JIT all print:

    TypeError: Illegal offset type
    TypeError: Illegal offset type
    var TypeError: Illegal offset type
    done
    

    No TOSTRING / AFTER_*. Unit test IllegalOffsetObjectKeyNewInTryTest OK.

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:compilerCompiler / CFG / JITarea: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