@@ -148,11 +148,21 @@ php_stream_filter_status_t userfilter_filter(
148148 stream -> flags |= PHP_STREAM_FLAG_NO_FCLOSE ;
149149
150150 /* Give the userfilter class a hook back to the stream */
151- zval * stream_prop = zend_hash_str_find (Z_OBJPROP_P (obj ), "stream" , sizeof ("stream" )- 1 );
152- if (stream_prop ) {
151+ zend_property_info * prop_info = zend_hash_str_find_ptr (& Z_OBJCE_P (obj )-> properties_info , "stream" , sizeof ("stream" )- 1 );
152+
153+ if (prop_info ) {
154+ /* Declared property (may be uninitialized typed property) - always update */
153155 zval stream_zval ;
154156 php_stream_to_zval (stream , & stream_zval );
155157 zend_update_property (Z_OBJCE_P (obj ), Z_OBJ_P (obj ), "stream" , sizeof ("stream" )- 1 , & stream_zval );
158+ } else {
159+ /* Check if it's a dynamic property - only access OBJPROP as fallback */
160+ zval * stream_prop = zend_hash_str_find (Z_OBJPROP_P (obj ), "stream" , sizeof ("stream" )- 1 );
161+ if (stream_prop ) {
162+ zval stream_zval ;
163+ php_stream_to_zval (stream , & stream_zval );
164+ zend_update_property (Z_OBJCE_P (obj ), Z_OBJ_P (obj ), "stream" , sizeof ("stream" )- 1 , & stream_zval );
165+ }
156166 }
157167
158168 ZVAL_STRINGL (& func_name , "filter" , sizeof ("filter" )- 1 );
@@ -196,8 +206,20 @@ php_stream_filter_status_t userfilter_filter(
196206 /* filter resources are cleaned up by the stream destructor,
197207 * keeping a reference to the stream resource here would prevent it
198208 * from being destroyed properly */
199- if (stream_prop ) {
200- zend_update_property_null (Z_OBJCE_P (obj ), Z_OBJ_P (obj ), "stream" , sizeof ("stream" )- 1 );
209+ if (prop_info ) {
210+ /* Declared property - find the actual value to clean it up */
211+ zval * stream_prop = zend_hash_str_find (Z_OBJPROP_P (obj ), "stream" , sizeof ("stream" )- 1 );
212+ if (stream_prop ) {
213+ /* Use direct manipulation to avoid type checking during cleanup.
214+ * We need to break the resource reference regardless of property type constraints. */
215+ convert_to_null (stream_prop );
216+ }
217+ } else {
218+ /* Dynamic property - check if it exists */
219+ zval * stream_prop = zend_hash_str_find (Z_OBJPROP_P (obj ), "stream" , sizeof ("stream" )- 1 );
220+ if (stream_prop ) {
221+ convert_to_null (stream_prop );
222+ }
201223 }
202224
203225 zval_ptr_dtor (& args [3 ]);
0 commit comments