Skip to content

Commit

Permalink
Fixed list() behavior inconsistency (string handling is disabled for …
Browse files Browse the repository at this point in the history
…all cases, ArrayAccess objects handling is enabled for all cases, ZEND_FETCH_DIM_TMP_VAR opcode is renamed into ZEND_FETCH_LIST, ZEND_FETCH_ADD_LOCK flag is removed).
  • Loading branch information
dstogov committed Oct 5, 2014
1 parent 429e1b4 commit 7c7b918
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 114 deletions.
4 changes: 0 additions & 4 deletions Zend/tests/bug39304.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,5 @@ echo "I am alive";
?>
--EXPECTF--
Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d

Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d

Notice: Uninitialized string offset: 1 in %sbug39304.php on line %d
I am alive

8 changes: 2 additions & 6 deletions Zend/tests/bug39304_2_4.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,5 @@ Bug #39304 (Segmentation fault with list unpacking of string offset)
?>
--EXPECTF--
Notice: Uninitialized string offset: 0 in %sbug39304_2_4.php on line %d

Notice: Uninitialized string offset: 0 in %sbug39304_2_4.php on line %d

Notice: Uninitialized string offset: 1 in %sbug39304_2_4.php on line %d
string(0) ""
string(0) ""
NULL
NULL
8 changes: 2 additions & 6 deletions Zend/tests/foreach_list_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,5 @@ foreach($array as list(, $a)) {
int(1)
int(3)
string(1) "b"

Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d
string(0) ""

Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d
string(0) ""
NULL
NULL
6 changes: 3 additions & 3 deletions Zend/tests/list_005.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ var_dump($a, $b, $c);

?>
--EXPECTF--
string(1) "f"
string(1) "o"
string(1) "o"
NULL
NULL
NULL
----
NULL
NULL
Expand Down
5 changes: 2 additions & 3 deletions Zend/tests/list_007.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ list($x, $y) = function() { };
var_dump($x, $y);

?>
--EXPECT--
NULL
NULL
--EXPECTF--
Fatal error: Cannot use object of type Closure as array in %slist_007.php on line 3
37 changes: 12 additions & 25 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,15 +515,17 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
}
} else {
while (opline>CG(active_op_array)->opcodes) {
if (opline->opcode == ZEND_FETCH_DIM_R
&& opline->op1_type == IS_VAR
&& opline->op1.var == op1->u.op.var) {
/* This should the end of a list() construct
* Mark its result as unused
*/
opline->extended_value = ZEND_FETCH_STANDARD;
break;
} else if (opline->result_type==IS_VAR
if (opline->opcode == ZEND_FETCH_LIST &&
opline->op1_type == IS_VAR &&
opline->op1.var == op1->u.op.var) {
opline = get_next_op(CG(active_op_array) TSRMLS_CC);

opline->opcode = ZEND_FREE;
SET_NODE(opline->op1, op1);
SET_UNUSED(opline->op2);
return;
}
if (opline->result_type==IS_VAR
&& opline->result.var == op1->u.op.var) {
if (opline->opcode == ZEND_NEW) {
opline->result_type |= EXT_TYPE_UNUSED;
Expand Down Expand Up @@ -2174,20 +2176,6 @@ void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type TSRMLS
}
/* }}} */

static inline zend_uchar get_list_fetch_opcode(zend_uchar op_type) /* {{{ */
{
switch (op_type) {
case IS_VAR:
case IS_CV:
return ZEND_FETCH_DIM_R;
case IS_TMP_VAR:
case IS_CONST:
return ZEND_FETCH_DIM_TMP_VAR;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
/* }}} */

static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node TSRMLS_DC) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(ast);
Expand All @@ -2214,8 +2202,7 @@ static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_n
}

opline = zend_emit_op(&fetch_result,
get_list_fetch_opcode(expr_node->op_type), expr_node, &dim_node TSRMLS_CC);
opline->extended_value |= ZEND_FETCH_ADD_LOCK;
ZEND_FETCH_LIST, expr_node, &dim_node TSRMLS_CC);

zend_emit_assign_znode(var_ast, &fetch_result TSRMLS_CC);
}
Expand Down
1 change: 0 additions & 1 deletion Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,6 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
#define ZEND_FETCH_TYPE_MASK 0x70000000

#define ZEND_FETCH_STANDARD 0x00000000
#define ZEND_FETCH_ADD_LOCK 0x08000000
#define ZEND_FETCH_MAKE_REF 0x04000000

#define ZEND_ISSET 0x02000000
Expand Down
27 changes: 18 additions & 9 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -1209,9 +1209,7 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
container = GET_OP1_ZVAL_PTR(BP_VAR_R);
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE != IS_VAR || !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
FREE_OP1();
}
FREE_OP1();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
Expand Down Expand Up @@ -1506,23 +1504,34 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}

ZEND_VM_HANDLER(98, ZEND_FETCH_DIM_TMP_VAR, CONST|TMP, CONST)
ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMP|VAR|CV, CONST)
{
USE_OPLINE
zend_free_op free_op1;
zval *container;

SAVE_OPLINE();
container = GET_OP1_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);

if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
ZVAL_NULL(EX_VAR(opline->result.var));
} else {
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
zend_free_op free_op2;
zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);

ZVAL_COPY(EX_VAR(opline->result.var), value);
FREE_OP2();
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
zval *result = EX_VAR(opline->result.var);
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), BP_VAR_R, result TSRMLS_CC);

if (retval) {
if (result != retval) {
ZVAL_COPY(result, retval);
}
} else {
ZVAL_NULL(result);
}
} else {
ZVAL_NULL(EX_VAR(opline->result.var));
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
Expand Down
Loading

0 comments on commit 7c7b918

Please sign in to comment.