View Issue Details

IDProjectCategoryView StatusLast Update
0002443XdebugUncategorizedpublic2026-10-24 09:07
Reporterrolfvandekrol Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Summary0002443: Array items are transformed into references during exceptions handling
Description

With xdebug (develop mode) enabled the script in 'Steps to Reproduce' gives another output than with xdebug off. The product version field does not allow me to select xdebug 3.5.3, but this is in 3.5.3. I verified this in PHP 8.4.24 and PHP 8.4.26.

What seems to happen:
When an reference exists to an item in an array, during exception handling that array item is then transformed into a reference itself. It looks like this is not specific for array items, but is exposed easier in the array context because of the way array copying works.

I encountered this issue in a real world application where my tests would fail with xdebug on and would pass with xdebug off.

Steps To Reproduce

Use the following script

<?php

class Component
{
    public array $items = [];

    public function mount(bool $throw): void
    {
        $this->items[] = ['name' => 'create'];

        // A local reference into the property, freed when this method returns.
        $ref = &$this->items[0];

        if ($throw) {
            try {
                throw new Exception('caught');
            } catch (Exception) {
            }
        }
    }
}

printf("xDebug mode: %s\n", ini_get('xdebug.mode'));

foreach ([false, true] as $throw) {
    $component = new Component();
    $component->mount($throw);

    $isReference = ReflectionReference::fromArrayElement($component->items, 0) !== null;

    // Copy the array and overwrite the copy; the original should never change.
    $copy = $component->items;
    $copy[0] = 'changed in the copy';

    printf(
        "%s exception: items[0] is %sa reference, original items[0] = %s\n",
        $throw ? 'with   ' : 'without',
        $isReference ? '' : 'not ',
        json_encode($component->items[0]),
    );
}

With xdebug off, the output is

xDebug mode:
without exception: items[0] is not a reference, original items[0] = {"name":"create"}
with    exception: items[0] is not a reference, original items[0] = {"name":"create"}

With xdebug on, the output is

xDebug mode: debug,develop
without exception: items[0] is not a reference, original items[0] = {"name":"create"}
with    exception: items[0] is a reference, original items[0] = "changed in the copy"

In the script reflection is used. The reflection is only there to be able to show the text '... is (not) a reference'. Removing the reflection logic does not change the behavior.

Additional Information

AI disclaimer:
This issue was found by Claude, and the minimal reproduction script was written mostly by Claude. I verified the issue myself, and wrote and submitted this bug report myself as well.

TagsNo tags attached.
Operating System
PHP Version8.5.0-8.5.4

Activities

There are no notes attached to this issue.