FFI\CData use-after-free after FFI object destroyed
Open
Nobody has claimed this yet.
Bug
Extension: ffi
Status: Verified
- Dominant language
- C
- Stars
- 40.4k
- Forks
- 8.1k
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 96
Description
Description
The following code:
<?php
putenv("TEST=123");
var_dump((FFI::cdef("char *getenv(char *);", "/lib/x86_64-linux-gnu/libc.so.6"))->getenv("TEST"));
Resulted in an use-after-free:
FFI seems to free associated types instead of passing the type forward to the CData and refcounting them.
==571167== Invalid read of size 4
==571167== at 0x441331: zend_ffi_cdata_get_debug_info (ffi.c:1975)
==571167== by 0x90289D: zend_std_get_properties_for (zend_object_handlers.c:1912)
==571167== by 0x902993: zend_get_properties_for (zend_object_handlers.c:1941)
==571167== by 0x70AB9A: php_var_dump (var.c:163)
==571167== by 0x70B19D: zif_var_dump (var.c:228)
==571167== by 0x84E353: ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1250)
==571167== by 0x8C5FE3: execute_ex (zend_vm_execute.h:55851)
==571167== by 0x8CB80F: zend_execute (zend_vm_execute.h:60210)
==571167== by 0x7F4369: zend_eval_stringl (zend_execute_API.c:1266)
==571167== by 0x7F457D: zend_eval_stringl_ex (zend_execute_API.c:1308)
==571167== by 0x7F45F6: zend_eval_string_ex (zend_execute_API.c:1318)
==571167== by 0x989378: do_cli (php_cli.c:996)
==571167== Address 0x769f150 is 0 bytes inside a block of size 88 free'd
==571167== at 0x4A4292F: free (vg_replace_malloc.c:872)
==571167== by 0x7CC99B: _efree_custom (zend_alloc.c:2438)
==571167== by 0x7CCAF2: _efree (zend_alloc.c:2558)
==571167== by 0x441EED: _zend_ffi_type_dtor (ffi.c:2252)
==571167== by 0x43C4BA: zend_ffi_type_dtor (ffi.c:224)
==571167== by 0x441EA6: _zend_ffi_type_dtor (ffi.c:2247)
==571167== by 0x43C4BA: zend_ffi_type_dtor (ffi.c:224)
==571167== by 0x441FD0: zend_ffi_symbol_hash_dtor (ffi.c:2282)
==571167== by 0x8280E9: zend_hash_destroy (zend_hash.c:1695)
==571167== by 0x442284: zend_ffi_free_obj (ffi.c:2353)
==571167== by 0x90315A: zend_objects_store_del (zend_objects_API.c:200)
==571167== by 0x83D5D7: zend_object_release (zend_objects_API.h:75)
==571167== Block was alloc'd at
==571167== at 0x4A40045: malloc (vg_replace_malloc.c:381)
==571167== by 0x7CDE59: __zend_malloc (zend_alloc.c:3078)
==571167== by 0x7CC92A: _malloc_custom (zend_alloc.c:2429)
==571167== by 0x7CCA74: _emalloc (zend_alloc.c:2548)
==571167== by 0x4531F3: zend_ffi_make_pointer_type (ffi.c:6196)
==571167== by 0x461DEA: parse_pointer (ffi_parser.c:2660)
==571167== by 0x46198C: parse_declarator (ffi_parser.c:2574)
==571167== by 0x45FFFB: parse_declarations (ffi_parser.c:2024)
==571167== by 0x464284: parse (ffi_parser.c:3549)
==571167== by 0x464302: zend_ffi_parse_decl (ffi_parser.c:3561)
==571167== by 0x444B64: zim_FFI_cdef (ffi.c:2915)
==571167== by 0x84FC46: ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER (zend_vm_execute.h:1885)
// more...
object(FFI\CData:char*)#2 (1) {
[0]=>
string(1) "1"
}
PHP Version
master
Operating System
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the PHP FFI\CData example under Valgrind, then inspect ffi.c at zend_ffi_cdata_get_debug_info(), zend_ffi_free_obj(), and the FFI type destructors shown in the trace. Ensure the type used by CData remains valid after the FFI object is destroyed, and verify that the example no longer reports an invalid read.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, php
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100