Skip to content

Commit

Permalink
Properly handle FUNC_ARG fetches
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic committed Mar 3, 2013
1 parent 31705dd commit 6f5483f
Show file tree
Hide file tree
Showing 4 changed files with 956 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1350,7 +1350,7 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS
opline->op1_type = IS_CV;
opline->op1.var = CG(active_op_array)->this_var;
}
if ((type != BP_VAR_R && type != BP_VAR_IS) && (opline->op1_type == IS_TMP_VAR || opline->op1_type == IS_CONST) && opline->opcode != ZEND_FETCH_W) {
if ((type != BP_VAR_R && type != BP_VAR_IS && type != BP_VAR_FUNC_ARG) && (opline->op1_type == IS_TMP_VAR || opline->op1_type == IS_CONST) && opline->opcode != ZEND_FETCH_W) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use temporary expression in write context");
}
switch (type) {
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_language_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,7 @@ variable:
object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties
{ zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = $1.EA | ($7.EA ? $7.EA : $6.EA); }
| base_variable_with_function_calls { $$ = $1; }
| parenthesis_expr { zend_do_push_object(&$1 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
| parenthesis_expr { $1.EA = 0; zend_do_push_object(&$1 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); }
;

Expand Down
25 changes: 20 additions & 5 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -1263,7 +1263,7 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}

ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
Expand All @@ -1272,10 +1272,15 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
SAVE_OPLINE();

if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
if (OP1_TYPE == IS_TMP_VAR || OP1_TYPE == IS_CONST) {
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
}

container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}

zend_fetch_dimension_address(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_W TSRMLS_CC);
if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
Expand All @@ -1284,11 +1289,17 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
if (OP2_TYPE == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);

if (OP2_TYPE == IS_TMP_VAR || OP2_TYPE == IS_CONST) {
zval *container = GET_OP1_ZVAL_PTR(BP_VAR_R);
zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
} else {
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
}
}
FREE_OP2();
FREE_OP1_VAR_PTR();
FREE_OP1();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
Expand Down Expand Up @@ -1504,7 +1515,7 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}

ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE

Expand All @@ -1514,6 +1525,10 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zval *property;
zval **container;

if (OP1_TYPE == IS_TMP_VAR || OP1_TYPE == IS_CONST) {
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
}

SAVE_OPLINE();
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
Expand Down

0 comments on commit 6f5483f

Please sign in to comment.