[php-src] Issue #9698: stream_wrapper_register crashes with FFI\CData provided as class. Forbid it for some/all classes with custom handlers?

From: Date: Sun, 09 Oct 2022 16:19:47 +0000
Subject: [php-src] Issue #9698: stream_wrapper_register crashes with FFI\CData provided as class. Forbid it for some/all classes with custom handlers?
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-242552@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/9698 Author: TysonAndre ### Description The following code: ```php <?php stream_wrapper_register('badffi', 'FFI\CData'); file_get_contents('badffi://x'); ``` Resulted in this output: ``` segmentation fault (core dumped) ``` ``` ==80156== Invalid read of size 4 ==80156== at 0x4B6334: zend_ffi_cdata_write_field (ffi.c:1290) ==80156== by 0xA7D376: add_property_zval_ex (zend_API.c:2183) ==80156== by 0xA7CEE3: add_property_resource_ex (zend_API.c:2104) ==80156== by 0x9F8C19: add_property_resource (zend_API.h:640) ==80156== by 0x9F9131: user_stream_create_object (userspace.c:302) ==80156== by 0x9F92FC: user_wrapper_opener (userspace.c:345) ==80156== by 0x9EFC2C: _php_stream_open_wrapper_ex (streams.c:2167) ==80156== by 0x889A9A: zif_file_get_contents (file.c:426) ==80156== by 0x7059BD: phar_file_get_contents (func_interceptors.c:227) ==80156== by 0xAB4919: ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1250) ==80156== by 0xB2B883: execute_ex (zend_vm_execute.h:55975) ==80156== by 0xB310D5: zend_execute (zend_vm_execute.h:60343) ==80156== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==80156== ==80156== ==80156== Process terminating with default action of signal 11 (SIGSEGV) ==80156== Access not within mapped region at address 0x0 ==80156== at 0x4B6334: zend_ffi_cdata_write_field (ffi.c:1290) ==80156== by 0xA7D376: add_property_zval_ex (zend_API.c:2183) ==80156== by 0xA7CEE3: add_property_resource_ex (zend_API.c:2104) ==80156== by 0x9F8C19: add_property_resource (zend_API.h:640) ==80156== by 0x9F9131: user_stream_create_object (userspace.c:302) ==80156== by 0x9F92FC: user_wrapper_opener (userspace.c:345) ==80156== by 0x9EFC2C: _php_stream_open_wrapper_ex (streams.c:2167) ==80156== by 0x889A9A: zif_file_get_contents (file.c:426) ==80156== by 0x7059BD: phar_file_get_contents (func_interceptors.c:227) ==80156== by 0xAB4919: ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1250) ==80156== by 0xB2B883: execute_ex (zend_vm_execute.h:55975) ==80156== by 0xB310D5: zend_execute (zend_vm_execute.h:60343) ``` But I expected this output instead: ``` // A thrown error for attempting to call the constructor of CData ``` ------ Other notes: 1. Stream wrappers work by adding dynamic properties to a class 2. This could check obj->handlers for write_property, get_properties, get_properties_for, and read_property overrides? 3. It might make sense to check if the constructor succeeded (EG(exception) == NULL) **before** setting context. FFI crashes because the object isn't initialized. That may be a bc break if any constructors check $this->context Maybe that should be done that way only for internal classes and their subclasses in older php versions, to minimize the impact 4. (new ReflectionClass('FFI\CData'))->newInstanceWithoutConstructor() throws for internal classes right now - but stream wrappers do call constructors (streams are just modifying the object before calling the constructor) ```c // main/streams/userspace.c static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context, zval *object) { if (uwrap->ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { ZVAL_UNDEF(object); return; } /* create an instance of our class */ if (object_init_ex(object, uwrap->ce) == FAILURE) { ZVAL_UNDEF(object); return; } if (context) { GC_ADDREF(context->res); add_property_resource(object, "context", context->res); } else { add_property_null(object, "context"); } if (uwrap->ce->constructor) { zend_call_known_instance_method_with_0_params( uwrap->ce->constructor, Z_OBJ_P(object), NULL); } } ``` Noticed while looking into #9697 but they have different causes ### PHP Version 7.4-8.3-dev ### Operating System _No response_

« previous php.bugs (#242552) next »