Skip to content

Reflection*::__toString() truncates on null bytes #22681

Description

@DanielEScherzer

After #22658 I figured I would check some other things, the following all truncate on null bytes in user-controlled values

ReflectionClass::__toString() from doc comment
<?php

eval(<<<END
/** F\0oo */
class Demo {}
END
);

$r = new ReflectionClass('Demo');
echo $r;
var_dump( $r->getDocComment() );
ReflectionConstant::__toString() from constant name
<?php

define("F\0oo", true);

$r = new ReflectionConstant("F\0oo");
echo $r;
var_dump( $r->getName() );
ReflectionClassConstant::__toString() from doc comment
<?php

eval(<<<END
class Demo {
    /** F\0oo */
    public const DEMO = true;
}
END
);

$r = new ReflectionClassConstant('Demo', 'DEMO');
echo $r;
var_dump( $r->getDocComment() );
ReflectionEnum::__toString() with enum case documentation
<?php

eval(<<<END
enum Demo {
    /** F\0oo */
    case DEMO;
}
END
);

$r = new ReflectionEnum('Demo');
echo $r;
var_dump( new ReflectionEnumUnitCase('Demo', 'DEMO')->getDocComment() );
ReflectionEnum::__toString() with backed enum value
<?php

eval(<<<END
enum Demo: string {
    case DEMO = "F\0oo";
}
END
);

$r = new ReflectionEnum('Demo');
echo $r;
var_dump( new ReflectionEnumBackedCase('Demo', 'DEMO')->getBackingValue() );
ReflectionProperty::__toString() with doc comment
<?php

eval(<<<END
class Demo {
    /** F\0oo */
    public \$prop;
}
END
);

$r = new ReflectionProperty('Demo', 'prop');
echo $r;
var_dump( $r->getDocComment() );
ReflectionProperty::__toString() with dynamic property name
<?php

$obj = (object)["F\0oo" => true];
$r = new ReflectionProperty($obj, "F\0oo");
echo $r;
var_dump( $r->getDocComment() );
ReflectionExtension::__toString() with INI option value (also there is a weird `}` without a `{`, that should probably be fixed on master)
<?php

ini_set('arg_separator.output', "f\0oo");
$r = new ReflectionExtension('core');
$str = (string)$r;
$index = strpos($str, 'Entry [ arg_separator.output');
$str = substr($str, $index);
$index = strpos($str, 'Entry', 1);
$str = substr($str, 0, $index);
echo $str . "\n";
var_dump( $r->getINIEntries()['arg_separator.output'] );
ReflectionFunctionAbstract::__toString() with doc comment
<?php

eval(<<<END
/** F\0oo */
function demo() {}

class Demo {
    /** F\0oo */
    public function demo() {}
}
END
);

$r = new ReflectionFunction('demo');
echo $r;
var_dump( $r->getDocComment() );

$r = new ReflectionMethod(Demo::class, 'demo');
echo $r;
var_dump( $r->getDocComment() );

Activity

  1. DanielEScherzer commented on Jul 10, 2026

    @DanielEScherzer
    MemberAuthor

    ReflectionEnum::__toString() with backed enum value is only 8.5+, will do in a separate PR

  2. added a commit that references this issue on Jul 13, 2026
  3. DanielEScherzer commented on Jul 13, 2026

    @DanielEScherzer
    MemberAuthor

    For the 8.5 upmerge of #22685 at fd7e1e2, the null bytes reappeared in the output of enum doc comments (since I changed that in 8.5, #15956), will address in the same PR as the backed value

  4. added 2 commits that reference this issue on Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions