]> granicus.if.org Git - php/commitdiff
Evaluate arguments of new for classes without ctor
authorNikita Popov <nikic@php.net>
Sat, 12 Mar 2016 15:00:04 +0000 (16:00 +0100)
committerNikita Popov <nikic@php.net>
Fri, 25 Mar 2016 18:11:37 +0000 (19:11 +0100)
ML: http://markmail.org/message/4b3mk7jid64zvz34

15 files changed:
Zend/tests/bug52879.phpt
Zend/tests/new_args_without_ctor.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.c
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/dfa_pass.c
ext/opcache/Optimizer/nop_removal.c
ext/opcache/Optimizer/pass1_5.c
ext/opcache/Optimizer/zend_cfg.c
ext/opcache/zend_file_cache.c
ext/opcache/zend_persist.c
sapi/phpdbg/tests/print_001.phpt

index 0193be4b45e5974dd227b3f946ae9dd38d671fb6..6c3232f32dfc05e677c5a1e15414a8d3d4761275 100644 (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;
diff --git a/Zend/tests/new_args_without_ctor.phpt b/Zend/tests/new_args_without_ctor.phpt
new file mode 100644 (file)
index 0000000..9145689
--- /dev/null
@@ -0,0 +1,10 @@
+--TEST--
+Argument of new on class without constructor are evaluated
+--FILE--
+<?php
+
+new stdClass(print 'a', print 'b');
+
+?>
+--EXPECT--
+ab
index 0b871ed52a25a4de3fe60e87b77c25a15085420f..521cd08f36faca25a3afd678ac9ba3ddfacfcc68 100644 (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));
 }
index ab67a88272102975195df33a78d4d24b72221ea5..4800939b5f7306d988e0ef74b592638627f12844 100644 (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);
index e2ee420f89e5dd9049a7ae11a0320f75a496c574..9539b6e2ed336524dc5c73ccc2dc514759ce22f0 100644 (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)
index 612feb9e9c8f9ceddaf567957254a16c28267370..4eee6dd3eaec522543fe46e41ecd5b000dc35c94 100644 (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)
index ac5f0d6a32eeee981982ac59ba1b2660a72cde8b..d4c76ad2657a109dceea069d0c7fa0abcdfa64d5 100644 (file)
@@ -277,7 +277,7 @@ static uint32_t zend_vm_opcodes_flags[184] = {
        0x00001003,
        0x00001001,
        0x00001001,
-       0x01002073,
+       0x01000073,
        0x01000300,
        0x00004005,
        0x00186703,
index 159620c6179adfb3419b19ee31203bd9e3be46ad..52a440fba07368a63c4967aeefd4c5615857c904 100644 (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:
index 12a83f0d44fbc5e8aeaea68badeeba3c9b520525..74edad6361145430d11f3db7defe72bf8ecd0f88 100644 (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:
index aa04f6bc202f48c6a4870ac4f2be6cc0d02f7038..3ebbdad8cf4eb4c4f7225eaa89a4a3653da97f1d 100644 (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:
index 5809d247ec4b2e9a646a6deebda7928f726b49ce..ae31504f4c08053a62a4fd4ccac8c132af1d23ac 100644 (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:
index f0127d5ed0ad5de7d45bf5f086e292093f8ee79d..69a77f3b717042ddbd02af30efa3945558f124ec 100644 (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;
index dc4cb5f747af8e3fbfa416f47f676fdc0a334547..2fe5b61384c7c963fd1523360737b499e82eeb5a 100644 (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:
index 48fefd8918179980e29b4591ecdb1dc7968d5c24..aa3b8e82f3903f3d61a4d3689e32274bb6408b10 100644 (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:
index a4f300572a27615188e6856df55889eb0337f555..1f7a5ac0b94043accebb5efb12af67e1c0f7f9ca 100644 (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