Skip to content

Commit 8e5b139

Browse files
committed
Evaluate arguments of new for classes without ctor
ML: http://markmail.org/message/4b3mk7jid64zvz34
1 parent 24551ed commit 8e5b139

15 files changed

Lines changed: 80 additions & 41 deletions

Zend/tests/bug52879.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class MyClass {
88
$this->myRef = $value;
99
}
1010
}
11-
$myGlobal=new MyClass($myGlobal);
11+
$myGlobal=new MyClass();
1212
$myGlobal->myRef=&$myGlobal;
1313
$myGlobal->myNonExistentProperty="ok\n";
1414
echo $myGlobal;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Argument of new on class without constructor are evaluated
3+
--FILE--
4+
<?php
5+
6+
new stdClass(print 'a', print 'b');
7+
8+
?>
9+
--EXPECT--
10+
ab

Zend/zend_compile.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3792,7 +3792,8 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
37923792
zend_compile_call_common(&ctor_result, args_ast, NULL);
37933793
zend_do_free(&ctor_result);
37943794

3795-
/* New jumps over ctor call if ctor does not exist */
3795+
/* We save the position of DO_FCALL for convenience in find_live_range().
3796+
* This info is not preserved for runtime. */
37963797
opline = &CG(active_op_array)->opcodes[opnum];
37973798
opline->op2.opline_num = get_next_op_number(CG(active_op_array));
37983799
}

Zend/zend_opcode.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,6 @@ ZEND_API int pass_two(zend_op_array *op_array)
673673
case ZEND_JMPNZ_EX:
674674
case ZEND_JMP_SET:
675675
case ZEND_COALESCE:
676-
case ZEND_NEW:
677676
case ZEND_FE_RESET_R:
678677
case ZEND_FE_RESET_RW:
679678
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);

Zend/zend_vm_def.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5073,12 +5073,13 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
50735073
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
50745074
}
50755075

5076-
ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, JMP_ADDR, NUM)
5076+
ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, ANY, NUM)
50775077
{
50785078
USE_OPLINE
50795079
zval *result;
50805080
zend_function *constructor;
50815081
zend_class_entry *ce;
5082+
zend_execute_data *call;
50825083

50835084
SAVE_OPLINE();
50845085
if (OP1_TYPE == IS_CONST) {
@@ -5107,21 +5108,30 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, JMP_ADDR, NUM)
51075108

51085109
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
51095110
if (constructor == NULL) {
5110-
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
5111+
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
5112+
* opcode is DO_FCALL in case EXT instructions are used. */
5113+
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
5114+
ZEND_VM_NEXT_OPCODE_EX(1, 2);
5115+
}
5116+
5117+
/* Perform a dummy function call */
5118+
call = zend_vm_stack_push_call_frame(
5119+
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
5120+
opline->extended_value, NULL, NULL);
51115121
} else {
51125122
/* We are not handling overloaded classes right now */
5113-
zend_execute_data *call = zend_vm_stack_push_call_frame(
5123+
call = zend_vm_stack_push_call_frame(
51145124
ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
51155125
constructor,
51165126
opline->extended_value,
51175127
ce,
51185128
Z_OBJ_P(result));
5119-
call->prev_execute_data = EX(call);
5120-
EX(call) = call;
51215129
Z_ADDREF_P(result);
5122-
5123-
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
51245130
}
5131+
5132+
call->prev_execute_data = EX(call);
5133+
EX(call) = call;
5134+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
51255135
}
51265136

51275137
ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)

Zend/zend_vm_execute.h

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3756,6 +3756,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP
37563756
zval *result;
37573757
zend_function *constructor;
37583758
zend_class_entry *ce;
3759+
zend_execute_data *call;
37593760

37603761
SAVE_OPLINE();
37613762
if (IS_CONST == IS_CONST) {
@@ -3784,21 +3785,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP
37843785

37853786
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
37863787
if (constructor == NULL) {
3787-
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
3788+
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
3789+
* opcode is DO_FCALL in case EXT instructions are used. */
3790+
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
3791+
ZEND_VM_NEXT_OPCODE_EX(1, 2);
3792+
}
3793+
3794+
/* Perform a dummy function call */
3795+
call = zend_vm_stack_push_call_frame(
3796+
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
3797+
opline->extended_value, NULL, NULL);
37883798
} else {
37893799
/* We are not handling overloaded classes right now */
3790-
zend_execute_data *call = zend_vm_stack_push_call_frame(
3800+
call = zend_vm_stack_push_call_frame(
37913801
ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
37923802
constructor,
37933803
opline->extended_value,
37943804
ce,
37953805
Z_OBJ_P(result));
3796-
call->prev_execute_data = EX(call);
3797-
EX(call) = call;
37983806
Z_ADDREF_P(result);
3799-
3800-
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
38013807
}
3808+
3809+
call->prev_execute_data = EX(call);
3810+
EX(call) = call;
3811+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
38023812
}
38033813

38043814
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
1648416494
zval *result;
1648516495
zend_function *constructor;
1648616496
zend_class_entry *ce;
16497+
zend_execute_data *call;
1648716498

