Skip to content

Commit 192e1ce

Browse files
committed
Avoid @prefer-ref arguments
1 parent 2de0d8e commit 192e1ce

File tree

3 files changed

+68
-62
lines changed

3 files changed

+68
-62
lines changed

ext/ffi/ffi.c

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

550550
again:
@@ -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+
12241243
static 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

42044233
ZEND_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();

ext/ffi/ffi.stub.php

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,53 +17,40 @@ public static function scope(string $name): FFI {}
1717

1818
public static function new(FFI\CType|string $type, bool $owned = true, bool $persistent = false): FFI\CData {}
1919

20-
/** @prefer-ref $ptr */
2120
public static function free(FFI\CData $ptr): void {}
2221

2322
/**
2423
* @param FFI\CData|int|float|bool|null $ptr
25-
* @prefer-ref $ptr
2624
*/
2725
public static function cast(FFI\CType|string $type, $ptr): FFI\CData {}
2826

2927
public static function type(string $type): FFI\CType {}
3028

31-
/** @prefer-ref $ptr */
3229
public static function typeof(FFI\CData $ptr): FFI\CType {}
3330

3431
public static function arrayType(FFI\CType $type, array $dimensions): FFI\CType {}
3532

36-
/** @prefer-ref $ptr */
3733
public static function addr(FFI\CData $ptr): FFI\CData {}
3834

39-
/** @prefer-ref $ptr */
4035
public static function sizeof(FFI\CData|FFI\CType $ptr): int {}
4136

42-
/** @prefer-ref $ptr */
4337
public static function alignof(FFI\CData|FFI\CType $ptr): int {}
4438

4539
/**
4640
* @param FFI\CData|string $from
47-
* @prefer-ref $to
48-
* @prefer-ref $from
4941
*/
5042
public static function memcpy(FFI\CData $to, $from, int $size): void {}
5143

5244
/**
53-
* @prefer-ref $ptr1
5445
* @param string|FFI\CData $ptr1
55-
* @prefer-ref $ptr2
5646
* @param string|FFI\CData $ptr2
5747
*/
5848
public static function memcmp($ptr1, $ptr2, int $size): int {}
5949

60-
/** @prefer-ref $ptr */
6150
public static function memset(FFI\CData $ptr, int $value, int $size): void {}
6251

63-
/** @prefer-ref $ptr */
6452
public static function string(FFI\CData $ptr, ?int $size = null): string {}
6553

66-
/** @prefer-ref $ptr */
6754
public static function isNull(FFI\CData $ptr): bool {}
6855
}
6956

0 commit comments

Comments
 (0)