-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Fix use-after-free with nested FFI::addr() calls #9599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@iluuu1994 thanks for looking into this. See https://www.php.net/manual/en/ffi.addr.php
I don't think this should be fixed, may be it's better to throw a error. |
@dstogov Ah! Thanks for explaining. Should've read the documentation better 🙂
Yeah, I found this in a Symfony test which I'll fix instead then.
This would be the case when Lines 4231 to 4242 in b61c81c
Edit: I later found out transferring ownership of other things like structs works just fine as for those the |
…n test (iluuu1994) This PR was merged into the 6.2 branch. Discussion ---------- [VarDumper] Fix use-after-free with nested FFI::addr() in test | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | php/php-src#9598 | License | MIT | Doc PR | This issue was found by the PHP community build, after which I created php/php-src#9598. Basically, the inner `\FFI::addr()` `CData` will be deallocated after the second `\FFI::addr()` call which will be stored and then points to invalid memory. However, [it turns out](php/php-src#9599 (comment)) nesting `\FFI::addr()` calls without temporarily storing the result is actually not allowed. https://www.php.net/manual/en/ffi.addr.php > Creates an unmanaged pointer to the C data represented by the given `FFI\CData`. The source ptr must survive the resulting pointer. This function is mainly useful to pass arguments to C functions by pointer. We'll see if we can improve `FFI` by throwing an exception when passing temporary values to `FFI::addr()`. Either way, this test is not valid. Commits ------- 4c79915 Fix use-after-free with nested FFI::addr() in VarDumper test
…n test (iluuu1994) This PR was merged into the 6.2 branch. Discussion ---------- [VarDumper] Fix use-after-free with nested FFI::addr() in test | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | php/php-src#9598 | License | MIT | Doc PR | This issue was found by the PHP community build, after which I created php/php-src#9598. Basically, the inner `\FFI::addr()` `CData` will be deallocated after the second `\FFI::addr()` call which will be stored and then points to invalid memory. However, [it turns out](php/php-src#9599 (comment)) nesting `\FFI::addr()` calls without temporarily storing the result is actually not allowed. https://www.php.net/manual/en/ffi.addr.php > Creates an unmanaged pointer to the C data represented by the given `FFI\CData`. The source ptr must survive the resulting pointer. This function is mainly useful to pass arguments to C functions by pointer. We'll see if we can improve `FFI` by throwing an exception when passing temporary values to `FFI::addr()`. Either way, this test is not valid. Commits ------- 4c799152ec Fix use-after-free with nested FFI::addr() in VarDumper test
Fixes GH-9598
@dstogov I did not see another way to solve this. Basically,
cdata1.ptr -> cdata1.ptr_holder -> cdata2.ptr_holder -> Example
. Right after\FFI::addr(\FFI::addr($struct))
cdata2
is released. Since this object is released by the VM when theTMPVAR
is destroyed we need to increase the refcount of the CData object itself.Please let me know if you can see a better solution. This is the first time I've looked at the FFI internals, very much possible I'm missing something simple.
Thanks!