Skip to content

Commit 5ea2b36

Browse files
committed
Merge branch 'PHP-7.0' of git.php.net:/php-src into PHP-7.0
* 'PHP-7.0' of git.php.net:/php-src: Prevent usage in GC after free. Fix SEND_USER as well Fix SEND_ARRAY+PREFER_REF SHM corruption
2 parents 7648f20 + e46be0c commit 5ea2b36

File tree

4 files changed

+82
-73
lines changed

4 files changed

+82
-73
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
--TEST--
2+
call_user_func_array() passes value to prefer-ref arg if element wasn't a reference
3+
--FILE--
4+
<?php
5+
6+
namespace {
7+
call_user_func_array('array_multisort', [[3, 2, 1]]);
8+
9+
$args = [[3, 2, 1]];
10+
call_user_func_array('array_multisort', $args);
11+
var_dump($args);
12+
unset($args);
13+
14+
$array = [3, 2, 1];
15+
call_user_func('array_multisort', $array);
16+
var_dump($array);
17+
unset($array);
18+
}
19+
20+
namespace Foo {
21+
call_user_func_array('array_multisort', [[3, 2, 1]]);
22+
23+
$args = [[3, 2, 1]];
24+
call_user_func_array('array_multisort', $args);
25+
var_dump($args);
26+
unset($args);
27+
28+
$array = [3, 2, 1];
29+
call_user_func('array_multisort', $array);
30+
var_dump($array);
31+
unset($array);
32+
}
33+
34+
?>
35+
--EXPECT--
36+
array(1) {
37+
[0]=>
38+
array(3) {
39+
[0]=>
40+
int(3)
41+
[1]=>
42+
int(2)
43+
[2]=>
44+
int(1)
45+
}
46+
}
47+
array(3) {
48+
[0]=>
49+
int(3)
50+
[1]=>
51+
int(2)
52+
[2]=>
53+
int(1)
54+
}
55+
array(1) {
56+
[0]=>
57+
array(3) {
58+
[0]=>
59+
int(3)
60+
[1]=>
61+
int(2)
62+
[2]=>
63+
int(1)
64+
}
65+
}
66+
array(3) {
67+
[0]=>
68+
int(3)
69+
[1]=>
70+
int(2)
71+
[2]=>
72+
int(1)
73+
}

Zend/zend_inheritance.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,8 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
657657
int parent_num = OBJ_PROP_TO_NUM(parent_info->offset);
658658
int child_num = OBJ_PROP_TO_NUM(child_info->offset);
659659

660-
zval_ptr_dtor(&(ce->default_properties_table[parent_num]));
660+
/* Don't keep default properties in GC (thry may be freed by opcache) */
661+
zval_ptr_dtor_nogc(&(ce->default_properties_table[parent_num]));
661662
ce->default_properties_table[parent_num] = ce->default_properties_table[child_num];
662663
ZVAL_UNDEF(&ce->default_properties_table[child_num]);
663664
child_info->offset = parent_info->offset;

Zend/zend_vm_def.h

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4600,22 +4600,6 @@ ZEND_VM_C_LABEL(send_array):
46004600
ht = Z_ARRVAL_P(args);
46014601
zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht));
46024602

4603-
if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
4604-
int separate = 0;
4605-
4606-
/* check if any of arguments are going to be passed by reference */
4607-
for (arg_num = 0; arg_num < zend_hash_num_elements(ht); arg_num++) {
4608-
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + 1)) {
4609-
separate = 1;
4610-
break;
4611-
}
4612-
}
4613-
if (separate) {
4614-
zval_copy_ctor(args);
4615-
ht = Z_ARRVAL_P(args);
4616-
}
4617-
}
4618-
46194603
arg_num = 1;
46204604
param = ZEND_CALL_ARG(EX(call), 1);
46214605
ZEND_HASH_FOREACH_VAL(ht, arg) {
@@ -4641,21 +4625,15 @@ ZEND_VM_C_LABEL(send_array):
46414625

46424626
break;
46434627
}
4644-
4645-
ZVAL_NEW_REF(arg, arg);
46464628
}
4647-
Z_ADDREF_P(arg);
4648-
} else{
4629+
} else {
46494630
if (Z_ISREF_P(arg) &&
46504631
!(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
46514632
/* don't separate references for __call */
46524633
arg = Z_REFVAL_P(arg);
46534634
}
4654-
if (Z_OPT_REFCOUNTED_P(arg)) {
4655-
Z_ADDREF_P(arg);
4656-
}
46574635
}
4658-
ZVAL_COPY_VALUE(param, arg);
4636+
ZVAL_COPY(param, arg);
46594637
ZEND_CALL_NUM_ARGS(EX(call))++;
46604638
arg_num++;
46614639
param++;
@@ -4677,7 +4655,6 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
46774655

46784656
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
46794657
if (UNEXPECTED(!Z_ISREF_P(arg))) {
4680-
46814658
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
46824659

46834660
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
@@ -4700,21 +4677,15 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
47004677
FREE_OP1();
47014678
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
47024679
}
4703-
4704-
ZVAL_NEW_REF(arg, arg);
47054680
}
4706-
Z_ADDREF_P(arg);
47074681
} else {
47084682
if (Z_ISREF_P(arg) &&
47094683
!(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
47104684
/* don't separate references for __call */
47114685
arg = Z_REFVAL_P(arg);
47124686
}
4713-
if (Z_OPT_REFCOUNTED_P(arg)) {
4714-
Z_ADDREF_P(arg);
4715-
}
47164687
}
4717-
ZVAL_COPY_VALUE(param, arg);
4688+
ZVAL_COPY(param, arg);
47184689

47194690
FREE_OP1();
47204691
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();

Zend/zend_vm_execute.h

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,22 +1132,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O
11321132
ht = Z_ARRVAL_P(args);
11331133
zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht));
11341134

