Skip to content

Commit

Permalink
[VarDumper] Fix FFI caster test
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandre-daubois committed Jun 22, 2024
1 parent ad23ca4 commit f828481
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 18 deletions.
14 changes: 12 additions & 2 deletions Caster/FFICaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(<<<C
size_t zend_get_page_size(void);
C);

for ($i = 0; $i < self::MAX_STRING_LENGTH; ++$i) {
$pageSize = $ffi->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);
}
}
Expand Down
18 changes: 2 additions & 16 deletions Tests/Caster/FFICasterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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(<<<PHP
FFI\CData<char*> size 8 align 8 {
cdata: "$actualMessage%s"
cdata: %A"$actualMessage%s"
}
PHP, $pointer);
}
Expand Down

0 comments on commit f828481

Please sign in to comment.