1648816499
SAVE_OPLINE();
1648916500
if (IS_VAR == IS_CONST) {
@@ -16512,21 +16523,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCO
1651216523

1651316524
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
1651416525
if (constructor == NULL) {
16515-
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
16526+
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
16527+
* opcode is DO_FCALL in case EXT instructions are used. */
16528+
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
16529+
ZEND_VM_NEXT_OPCODE_EX(1, 2);
16530+
}
16531+
16532+
/* Perform a dummy function call */
16533+
call = zend_vm_stack_push_call_frame(
16534+
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
16535+
opline->extended_value, NULL, NULL);
1651616536
} else {
1651716537
/* We are not handling overloaded classes right now */
16518-
zend_execute_data *call = zend_vm_stack_push_call_frame(
16538+
call = zend_vm_stack_push_call_frame(
1651916539
ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
1652016540
constructor,
1652116541
opline->extended_value,
1652216542
ce,
1652316543
Z_OBJ_P(result));
16524-
call->prev_execute_data = EX(call);
16525-
EX(call) = call;
1652616544
Z_ADDREF_P(result);
16527-
16528-
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1652916545
}
16546+
16547+
call->prev_execute_data = EX(call);
16548+
EX(call) = call;
16549+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1653016550
}
1653116551

1653216552
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
2678026800
zval *result;
2678126801
zend_function *constructor;
2678226802
zend_class_entry *ce;
26803+
zend_execute_data *call;
2678326804

2678426805
SAVE_OPLINE();
2678526806
if (IS_UNUSED == IS_CONST) {
@@ -26808,21 +26829,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_HANDLER(ZEND_O
2680826829

2680926830
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
2681026831
if (constructor == NULL) {
26811-
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
26832+
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
26833+
* opcode is DO_FCALL in case EXT instructions are used. */
26834+
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
26835+
ZEND_VM_NEXT_OPCODE_EX(1, 2);
26836+
}
26837+
26838+
/* Perform a dummy function call */
26839+
call = zend_vm_stack_push_call_frame(
26840+
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
26841+
opline->extended_value, NULL, NULL);
2681226842
} else {
2681326843
/* We are not handling overloaded classes right now */
26814-
zend_execute_data *call = zend_vm_stack_push_call_frame(
26844+
call = zend_vm_stack_push_call_frame(
2681526845
ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
2681626846
constructor,
2681726847
opline->extended_value,
2681826848
ce,
2681926849
Z_OBJ_P(result));
26820-
call->prev_execute_data = EX(call);
26821-
EX(call) = call;
2682226850
Z_ADDREF_P(result);
26823-
26824-
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2682526851
}
26852+
26853+
call->prev_execute_data = EX(call);
26854+
EX(call) = call;
26855+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2682626856
}
2682726857

2682826858
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)

Zend/zend_vm_opcodes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ static uint32_t zend_vm_opcodes_flags[184] = {
277277
0x00001003,
278278
0x00001001,
279279
0x00001001,
280-
0x01002073,
280+
0x01000073,
281281
0x01000300,
282282
0x00004005,
283283
0x00186703,

ext/opcache/Optimizer/block_pass.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
846846
case ZEND_JMPNZ_EX:
847847
case ZEND_FE_RESET_R:
848848
case ZEND_FE_RESET_RW:
849-
case ZEND_NEW:
850849
case ZEND_JMP_SET:
851850
case ZEND_COALESCE:
852851
case ZEND_ASSERT_CHECK:

ext/opcache/Optimizer/dfa_pass.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
182182
case ZEND_JMPNZ_EX:
183183
case ZEND_FE_RESET_R:
184184
case ZEND_FE_RESET_RW:
185-
case ZEND_NEW:
186185
case ZEND_JMP_SET:
187186
case ZEND_COALESCE:
188187
case ZEND_ASSERT_CHECK:
@@ -250,7 +249,6 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
250249
case ZEND_JMPNZ_EX:
251250
case ZEND_FE_RESET_R:
252251
case ZEND_FE_RESET_RW:
253-
case ZEND_NEW:
254252
case ZEND_JMP_SET:
255253
case ZEND_COALESCE:
256254
case ZEND_ASSERT_CHECK:

ext/opcache/Optimizer/nop_removal.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
8080
case ZEND_JMPNZ_EX:
8181
case ZEND_FE_RESET_R:
8282
case ZEND_FE_RESET_RW:
83-
case ZEND_NEW:
8483
case ZEND_JMP_SET:
8584
case ZEND_COALESCE:
8685
case ZEND_ASSERT_CHECK:
@@ -123,7 +122,6 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
123122
case ZEND_JMPNZ_EX:
124123
case ZEND_FE_RESET_R:
125124
case ZEND_FE_RESET_RW:
126-
case ZEND_NEW:
127125
case ZEND_JMP_SET:
128126
case ZEND_COALESCE:
129127
case ZEND_ASSERT_CHECK:

0 commit comments

Comments
 (0)