Skip to content

Commit

Permalink
bug #57397 [VarDumper] Fix FFI caster test (alexandre-daubois)
Browse files Browse the repository at this point in the history
This PR was merged into the 6.4 branch.

Discussion
----------

[VarDumper] Fix FFI caster test

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Issues        | Fix #57387
| License       | MIT

Fixes the invalid memory writing thanks to Arnaud's hints. Not easy to understand exactly what's the point of `testCastNonTrailingCharPointer`, so I hope the test is still valid like this.

Commits
-------

8594b2f [VarDumper] Fix FFI caster test
  • Loading branch information
fabpot committed Jun 22, 2024
2 parents 5fe9ba0 + 8594b2f commit a26387b
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 18 deletions.
14 changes: 12 additions & 2 deletions src/Symfony/Component/VarDumper/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 src/Symfony/Component/VarDumper/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 a26387b

Please sign in to comment.