Analyse Case 01

 PHP Source Code

<?php
class A
{
        private function foo()
        {
                echo 'A foo()' . PHP_EOL;
        }

        public function test()
        {
                $this->foo();
        }
}

class C extends A
{
        public function foo()
        {
                echo 'C foo()' . PHP_EOL;
        }
}

$c = new C();
$c->test();

 

opcode

Finding entry points
Branch analysis from position: 0
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  (null)
number of ops:  9
compiled vars:  !0 = $c
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   NOP                                                      
  15     1        NOP                                                      
         2        NOP                                                      
  23     3        NEW                                              $4      :-4
         4        DO_FCALL                                      0          
         5        ASSIGN                                                   !0, $4
  24     6        INIT_METHOD_CALL                                         !0, 'test'
         7        DO_FCALL                                      0          
  25     8      > RETURN                                                   1

Class A:
Function foo:
Finding entry points
Branch analysis from position: 0
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  foo
number of ops:  2
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   6     0  E >   ECHO                                                     'A+foo%28%29%0A'
   7     1      > RETURN                                                   null

End of function foo

Function test:
Finding entry points
Branch analysis from position: 0
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  test
number of ops:  3
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  11     0  E >   INIT_METHOD_CALL                                         'foo'
         1        DO_FCALL                                      0          
  12     2      > RETURN                                                   null

End of function test

End of class A.

Class C:
Function foo:
Finding entry points
Branch analysis from position: 0
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  foo
number of ops:  2
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  19     0  E >   ECHO                                                     'C+foo%28%29%0A'
  20     1      > RETURN                                                   null

End of function foo

Function test:
Finding entry points
Branch analysis from position: 0
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  test
number of ops:  3
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  11     0  E >   INIT_METHOD_CALL                                         'foo'
         1        DO_FCALL                                      0          
  12     2      > RETURN                                                   null

End of function test

End of class C.
Finding entry points
Branch analysis from position: 0
Add 0
Add 1
Add 2
Add 3
Add 4
Add 5
Add 6
Add 7
Add 8
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  (null)
number of ops:  9
compiled vars:  !0 = $c
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   NOP                                                      
  15     1        NOP                                                      
         2        NOP                                                      
  23     3        NEW                                               RES[  IS_VAR $4 ]       OP1[ :-4 ]
         4        DO_FCALL                                      0   RES[  ]         OP1[  IS_UNUSED  ]
         5        ASSIGN                                            RES[  ]         OP1[  IS_CV !0 ] OP2[ ,  IS_VAR $4 ]
  24     6        INIT_METHOD_CALL                                  RES[  IS_UNUSED  ]         OP1[  IS_CV !0 ] OP2[ ,  IS_CONST (4) 'test' ]
         7        DO_FCALL                                      0   RES[  ]         OP1[  IS_UNUSED  ]
  25     8      > RETURN                                                    OP1[  IS_CONST (6) 1 ]

branch: #  0; line:     2-   25; sop:     0; eop:     8; out1:  -2
path #1: 0, 
Class A:
Function foo:
Finding entry points
Branch analysis from position: 0
Add 0
Add 1
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  foo
number of ops:  2
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   6     0  E >   ECHO                                                      OP1[  IS_CONST (0) 'A+foo%28%29%0A' ]
   7     1      > RETURN                                                    OP1[  IS_CONST (1) null ]

branch: #  0; line:     6-    7; sop:     0; eop:     1; out1:  -2
path #1: 0, 
End of function foo

Function test:
Finding entry points
Branch analysis from position: 0
Add 0
Add 1
Add 2
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  test
number of ops:  3
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  11     0  E >   INIT_METHOD_CALL                                  RES[  IS_UNUSED  ]         OP1[  IS_UNUSED  ] OP2[  IS_CONST (0) 'foo' ]
         1        DO_FCALL                                      0   RES[  ]         OP1[  IS_UNUSED  ]
  12     2      > RETURN                                                    OP1[  IS_CONST (2) null ]

branch: #  0; line:    11-   12; sop:     0; eop:     2; out1:  -2
path #1: 0, 
End of function test

End of class A.

