Evaluate arguments of new for classes without ctor

ML: http://markmail.org/message/4b3mk7jid64zvz34
This commit is contained in:
Nikita Popov 2016-03-12 16:00:04 +01:00
parent 24551ed6c8
commit 8e5b139732
15 changed files with 80 additions and 41 deletions

View File

@ -8,7 +8,7 @@ class MyClass {
$this->myRef = $value;
}
}
$myGlobal=new MyClass($myGlobal);
$myGlobal=new MyClass();
$myGlobal->myRef=&$myGlobal;
$myGlobal->myNonExistentProperty="ok\n";
echo $myGlobal;

View File

@ -0,0 +1,10 @@
--TEST--
Argument of new on class without constructor are evaluated
--FILE--
<?php
new stdClass(print 'a', print 'b');
?>
--EXPECT--
ab

View File

@ -3792,7 +3792,8 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
zend_compile_call_common(&ctor_result, args_ast, NULL);
zend_do_free(&ctor_result);
/* New jumps over ctor call if ctor does not exist */
/* We save the position of DO_FCALL for convenience in find_live_range().
* This info is not preserved for runtime. */
opline = &CG(active_op_array)->opcodes[opnum];
opline->op2.opline_num = get_next_op_number(CG(active_op_array));
}

View File

@ -673,7 +673,6 @@ ZEND_API int pass_two(zend_op_array *op_array)
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_NEW:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);

View File

@ -5073,12 +5073,13 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, JMP_ADDR, NUM)
ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, ANY, NUM)
{
USE_OPLINE
zval *result;
zend_function *constructor;
zend_class_entry *ce;
zend_execute_data *call;
SAVE_OPLINE();
if (OP1_TYPE == IS_CONST) {
@ -5107,21 +5108,30 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, JMP_ADDR, NUM)
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
if (constructor == NULL) {
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
* opcode is DO_FCALL in case EXT instructions are used. */
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}
/* Perform a dummy function call */
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
opline->extended_value, NULL, NULL);
} else {
/* We are not handling overloaded classes right now */
zend_execute_data *call = zend_vm_stack_push_call_frame(
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
constructor,
opline->extended_value,
ce,
Z_OBJ_P(result));
call->prev_execute_data = EX(call);
EX(call) = call;
Z_ADDREF_P(result);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
call->prev_execute_data = EX(call);
EX(call) = call;
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)

View File

@ -3756,6 +3756,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP
zval *result;
zend_function *constructor;
zend_class_entry *ce;
zend_execute_data *call;
SAVE_OPLINE();
if (IS_CONST == IS_CONST) {
@ -3784,21 +3785,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
if (constructor == NULL) {
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
* opcode is DO_FCALL in case EXT instructions are used. */
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}
/* Perform a dummy function call */
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
opline->extended_value, NULL, NULL);
} else {
/* We are not handling overloaded classes right now */
zend_execute_data *call = zend_vm_stack_push_call_frame(
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
constructor,
opline->extended_value,
ce,
Z_OBJ_P(result));
call->prev_execute_data = EX(call);
EX(call) = call;
Z_ADDREF_P(result);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
call->prev_execute_data = EX(call);
EX(call) = call;
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -16484,6 +16494,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCO
zval *result;
zend_function *constructor;
zend_class_entry *ce;
zend_execute_data *call;
SAVE_OPLINE();
if (IS_VAR == IS_CONST) {
@ -16512,21 +16523,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCO
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
if (constructor == NULL) {
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
* opcode is DO_FCALL in case EXT instructions are used. */
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}
/* Perform a dummy function call */
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
opline->extended_value, NULL, NULL);
} else {
/* We are not handling overloaded classes right now */
zend_execute_data *call = zend_vm_stack_push_call_frame(
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
constructor,
opline->extended_value,
ce,
Z_OBJ_P(result));
call->prev_execute_data = EX(call);
EX(call) = call;
Z_ADDREF_P(result);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
call->prev_execute_data = EX(call);
EX(call) = call;
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -26780,6 +26800,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_HANDLER(ZEND_O
zval *result;
zend_function *constructor;
zend_class_entry *ce;
zend_execute_data *call;
SAVE_OPLINE();
if (IS_UNUSED == IS_CONST) {
@ -26808,21 +26829,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_HANDLER(ZEND_O
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
if (constructor == NULL) {
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
* opcode is DO_FCALL in case EXT instructions are used. */
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}
/* Perform a dummy function call */
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
opline->extended_value, NULL, NULL);
} else {
/* We are not handling overloaded classes right now */
zend_execute_data *call = zend_vm_stack_push_call_frame(
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
constructor,
opline->extended_value,
ce,
Z_OBJ_P(result));
call->prev_execute_data = EX(call);
EX(call) = call;
Z_ADDREF_P(result);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
call->prev_execute_data = EX(call);
EX(call) = call;
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)

View File

@ -277,7 +277,7 @@ static uint32_t zend_vm_opcodes_flags[184] = {
0x00001003,
0x00001001,
0x00001001,
0x01002073,
0x01000073,
0x01000300,
0x00004005,
0x00186703,

View File

@ -846,7 +846,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
case ZEND_JMPNZ_EX:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_NEW:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_ASSERT_CHECK:

View File

@ -182,7 +182,6 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
case ZEND_JMPNZ_EX:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_NEW:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_ASSERT_CHECK:
@ -250,7 +249,6 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
case ZEND_JMPNZ_EX:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_NEW:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_ASSERT_CHECK:

View File

@ -80,7 +80,6 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
case ZEND_JMPNZ_EX:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_NEW:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_ASSERT_CHECK:
@ -123,7 +122,6 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
case ZEND_JMPNZ_EX:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_NEW:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_ASSERT_CHECK:

View File

@ -643,7 +643,6 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
case ZEND_FE_RESET_RW:
case ZEND_FE_FETCH_R:
case ZEND_FE_FETCH_RW:
case ZEND_NEW:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_ASSERT_CHECK:

View File

@ -363,7 +363,6 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
break;
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_NEW:
BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes);
BB_START(i + 1);
break;
@ -496,7 +495,6 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
break;
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_NEW:
record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]);
record_successor(blocks, j, 1, j + 1);
break;

View File

@ -404,7 +404,6 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_NEW:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_ASSERT_CHECK:
@ -982,7 +981,6 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_NEW:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_ASSERT_CHECK:

View File

@ -541,7 +541,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_NEW:
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_ASSERT_CHECK:

View File

@ -34,7 +34,7 @@ prompt> [Context %s (11 ops)]
L1-19 {main}() %s - %s + 11 ops
L4 #0 NOP
L14 #1 NOP
L18 #2 NEW "Foo\\Bar" J4 @1
L18 #2 NEW "Foo\\Bar" @1
L18 #3 DO_FCALL
L18 #4 INIT_METHOD_CALL @1 "Foo"
L18 #5 SEND_VAL_EX "test" 1