@@ -542,9 +542,9 @@ static zend_never_inline zend_ffi_cdata *zend_ffi_cdata_to_zval_slow_ret(void *p
542542}
543543/* }}} */
544544
545- static zend_always_inline void zend_ffi_cdata_to_zval (zend_ffi_cdata * cdata , void * ptr , zend_ffi_type * type , int read_type , zval * rv , zend_ffi_flags flags , bool is_ret , bool debug_union ) /* {{{ */
545+ static zend_always_inline void zend_ffi_cdata_to_zval (zend_ffi_cdata * cdata , void * ptr , zend_ffi_type * type , int convert , zval * rv , zend_ffi_flags flags , bool is_ret , bool debug_union ) /* {{{ */
546546{
547- if (read_type == BP_VAR_R ) {
547+ if (convert && type -> kind <= ZEND_FFI_TYPE_POINTER ) {
548548 zend_ffi_type_kind kind = type -> kind ;
549549
550550again :
@@ -959,7 +959,7 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v
959959
960960 ZEND_HASH_PACKED_FOREACH_PTR (callback_data -> type -> func .args , arg_type ) {
961961 arg_type = ZEND_FFI_TYPE (arg_type );
962- zend_ffi_cdata_to_zval (NULL , args [n ], arg_type , BP_VAR_R , & fci .params [n ], (zend_ffi_flags )(arg_type -> attr & ZEND_FFI_ATTR_CONST ), 0 , 0 );
962+ zend_ffi_cdata_to_zval (NULL , args [n ], arg_type , 1 , & fci .params [n ], (zend_ffi_flags )(arg_type -> attr & ZEND_FFI_ATTR_CONST ), 0 , 0 );
963963 n ++ ;
964964 } ZEND_HASH_FOREACH_END ();
965965 }
@@ -1116,7 +1116,7 @@ static zval *zend_ffi_cdata_get(zend_object *obj, zend_string *member, int read_
11161116 return & EG (uninitialized_zval );
11171117 }
11181118
1119- zend_ffi_cdata_to_zval (cdata , cdata -> ptr , type , BP_VAR_R , rv , 0 , 0 , 0 );
1119+ zend_ffi_cdata_to_zval (cdata , cdata -> ptr , type , 1 , rv , 0 , 0 , 0 );
11201120 return rv ;
11211121}
11221122/* }}} */
@@ -1221,6 +1221,25 @@ static zend_result zend_ffi_cdata_cast_object(zend_object *readobj, zval *writeo
12211221}
12221222/* }}} */
12231223
1224+ static int zend_ffi_should_convert_cdata (void )
1225+ {
1226+ zend_execute_data * execute_data = EG (current_execute_data );
1227+
1228+ if (execute_data
1229+ && EX (opline )
1230+ && EX (call )
1231+ && (EX (opline )-> opcode == ZEND_FETCH_OBJ_R
1232+ || EX (opline )-> opcode == ZEND_FETCH_OBJ_FUNC_ARG
1233+ || EX (opline )-> opcode == ZEND_FETCH_DIM_R
1234+ || EX (opline )-> opcode == ZEND_FETCH_DIM_FUNC_ARG )
1235+ && EX (call )-> func
1236+ && EX (call )-> func -> type == ZEND_INTERNAL_FUNCTION
1237+ && EX (call )-> func -> internal_function .module == & ffi_module_entry ) {
1238+ return 0 ;
1239+ }
1240+ return 1 ;
1241+ }
1242+
12241243static zval * zend_ffi_cdata_read_field (zend_object * obj , zend_string * field_name , int read_type , void * * cache_slot , zval * rv ) /* {{{ */
12251244{
12261245 zend_ffi_cdata * cdata = (zend_ffi_cdata * )obj ;
@@ -1285,7 +1304,11 @@ static zval *zend_ffi_cdata_read_field(zend_object *obj, zend_string *field_name
12851304 }
12861305 }
12871306 ptr = (void * )(((char * )ptr ) + field -> offset );
1288- zend_ffi_cdata_to_zval (NULL , ptr , field_type , read_type , rv , (cdata -> flags & ZEND_FFI_FLAG_CONST ) | (zend_ffi_flags )field -> is_const , 0 , 0 );
1307+ int convert = 0 ;
1308+ if (read_type == BP_VAR_R && field_type -> kind <= ZEND_FFI_TYPE_POINTER ) {
1309+ convert = zend_ffi_should_convert_cdata ();
1310+ }
1311+ zend_ffi_cdata_to_zval (NULL , ptr , field_type , convert , rv , (cdata -> flags & ZEND_FFI_FLAG_CONST ) | (zend_ffi_flags )field -> is_const , 0 , 0 );
12891312 } else {
12901313 zend_ffi_bit_field_to_zval (ptr , field , rv );
12911314 }
@@ -1421,7 +1444,11 @@ static zval *zend_ffi_cdata_read_dim(zend_object *obj, zval *offset, int read_ty
14211444 return & EG (uninitialized_zval );
14221445 }
14231446
1424- zend_ffi_cdata_to_zval (NULL , ptr , dim_type , read_type , rv , is_const , 0 , 0 );
1447+ int convert = 0 ;
1448+ if (read_type == BP_VAR_R && dim_type -> kind <= ZEND_FFI_TYPE_POINTER ) {
1449+ convert = zend_ffi_should_convert_cdata ();
1450+ }
1451+ zend_ffi_cdata_to_zval (NULL , ptr , dim_type , convert , rv , is_const , 0 , 0 );
14251452 return rv ;
14261453}
14271454/* }}} */
@@ -1967,7 +1994,7 @@ static zval *zend_ffi_cdata_it_get_current_data(zend_object_iterator *it) /* {{{
19671994 ptr = (void * )((char * )cdata -> ptr + dim_type -> size * iter -> it .index );
19681995
19691996 zval_ptr_dtor (& iter -> value );
1970- zend_ffi_cdata_to_zval (NULL , ptr , dim_type , iter -> by_ref ? BP_VAR_RW : BP_VAR_R , & iter -> value , (cdata -> flags & ZEND_FFI_FLAG_CONST ) | (zend_ffi_flags )(type -> attr & ZEND_FFI_ATTR_CONST ), 0 , 0 );
1997+ zend_ffi_cdata_to_zval (NULL , ptr , dim_type , iter -> by_ref ? 0 : 1 , & iter -> value , (cdata -> flags & ZEND_FFI_FLAG_CONST ) | (zend_ffi_flags )(type -> attr & ZEND_FFI_ATTR_CONST ), 0 , 0 );
19711998 return & iter -> value ;
19721999}
19732000/* }}} */
@@ -2065,7 +2092,7 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp)
20652092 case ZEND_FFI_TYPE_SINT32 :
20662093 case ZEND_FFI_TYPE_UINT64 :
20672094 case ZEND_FFI_TYPE_SINT64 :
2068- zend_ffi_cdata_to_zval (cdata , ptr , type , BP_VAR_R , & tmp , ZEND_FFI_FLAG_CONST , 0 , 0 );
2095+ zend_ffi_cdata_to_zval (cdata , ptr , type , 1 , & tmp , ZEND_FFI_FLAG_CONST , 0 , 0 );
20692096 ht = zend_new_array (1 );
20702097 zend_hash_str_add (ht , "cdata" , sizeof ("cdata" )- 1 , & tmp );
20712098 * is_temp = 1 ;
@@ -2085,7 +2112,7 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp)
20852112 * is_temp = 1 ;
20862113 return ht ;
20872114 } else {
2088- zend_ffi_cdata_to_zval (NULL , * (void * * )ptr , ZEND_FFI_TYPE (type -> pointer .type ), BP_VAR_R , & tmp , ZEND_FFI_FLAG_CONST , 0 , 0 );
2115+ zend_ffi_cdata_to_zval (NULL , * (void * * )ptr , ZEND_FFI_TYPE (type -> pointer .type ), 1 , & tmp , ZEND_FFI_FLAG_CONST , 0 , 0 );
20892116 ht = zend_new_array (1 );
20902117 zend_hash_index_add_new (ht , 0 , & tmp );
20912118 * is_temp = 1 ;
@@ -2098,7 +2125,7 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp)
20982125 if (key ) {
20992126 if (!f -> bits ) {
21002127 void * f_ptr = (void * )(((char * )ptr ) + f -> offset );
2101- zend_ffi_cdata_to_zval (NULL , f_ptr , ZEND_FFI_TYPE (f -> type ), BP_VAR_R , & tmp , ZEND_FFI_FLAG_CONST , 0 , type -> attr & ZEND_FFI_ATTR_UNION );
2128+ zend_ffi_cdata_to_zval (NULL , f_ptr , ZEND_FFI_TYPE (f -> type ), 1 , & tmp , ZEND_FFI_FLAG_CONST , 0 , type -> attr & ZEND_FFI_ATTR_UNION );
21022129 zend_hash_add (ht , key , & tmp );
21032130 } else {
21042131 zend_ffi_bit_field_to_zval (ptr , f , & tmp );
@@ -2111,7 +2138,7 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp)
21112138 case ZEND_FFI_TYPE_ARRAY :
21122139 ht = zend_new_array (type -> array .length );
21132140 for (n = 0 ; n < type -> array .length ; n ++ ) {
2114- zend_ffi_cdata_to_zval (NULL , ptr , ZEND_FFI_TYPE (type -> array .type ), BP_VAR_R , & tmp , ZEND_FFI_FLAG_CONST , 0 , 0 );
2141+ zend_ffi_cdata_to_zval (NULL , ptr , ZEND_FFI_TYPE (type -> array .type ), 1 , & tmp , ZEND_FFI_FLAG_CONST , 0 , 0 );
21152142 zend_hash_index_add (ht , n , & tmp );
21162143 ptr = (void * )(((char * )ptr ) + ZEND_FFI_TYPE (type -> array .type )-> size );
21172144 }
@@ -2492,7 +2519,12 @@ static zval *zend_ffi_read_var(zend_object *obj, zend_string *var_name, int read
24922519 }
24932520
24942521 if (sym -> kind == ZEND_FFI_SYM_VAR ) {
2495- zend_ffi_cdata_to_zval (NULL , sym -> addr , ZEND_FFI_TYPE (sym -> type ), read_type , rv , (zend_ffi_flags )sym -> is_const , 0 , 0 );
2522+ zend_ffi_type * sym_type = ZEND_FFI_TYPE (sym -> type );
2523+ int convert = 0 ;
2524+ if (read_type == BP_VAR_R && sym_type -> kind <= ZEND_FFI_TYPE_POINTER ) {
2525+ convert = zend_ffi_should_convert_cdata ();
2526+ }
2527+ zend_ffi_cdata_to_zval (NULL , sym -> addr , sym_type , convert , rv , (zend_ffi_flags )sym -> is_const , 0 , 0 );
24962528 } else if (sym -> kind == ZEND_FFI_SYM_FUNC ) {
24972529 zend_ffi_cdata * cdata ;
24982530 zend_ffi_type * new_type = emalloc (sizeof (zend_ffi_type ));
@@ -2855,7 +2887,7 @@ static ZEND_FUNCTION(ffi_trampoline) /* {{{ */
28552887 }
28562888
28572889 if (ZEND_FFI_TYPE (type -> func .ret_type )-> kind != ZEND_FFI_TYPE_VOID ) {
2858- zend_ffi_cdata_to_zval (NULL , ret , ZEND_FFI_TYPE (type -> func .ret_type ), BP_VAR_R , return_value , 0 , 1 , 0 );
2890+ zend_ffi_cdata_to_zval (NULL , ret , ZEND_FFI_TYPE (type -> func .ret_type ), 1 , return_value , 0 , 1 , 0 );
28592891 } else {
28602892 ZVAL_NULL (return_value );
28612893 }
@@ -3926,7 +3958,7 @@ ZEND_METHOD(FFI, free) /* {{{ */
39263958
39273959 ZEND_FFI_VALIDATE_API_RESTRICTION ();
39283960 ZEND_PARSE_PARAMETERS_START (1 , 1 )
3929- Z_PARAM_OBJECT_OF_CLASS_EX (zv , zend_ffi_cdata_ce , 0 , 1 );
3961+ Z_PARAM_OBJECT_OF_CLASS (zv , zend_ffi_cdata_ce );
39303962 ZEND_PARSE_PARAMETERS_END ();
39313963
39323964 cdata = (zend_ffi_cdata * )Z_OBJ_P (zv );
@@ -3961,7 +3993,7 @@ ZEND_METHOD(FFI, cast) /* {{{ */
39613993 zend_ffi_cdata * old_cdata , * cdata ;
39623994 bool is_const = 0 ;
39633995 bool is_static_call = Z_TYPE (EX (This )) != IS_OBJECT ;
3964- zval * zv , * arg ;
3996+ zval * zv ;
39653997 void * ptr ;
39663998
39673999 ZEND_FFI_VALIDATE_API_RESTRICTION ();
@@ -3977,9 +4009,6 @@ ZEND_METHOD(FFI, cast) /* {{{ */
39774009 }
39784010 }
39794011
3980- arg = zv ;
3981- ZVAL_DEREF (zv );
3982-
39834012 if (type_def ) {
39844013 zend_ffi_dcl dcl = ZEND_FFI_ATTR_INIT ;
39854014
@@ -4123,7 +4152,7 @@ ZEND_METHOD(FFI, cast) /* {{{ */
41234152 }
41244153
41254154 if (old_cdata -> flags & ZEND_FFI_FLAG_OWNED ) {
4126- if (GC_REFCOUNT (& old_cdata -> std ) == 1 && Z_REFCOUNT_P ( arg ) == 1 ) {
4155+ if (GC_REFCOUNT (& old_cdata -> std ) == 1 ) {
41274156 /* transfer ownership */
41284157 old_cdata -> flags &= ~ZEND_FFI_FLAG_OWNED ;
41294158 cdata -> flags |= ZEND_FFI_FLAG_OWNED ;
@@ -4203,7 +4232,7 @@ ZEND_METHOD(FFI, type) /* {{{ */
42034232
42044233ZEND_METHOD (FFI , typeof ) /* {{{ */
42054234{
4206- zval * zv , * arg ;
4235+ zval * zv ;
42074236 zend_ffi_ctype * ctype ;
42084237 zend_ffi_type * type ;
42094238
@@ -4212,16 +4241,14 @@ ZEND_METHOD(FFI, typeof) /* {{{ */
42124241 Z_PARAM_ZVAL (zv );
42134242 ZEND_PARSE_PARAMETERS_END ();
42144243
4215- arg = zv ;
4216- ZVAL_DEREF (zv );
42174244 if (Z_TYPE_P (zv ) == IS_OBJECT && Z_OBJCE_P (zv ) == zend_ffi_cdata_ce ) {
42184245 zend_ffi_cdata * cdata = (zend_ffi_cdata * )Z_OBJ_P (zv );
42194246
42204247 type = cdata -> type ;
42214248 if (ZEND_FFI_TYPE_IS_OWNED (type )) {
42224249 type = ZEND_FFI_TYPE (type );
42234250 if (!(type -> attr & ZEND_FFI_ATTR_STORED )) {
4224- if (GC_REFCOUNT (& cdata -> std ) == 1 && Z_REFCOUNT_P ( arg ) == 1 ) {
4251+ if (GC_REFCOUNT (& cdata -> std ) == 1 ) {
42254252 /* transfer type ownership */
42264253 cdata -> type = type ;
42274254 type = ZEND_FFI_TYPE_MAKE_OWNED (type );
@@ -4325,15 +4352,13 @@ ZEND_METHOD(FFI, addr) /* {{{ */
43254352{
43264353 zend_ffi_type * type , * new_type ;
43274354 zend_ffi_cdata * cdata , * new_cdata ;
4328- zval * zv , * arg ;
4355+ zval * zv ;
43294356
43304357 ZEND_FFI_VALIDATE_API_RESTRICTION ();
43314358 ZEND_PARSE_PARAMETERS_START (1 , 1 )
43324359 Z_PARAM_ZVAL (zv )
43334360 ZEND_PARSE_PARAMETERS_END ();
43344361
4335- arg = zv ;
4336- ZVAL_DEREF (zv );
43374362 if (Z_TYPE_P (zv ) != IS_OBJECT || Z_OBJCE_P (zv ) != zend_ffi_cdata_ce ) {
43384363 zend_wrong_parameter_class_error (1 , "FFI\\CData" , zv );
43394364 RETURN_THROWS ();
@@ -4342,7 +4367,7 @@ ZEND_METHOD(FFI, addr) /* {{{ */
43424367 cdata = (zend_ffi_cdata * )Z_OBJ_P (zv );
43434368 type = ZEND_FFI_TYPE (cdata -> type );
43444369
4345- if (GC_REFCOUNT (& cdata -> std ) == 1 && Z_REFCOUNT_P ( arg ) == 1 && type -> kind == ZEND_FFI_TYPE_POINTER
4370+ if (GC_REFCOUNT (& cdata -> std ) == 1 && type -> kind == ZEND_FFI_TYPE_POINTER
43464371 && cdata -> ptr == & cdata -> ptr_holder ) {
43474372 zend_throw_error (zend_ffi_exception_ce , "FFI::addr() cannot create a reference to a temporary pointer" );
43484373 RETURN_THROWS ();
@@ -4361,7 +4386,7 @@ ZEND_METHOD(FFI, addr) /* {{{ */
43614386 new_cdata -> ptr_holder = cdata -> ptr ;
43624387 new_cdata -> ptr = & new_cdata -> ptr_holder ;
43634388
4364- if (GC_REFCOUNT (& cdata -> std ) == 1 && Z_REFCOUNT_P ( arg ) == 1 ) {
4389+ if (GC_REFCOUNT (& cdata -> std ) == 1 ) {
43654390 if (ZEND_FFI_TYPE_IS_OWNED (cdata -> type )) {
43664391 /* transfer type ownership */
43674392 cdata -> type = type ;
@@ -4388,7 +4413,6 @@ ZEND_METHOD(FFI, sizeof) /* {{{ */
43884413 Z_PARAM_ZVAL (zv );
43894414 ZEND_PARSE_PARAMETERS_END ();
43904415
4391- ZVAL_DEREF (zv );
43924416 if (Z_TYPE_P (zv ) == IS_OBJECT && Z_OBJCE_P (zv ) == zend_ffi_cdata_ce ) {
43934417 zend_ffi_cdata * cdata = (zend_ffi_cdata * )Z_OBJ_P (zv );
43944418 type = ZEND_FFI_TYPE (cdata -> type );
@@ -4414,7 +4438,6 @@ ZEND_METHOD(FFI, alignof) /* {{{ */
44144438 Z_PARAM_ZVAL (zv );
44154439 ZEND_PARSE_PARAMETERS_END ();
44164440
4417- ZVAL_DEREF (zv );
44184441 if (Z_TYPE_P (zv ) == IS_OBJECT && Z_OBJCE_P (zv ) == zend_ffi_cdata_ce ) {
44194442 zend_ffi_cdata * cdata = (zend_ffi_cdata * )Z_OBJ_P (zv );
44204443 type = ZEND_FFI_TYPE (cdata -> type );
@@ -4440,7 +4463,7 @@ ZEND_METHOD(FFI, memcpy) /* {{{ */
44404463
44414464 ZEND_FFI_VALIDATE_API_RESTRICTION ();
44424465 ZEND_PARSE_PARAMETERS_START (3 , 3 )
4443- Z_PARAM_OBJECT_OF_CLASS_EX (zv1 , zend_ffi_cdata_ce , 0 , 1 );
4466+ Z_PARAM_OBJECT_OF_CLASS (zv1 , zend_ffi_cdata_ce );
44444467 Z_PARAM_ZVAL (zv2 )
44454468 Z_PARAM_LONG (size )
44464469 ZEND_PARSE_PARAMETERS_END ();
@@ -4457,7 +4480,6 @@ ZEND_METHOD(FFI, memcpy) /* {{{ */
44574480 }
44584481 }
44594482
4460- ZVAL_DEREF (zv2 );
44614483 if (Z_TYPE_P (zv2 ) == IS_STRING ) {
44624484 ptr2 = Z_STRVAL_P (zv2 );
44634485 if (size > Z_STRLEN_P (zv2 )) {
@@ -4501,7 +4523,6 @@ ZEND_METHOD(FFI, memcmp) /* {{{ */
45014523 Z_PARAM_LONG (size )
45024524 ZEND_PARSE_PARAMETERS_END ();
45034525
4504- ZVAL_DEREF (zv1 );
45054526 if (Z_TYPE_P (zv1 ) == IS_STRING ) {
45064527 ptr1 = Z_STRVAL_P (zv1 );
45074528 if (size > Z_STRLEN_P (zv1 )) {
@@ -4525,7 +4546,6 @@ ZEND_METHOD(FFI, memcmp) /* {{{ */
45254546 RETURN_THROWS ();
45264547 }
45274548
4528- ZVAL_DEREF (zv2 );
45294549 if (Z_TYPE_P (zv2 ) == IS_STRING ) {
45304550 ptr2 = Z_STRVAL_P (zv2 );
45314551 if (size > Z_STRLEN_P (zv2 )) {
@@ -4602,7 +4622,7 @@ ZEND_METHOD(FFI, string) /* {{{ */
46024622
46034623 ZEND_FFI_VALIDATE_API_RESTRICTION ();
46044624 ZEND_PARSE_PARAMETERS_START (1 , 2 )
4605- Z_PARAM_OBJECT_OF_CLASS_EX (zv , zend_ffi_cdata_ce , 0 , 1 );
4625+ Z_PARAM_OBJECT_OF_CLASS (zv , zend_ffi_cdata_ce );
46064626 Z_PARAM_OPTIONAL
46074627 Z_PARAM_LONG_OR_NULL (size , size_is_null )
46084628 ZEND_PARSE_PARAMETERS_END ();
@@ -4645,7 +4665,6 @@ ZEND_METHOD(FFI, isNull) /* {{{ */
46454665 Z_PARAM_ZVAL (zv );
46464666 ZEND_PARSE_PARAMETERS_END ();
46474667
4648- ZVAL_DEREF (zv );
46494668 if (Z_TYPE_P (zv ) != IS_OBJECT || Z_OBJCE_P (zv ) != zend_ffi_cdata_ce ) {
46504669 zend_wrong_parameter_class_error (1 , "FFI\\CData" , zv );
46514670 RETURN_THROWS ();
0 commit comments