Skip to content

Commit 46488c8

Browse files
committed
Fixed parameter passing incompatibilities.
Now it is possible to call array_pop(explode("&","1&2&3")) again.
1 parent 1165842 commit 46488c8

File tree

3 files changed

+67
-40
lines changed

3 files changed

+67
-40
lines changed

Zend/tests/bug33257.phpt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,10 @@ array_splice(X::getArr(), 1, 1);
1414
print_r(X::getArr());
1515
?>
1616
--EXPECTF--
17-
Fatal error: Only variables can be passed by reference in %sbug33257.php on line 10
17+
Strict Standards: Only variables should be passed by reference in %sbug33257.php on line 10
18+
Array
19+
(
20+
[0] => a
21+
[1] => b
22+
[2] => c
23+
)

Zend/zend_vm_def.h

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,30 +2185,37 @@ ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
21852185
ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
21862186
{
21872187
zend_op *opline = EX(opline);
2188+
zend_free_op free_op1;
2189+
zval *varptr;
2190+
21882191
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
21892192
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
21902193
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
21912194
}
21922195
} else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
21932196
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
21942197
}
2195-
if ((opline->extended_value & ZEND_ARG_SEND_FUNCTION) &&
2196-
!EX_T(opline->op1.u.var).var.fcall_returned_reference) {
2197-
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
2198+
2199+
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
2200+
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
2201+
EX_T(opline->op1.u.var).var.fcall_returned_reference) &&
2202+
varptr != &EG(uninitialized_zval) &&
2203+
(PZVAL_IS_REF(varptr) || varptr->refcount == 1)) {
2204+
varptr->is_ref = 1;
2205+
varptr->refcount++;
2206+
zend_ptr_stack_push(&EG(argument_stack), varptr);
21982207
} else {
2199-
zval *varptr;
2200-
zend_free_op free_op1;
2201-
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
2208+
zval *valptr;
22022209

2203-
if (varptr != &EG(uninitialized_zval) && (PZVAL_IS_REF(varptr) || varptr->refcount == 1)) {
2204-
varptr->is_ref = 1;
2205-
varptr->refcount++;
2206-
zend_ptr_stack_push(&EG(argument_stack), varptr);
2207-
FREE_OP1_IF_VAR();
2208-
ZEND_VM_NEXT_OPCODE();
2210+
zend_error(E_STRICT, "Only variables should be passed by reference");
2211+
ALLOC_ZVAL(valptr);
2212+
INIT_PZVAL_COPY(valptr, varptr);
2213+
if (!IS_OP1_TMP_FREE()) {
2214+
zval_copy_ctor(valptr);
22092215
}
2210-
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
2216+
zend_ptr_stack_push(&EG(argument_stack), valptr);
22112217
}
2218+
FREE_OP1_IF_VAR();
22122219
ZEND_VM_NEXT_OPCODE();
22132220
}
22142221

Zend/zend_vm_execute.h

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7093,30 +7093,37 @@ static int zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS)
70937093
static int ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
70947094
{
70957095
zend_op *opline = EX(opline);
7096+
zend_free_op free_op1;
7097+
zval *varptr;
7098+
70967099
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
70977100
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
70987101
return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
70997102
}
71007103
} else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
71017104
return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
71027105
}
7103-
if ((opline->extended_value & ZEND_ARG_SEND_FUNCTION) &&
7104-
!EX_T(opline->op1.u.var).var.fcall_returned_reference) {
7105-
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
7106+
7107+
varptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
7108+
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
7109+
EX_T(opline->op1.u.var).var.fcall_returned_reference) &&
7110+
varptr != &EG(uninitialized_zval) &&
7111+
(PZVAL_IS_REF(varptr) || varptr->refcount == 1)) {
7112+
varptr->is_ref = 1;
7113+
varptr->refcount++;
7114+
zend_ptr_stack_push(&EG(argument_stack), varptr);
71067115
} else {
7107-
zval *varptr;
7108-
zend_free_op free_op1;
7109-
varptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
7116+
zval *valptr;
71107117

7111-
if (varptr != &EG(uninitialized_zval) && (PZVAL_IS_REF(varptr) || varptr->refcount == 1)) {
7112-
varptr->is_ref = 1;
7113-
varptr->refcount++;
7114-
zend_ptr_stack_push(&EG(argument_stack), varptr);
7115-
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
7116-
ZEND_VM_NEXT_OPCODE();
7118+
zend_error(E_STRICT, "Only variables should be passed by reference");
7119+
ALLOC_ZVAL(valptr);
7120+
INIT_PZVAL_COPY(valptr, varptr);
7121+
if (!0) {
7122+
zval_copy_ctor(valptr);
71177123
}
7118-
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
7124+
zend_ptr_stack_push(&EG(argument_stack), valptr);
71197125
}
7126+
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
71207127
ZEND_VM_NEXT_OPCODE();
71217128
}
71227129

@@ -19258,30 +19265,37 @@ static int zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS)
1925819265
static int ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
1925919266
{
1926019267
zend_op *opline = EX(opline);
19268+
19269+
zval *varptr;
19270+
1926119271
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
1926219272
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
1926319273
return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
1926419274
}
1926519275
} else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
1926619276
return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
1926719277
}
19268-
if ((opline->extended_value & ZEND_ARG_SEND_FUNCTION) &&
19269-
!EX_T(opline->op1.u.var).var.fcall_returned_reference) {
19270-
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
19278+
19279+
varptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
19280+
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
19281+
EX_T(opline->op1.u.var).var.fcall_returned_reference) &&
19282+
varptr != &EG(uninitialized_zval) &&
19283+
(PZVAL_IS_REF(varptr) || varptr->refcount == 1)) {
19284+
varptr->is_ref = 1;
19285+
varptr->refcount++;
19286+
zend_ptr_stack_push(&EG(argument_stack), varptr);
1927119287
} else {
19272-
zval *varptr;
19273-
19274-
varptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
19275-
19276-
if (varptr != &EG(uninitialized_zval) && (PZVAL_IS_REF(varptr) || varptr->refcount == 1)) {
19277-
varptr->is_ref = 1;
19278-
varptr->refcount++;
19279-
zend_ptr_stack_push(&EG(argument_stack), varptr);
19288+
zval *valptr;
1928019289

19281-
ZEND_VM_NEXT_OPCODE();
19290+
zend_error(E_STRICT, "Only variables should be passed by reference");
19291+
ALLOC_ZVAL(valptr);
19292+
INIT_PZVAL_COPY(valptr, varptr);
19293+
if (!0) {
19294+
zval_copy_ctor(valptr);
1928219295
}
19283-
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
19296+
zend_ptr_stack_push(&EG(argument_stack), valptr);
1928419297
}
19298+
1928519299
ZEND_VM_NEXT_OPCODE();
1928619300
}
1928719301

0 commit comments

Comments
 (0)