1135-
if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
1136-
int separate = 0;
1137-
1138-
/* check if any of arguments are going to be passed by reference */
1139-
for (arg_num = 0; arg_num < zend_hash_num_elements(ht); arg_num++) {
1140-
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + 1)) {
1141-
separate = 1;
1142-
break;
1143-
}
1144-
}
1145-
if (separate) {
1146-
zval_copy_ctor(args);
1147-
ht = Z_ARRVAL_P(args);
1148-
}
1149-
}
1150-
11511135
arg_num = 1;
11521136
param = ZEND_CALL_ARG(EX(call), 1);
11531137
ZEND_HASH_FOREACH_VAL(ht, arg) {
@@ -1173,21 +1157,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O
11731157

11741158
break;
11751159
}
1176-
1177-
ZVAL_NEW_REF(arg, arg);
11781160
}
1179-
Z_ADDREF_P(arg);
1180-
} else{
1161+
} else {
11811162
if (Z_ISREF_P(arg) &&
11821163
!(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
11831164
/* don't separate references for __call */
11841165
arg = Z_REFVAL_P(arg);
11851166
}
1186-
if (Z_OPT_REFCOUNTED_P(arg)) {
1187-
Z_ADDREF_P(arg);
1188-
}
11891167
}
1190-
ZVAL_COPY_VALUE(param, arg);
1168+
ZVAL_COPY(param, arg);
11911169
ZEND_CALL_NUM_ARGS(EX(call))++;
11921170
arg_num++;
11931171
param++;
@@ -15353,7 +15331,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN
1535315331

1535415332
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
1535515333
if (UNEXPECTED(!Z_ISREF_P(arg))) {
15356-
1535715334
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
1535815335

1535915336
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
@@ -15376,21 +15353,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN
1537615353
zval_ptr_dtor_nogc(free_op1);
1537715354
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1537815355
}
15379-
15380-
ZVAL_NEW_REF(arg, arg);
1538115356
}
15382-
Z_ADDREF_P(arg);
1538315357
} else {
1538415358
if (Z_ISREF_P(arg) &&
1538515359
!(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
1538615360
/* don't separate references for __call */
1538715361
arg = Z_REFVAL_P(arg);
1538815362
}
15389-
if (Z_OPT_REFCOUNTED_P(arg)) {
15390-
Z_ADDREF_P(arg);
15391-
}
1539215363
}
15393-
ZVAL_COPY_VALUE(param, arg);
15364+
ZVAL_COPY(param, arg);
1539415365

1539515366
zval_ptr_dtor_nogc(free_op1);
1539615367
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -28967,7 +28938,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND
2896728938

2896828939
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
2896928940
if (UNEXPECTED(!Z_ISREF_P(arg))) {
28970-
2897128941
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
2897228942

2897328943
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
@@ -28989,21 +28959,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND
2898928959

2899028960
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2899128961
}
28992-
28993-
ZVAL_NEW_REF(arg, arg);
2899428962
}
28995-
Z_ADDREF_P(arg);
2899628963
} else {
2899728964
if (Z_ISREF_P(arg) &&
2899828965
!(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
2899928966
/* don't separate references for __call */
2900028967
arg = Z_REFVAL_P(arg);
2900128968
}
29002-
if (Z_OPT_REFCOUNTED_P(arg)) {
29003-
Z_ADDREF_P(arg);
29004-
}
2900528969
}
29006-
ZVAL_COPY_VALUE(param, arg);
28970+
ZVAL_COPY(param, arg);
2900728971

2900828972
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2900928973
}

0 commit comments

Comments
 (0)