diff --git a/src/Symfony/Component/VarDumper/Caster/FFICaster.php b/src/Symfony/Component/VarDumper/Caster/FFICaster.php index f1984eef368ee..ffed9f315ba56 100644 --- a/src/Symfony/Component/VarDumper/Caster/FFICaster.php +++ b/src/Symfony/Component/VarDumper/Caster/FFICaster.php @@ -115,11 +115,21 @@ private static function castFFIPointer(Stub $stub, CType $type, ?CData $data = n private static function castFFIStringValue(CData $data): string|CutStub { $result = []; + $ffi = \FFI::cdef(<<zend_get_page_size(); + + // get cdata address + $start = $ffi->cast('uintptr_t', $ffi->cast('char*', $data))->cdata; + // accessing memory in the same page as $start is safe + $max = min(self::MAX_STRING_LENGTH, ($start | ($pageSize - 1)) - $start); + + for ($i = 0; $i < $max; ++$i) { $result[$i] = $data[$i]; - if ("\0" === $result[$i]) { + if ("\0" === $data[$i]) { return implode('', $result); } } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php index 5e7ec147bbbe6..d06b29963ce98 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\VarDumper\Tests\Caster; use PHPUnit\Framework\TestCase; -use Symfony\Component\VarDumper\Caster\FFICaster; use Symfony\Component\VarDumper\Test\VarDumperTestTrait; /** @@ -191,34 +190,21 @@ public function testCastCuttedPointerToChar() PHP, $pointer); } - /** - * It is worth noting that such a test can cause SIGSEGV, as it breaks - * into "foreign" memory. However, this is only theoretical, since - * memory is allocated within the PHP process and almost always "garbage - * data" will be read from the PHP process itself. - * - * If this test fails for some reason, please report it: We may have to - * disable the dumping of strings ("char*") feature in VarDumper. - * - * @see FFICaster::castFFIStringValue() - */ public function testCastNonTrailingCharPointer() { $actualMessage = 'Hello World!'; $actualLength = \strlen($actualMessage); - $string = \FFI::cdef()->new('char['.$actualLength.']'); + $string = \FFI::cdef()->new('char['.($actualLength + 1).']'); $pointer = \FFI::addr($string[0]); - \FFI::memcpy($pointer, $actualMessage, $actualLength); - // Remove automatically addition of the trailing "\0" and remove trailing "\0" $pointer = \FFI::cdef()->cast('char*', \FFI::cdef()->cast('void*', $pointer)); $pointer[$actualLength] = "\x01"; $this->assertDumpMatchesFormat(<< size 8 align 8 { - cdata: "$actualMessage%s" + cdata: %A"$actualMessage%s" } PHP, $pointer); }