Class C:
Function foo:
Finding entry points
Branch analysis from position: 0
Add 0
Add 1
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  foo
number of ops:  2
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  19     0  E >   ECHO                                                      OP1[  IS_CONST (0) 'C+foo%28%29%0A' ]
  20     1      > RETURN                                                    OP1[  IS_CONST (1) null ]

branch: #  0; line:    19-   20; sop:     0; eop:     1; out1:  -2
path #1: 0, 
End of function foo

Function test:
Finding entry points
Branch analysis from position: 0
Add 0
Add 1
Add 2
Jump found. (Code = 62) Position 1 = -2
filename:       /home/minsec/php_demo/a.php
function name:  test
number of ops:  3
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  11     0  E >   INIT_METHOD_CALL                                  RES[  IS_UNUSED  ]         OP1[  IS_UNUSED  ] OP2[  IS_CONST (0) 'foo' ]
         1        DO_FCALL                                      0   RES[  ]         OP1[  IS_UNUSED  ]
  12     2      > RETURN                                                    OP1[  IS_CONST (2) null ]

branch: #  0; line:    11-   12; sop:     0; eop:     2; out1:  -2
path #1: 0, 
End of function test

End of class C.

A foo()
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
	USE_OPLINE
	zval *function_name;

	zval *object;
	zend_function *fbc;
	zend_class_entry *called_scope;
	zend_object *obj;
	zend_execute_data *call;
	uint32_t call_info;

	SAVE_OPLINE();

	object = _get_zval_ptr_cv_undef(opline->op1.var EXECUTE_DATA_CC);

	if (IS_CV == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
		ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
	}

	function_name = EX_CONSTANT(opline->op2);

	if (IS_CONST != IS_CONST &&
	    UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
		do {
			if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) {
				function_name = Z_REFVAL_P(function_name);
				if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
					break;
				}
			} else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
				GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
				if (UNEXPECTED(EG(exception) != NULL)) {

					HANDLE_EXCEPTION();
				}
			}
			zend_throw_error(NULL, "Method name must be a string");


			HANDLE_EXCEPTION();
		} while (0);
	}

	if (IS_CV != IS_UNUSED) {
		do {
			if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
				if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
					object = Z_REFVAL_P(object);
					if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
						break;
					}
				}
				if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
					object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
					if (UNEXPECTED(EG(exception) != NULL)) {

						HANDLE_EXCEPTION();
					}
				}
				zend_throw_error(NULL, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));


				HANDLE_EXCEPTION();
			}
		} while (0);
	}

	obj = Z_OBJ_P(object);
	called_scope = obj->ce;

	if (IS_CONST == IS_CONST &&
	    EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(function_name)) == called_scope)) {
	    fbc = CACHED_PTR(Z_CACHE_SLOT_P(function_name) + sizeof(void*));
	} else {
	    zend_object *orig_obj = obj;

		if (UNEXPECTED(obj->handlers->get_method == NULL)) {
			zend_throw_error(NULL, "Object does not support method calls");


			HANDLE_EXCEPTION();
		}

		/* First, locate the function. */
		fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
		if (UNEXPECTED(fbc == NULL)) {
			if (EXPECTED(!EG(exception))) {
				zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(obj->ce->name), Z_STRVAL_P(function_name));
			}


			HANDLE_EXCEPTION();
		}
		if (IS_CONST == IS_CONST &&
		    EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
		    EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
		    EXPECTED(obj == orig_obj)) {
			CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
		}
		if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
			init_func_run_time_cache(&fbc->op_array);
		}
	}

	call_info = ZEND_CALL_NESTED_FUNCTION;
	if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
		obj = NULL;
	} else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
		/* CV may be changed indirectly (e.g. when it's a reference) */
		call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
		GC_REFCOUNT(obj)++; /* For $this pointer */
	}


	if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
		HANDLE_EXCEPTION();
	}

	call = zend_vm_stack_push_call_frame(call_info,
		fbc, opline->extended_value, called_scope, obj);
	call->prev_execute_data = EX(call);
	EX(call) = call;

	ZEND_VM_NEXT_OPCODE();
}

 

转载于:https://my.oschina.net/u/877598/blog/1510325

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值