PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_object_handlers.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 716 777 92.1 %
Date: 2016-05-28 Functions: 34 34 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend license,     |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      18             :    +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : #include "zend.h"
      24             : #include "zend_globals.h"
      25             : #include "zend_variables.h"
      26             : #include "zend_API.h"
      27             : #include "zend_objects.h"
      28             : #include "zend_objects_API.h"
      29             : #include "zend_object_handlers.h"
      30             : #include "zend_interfaces.h"
      31             : #include "zend_exceptions.h"
      32             : #include "zend_closures.h"
      33             : #include "zend_compile.h"
      34             : #include "zend_hash.h"
      35             : 
      36             : #define DEBUG_OBJECT_HANDLERS 0
      37             : 
      38             : /* guard flags */
      39             : #define IN_GET          (1<<0)
      40             : #define IN_SET          (1<<1)
      41             : #define IN_UNSET        (1<<2)
      42             : #define IN_ISSET        (1<<3)
      43             : 
      44             : #define Z_OBJ_PROTECT_RECURSION(zval_p) \
      45             :         do { \
      46             :                 if (Z_OBJ_APPLY_COUNT_P(zval_p) >= 3) { \
      47             :                         zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?"); \
      48             :                 } \
      49             :                 Z_OBJ_INC_APPLY_COUNT_P(zval_p); \
      50             :         } while (0)
      51             : 
      52             : 
      53             : #define Z_OBJ_UNPROTECT_RECURSION(zval_p) \
      54             :         Z_OBJ_DEC_APPLY_COUNT_P(zval_p)
      55             : 
      56             : /*
      57             :   __X accessors explanation:
      58             : 
      59             :   if we have __get and property that is not part of the properties array is
      60             :   requested, we call __get handler. If it fails, we return uninitialized.
      61             : 
      62             :   if we have __set and property that is not part of the properties array is
      63             :   set, we call __set handler. If it fails, we do not change the array.
      64             : 
      65             :   for both handlers above, when we are inside __get/__set, no further calls for
      66             :   __get/__set for this property of this object will be made, to prevent endless
      67             :   recursion and enable accessors to change properties array.
      68             : 
      69             :   if we have __call and method which is not part of the class function table is
      70             :   called, we cal __call handler.
      71             : */
      72             : 
      73      629473 : ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
      74             : {
      75      629473 :         if (!zobj->properties) {
      76             :                 zend_property_info *prop_info;
      77      629473 :                 zend_class_entry *ce = zobj->ce;
      78             : 
      79      629473 :                 ALLOC_HASHTABLE(zobj->properties);
      80      629473 :                 zend_hash_init(zobj->properties, ce->default_properties_count, NULL, ZVAL_PTR_DTOR, 0);
      81      629473 :                 if (ce->default_properties_count) {
      82       12287 :                         zend_hash_real_init(zobj->properties, 0);
      83       12287 :                         zobj->properties->nInternalPointer = 0;
      84       47111 :                         ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
      85       17410 :                                 if (/*prop_info->ce == ce &&*/
      86       17410 :                                     (prop_info->flags & ZEND_ACC_STATIC) == 0) {
      87             : 
      88       34766 :                                         if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) == IS_UNDEF)) {
      89          13 :                                                 zobj->properties->u.v.flags |= HASH_FLAG_HAS_EMPTY_IND;
      90             :                                         }
      91             : 
      92       17383 :                                         _zend_hash_append_ind(zobj->properties, prop_info->name, 
      93             :                                                 OBJ_PROP(zobj, prop_info->offset));
      94             :                                 }
      95             :                         } ZEND_HASH_FOREACH_END();
      96       25575 :                         while (ce->parent && ce->parent->default_properties_count) {
      97        1001 :                                 ce = ce->parent;
      98        9635 :                                 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
      99       12654 :                                         if (prop_info->ce == ce &&
     100        4174 :                                             (prop_info->flags & ZEND_ACC_STATIC) == 0 &&
     101        4163 :                                             (prop_info->flags & ZEND_ACC_PRIVATE) != 0) {
     102             :                                                 zval zv;
     103             : 
     104        2994 :                                                 if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) == IS_UNDEF)) {
     105           2 :                                                         zobj->properties->u.v.flags |= HASH_FLAG_HAS_EMPTY_IND;
     106             :                                                 }
     107             : 
     108        1497 :                                                 ZVAL_INDIRECT(&zv, OBJ_PROP(zobj, prop_info->offset));
     109        1497 :                                                 zend_hash_add(zobj->properties, prop_info->name, &zv);
     110             :                                         }
     111             :                                 } ZEND_HASH_FOREACH_END();
     112             :                         }
     113             :                 }
     114             :         }
     115      629473 : }
     116             : /* }}} */
     117             : 
     118      487169 : ZEND_API HashTable *zend_std_get_properties(zval *object) /* {{{ */
     119             : {
     120             :         zend_object *zobj;
     121      487169 :         zobj = Z_OBJ_P(object);
     122      487169 :         if (!zobj->properties) {
     123      221158 :                 rebuild_object_properties(zobj);
     124             :         }
     125      487169 :         return zobj->properties;
     126             : }
     127             : /* }}} */
     128             : 
     129      710229 : ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ */
     130             : {
     131      710229 :         if (Z_OBJ_HANDLER_P(object, get_properties) != zend_std_get_properties) {
     132           0 :                 *table = NULL;
     133           0 :                 *n = 0;
     134           0 :                 return Z_OBJ_HANDLER_P(object, get_properties)(object);
     135             :         } else {
     136      710229 :                 zend_object *zobj = Z_OBJ_P(object);
     137             : 
     138      710229 :                 if (zobj->properties) {
     139      410067 :                         *table = NULL;
     140      410067 :                         *n = 0;
     141      410067 :                         return zobj->properties;
     142             :                 } else {
     143      300162 :                         *table = zobj->properties_table;
     144      300162 :                         *n = zobj->ce->default_properties_count;
     145      300162 :                         return NULL;
     146             :                 }
     147             :         }
     148             : }
     149             : /* }}} */
     150             : 
     151        3677 : ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp) /* {{{ */
     152             : {
     153        3677 :         zend_class_entry *ce = Z_OBJCE_P(object);
     154             :         zval retval;
     155             :         HashTable *ht;
     156             : 
     157        3677 :         if (!ce->__debugInfo) {
     158        3664 :                 *is_temp = 0;
     159        7328 :                 return Z_OBJ_HANDLER_P(object, get_properties)
     160        3664 :                         ? Z_OBJ_HANDLER_P(object, get_properties)(object)
     161             :                         : NULL;
     162             :         }
     163             : 
     164          13 :         zend_call_method_with_0_params(object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval);
     165          13 :         if (Z_TYPE(retval) == IS_ARRAY) {
     166           2 :                 if (Z_IMMUTABLE(retval)) {
     167           0 :                         *is_temp = 1;
     168           0 :                         return zend_array_dup(Z_ARRVAL(retval));
     169           2 :                 } else if (Z_REFCOUNT(retval) <= 1) {
     170           2 :                         *is_temp = 1;
     171           2 :                         ht = Z_ARR(retval);
     172           2 :                         return ht;
     173             :                 } else {
     174           0 :                         *is_temp = 0;
     175           0 :                         zval_ptr_dtor(&retval);
     176           0 :                         return Z_ARRVAL(retval);
     177             :                 }
     178          11 :         } else if (Z_TYPE(retval) == IS_NULL) {
     179           1 :                 *is_temp = 1;
     180           1 :                 ALLOC_HASHTABLE(ht);
     181           1 :                 zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
     182           1 :                 return ht;
     183             :         }
     184             : 
     185          10 :         zend_error_noreturn(E_ERROR, ZEND_DEBUGINFO_FUNC_NAME "() must return an array");
     186             : 
     187             :         return NULL; /* Compilers are dumb and don't understand that noreturn means that the function does NOT need a return value... */
     188             : }
     189             : /* }}} */
     190             : 
     191         155 : static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{{ */
     192             : {
     193         155 :         zend_class_entry *ce = Z_OBJCE_P(object);
     194             : 
     195             :         /* __get handler is called with one argument:
     196             :               property name
     197             : 
     198             :            it should return whether the call was successful or not
     199             :         */
     200         155 :         if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
     201             : 
     202         155 :         zend_call_method_with_1_params(object, ce, &ce->__get, ZEND_GET_FUNC_NAME, retval, member);
     203             : 
     204         155 :         zval_ptr_dtor(member);
     205         155 : }
     206             : /* }}} */
     207             : 
     208         100 : static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{ */
     209             : {
     210             :         zval retval;
     211             :         int result;
     212         100 :         zend_class_entry *ce = Z_OBJCE_P(object);
     213             : 
     214         100 :         if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
     215         100 :         if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
     216             : 
     217             :         /* __set handler is called with two arguments:
     218             :              property name
     219             :              value to be set
     220             : 
     221             :            it should return whether the call was successful or not
     222             :         */
     223         100 :         zend_call_method_with_2_params(object, ce, &ce->__set, ZEND_SET_FUNC_NAME, &retval, member, value);
     224             : 
     225         100 :         zval_ptr_dtor(member);
     226         100 :         zval_ptr_dtor(value);
     227             : 
     228         100 :         if (Z_TYPE(retval) != IS_UNDEF) {
     229          99 :                 result = i_zend_is_true(&retval) ? SUCCESS : FAILURE;
     230          99 :                 zval_ptr_dtor(&retval);
     231          99 :                 return result;
     232             :         } else {
     233           1 :                 return FAILURE;
     234             :         }
     235             : }
     236             : /* }}} */
     237             : 
     238           8 : static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
     239             : {
     240           8 :         zend_class_entry *ce = Z_OBJCE_P(object);
     241             : 
     242             :         /* __unset handler is called with one argument:
     243             :               property name
     244             :         */
     245             : 
     246           8 :         if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
     247             : 
     248           8 :         zend_call_method_with_1_params(object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
     249             : 
     250           8 :         zval_ptr_dtor(member);
     251           8 : }
     252             : /* }}} */
     253             : 
     254          28 : static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /* {{{ */
     255             : {
     256          28 :         zend_class_entry *ce = Z_OBJCE_P(object);
     257             : 
     258             :         /* __isset handler is called with one argument:
     259             :               property name
     260             : 
     261             :            it should return whether the property is set or not
     262             :         */
     263             : 
     264          28 :         if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
     265             : 
     266          28 :         zend_call_method_with_1_params(object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, retval, member);
     267             : 
     268          28 :         zval_ptr_dtor(member);
     269          28 : }
     270             : /* }}} */
     271             : 
     272             : static zend_always_inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce) /* {{{ */
     273             : {
     274       38727 :         if (property_info->flags & ZEND_ACC_PUBLIC) {
     275       19682 :                 return 1;
     276       19045 :         } else if (property_info->flags & ZEND_ACC_PRIVATE) {
     277        4274 :                 return (ce == EG(scope) || property_info->ce == EG(scope));
     278       14771 :         } else if (property_info->flags & ZEND_ACC_PROTECTED) {
     279       14770 :                 return zend_check_protected(property_info->ce, EG(scope));
     280             :         }
     281           1 :         return 0;
     282             : }
     283             : /* }}} */
     284             : 
     285             : static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */
     286             : {
     287        8705 :         child_class = child_class->parent;
     288       10320 :         while (child_class) {
     289        4852 :                 if (child_class == parent_class) {
     290        3237 :                         return 1;
     291             :                 }
     292        1615 :                 child_class = child_class->parent;
     293             :         }
     294             : 
     295        5468 :         return 0;
     296             : }
     297             : /* }}} */
     298             : 
     299             : static zend_always_inline uint32_t zend_get_property_offset(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot) /* {{{ */
     300             : {
     301             :         zval *zv;
     302      473838 :         zend_property_info *property_info = NULL;
     303             :         uint32_t flags;
     304             : 
     305      473838 :         if (cache_slot && EXPECTED(ce == CACHED_PTR_EX(cache_slot))) {
     306        4560 :                 return (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
     307             :         }
     308             : 
     309      469278 :         if (UNEXPECTED(ZSTR_VAL(member)[0] == '\0')) {
     310          20 :                 if (!silent) {
     311           1 :                         if (ZSTR_LEN(member) == 0) {
     312           1 :                                 zend_throw_error(NULL, "Cannot access empty property");
     313             :                         } else {
     314           0 :                                 zend_throw_error(NULL, "Cannot access property started with '\\0'");
     315             :                         }
     316             :                 }
     317          20 :                 return ZEND_WRONG_PROPERTY_OFFSET;
     318             :         }
     319             : 
     320      469258 :         if (UNEXPECTED(zend_hash_num_elements(&ce->properties_info) == 0)) {
     321             :                 goto exit_dynamic;
     322             :         }
     323             : 
     324       41601 :         zv = zend_hash_find(&ce->properties_info, member);
     325       41601 :         if (EXPECTED(zv != NULL)) {
     326       39745 :                 property_info = (zend_property_info*)Z_PTR_P(zv);
     327       39745 :                 flags = property_info->flags;
     328       39745 :                 if (UNEXPECTED((flags & ZEND_ACC_SHADOW) != 0)) {
     329             :                         /* if it's a shadow - go to access it's private */
     330        3154 :                         property_info = NULL;
     331             :                 } else {
     332       36591 :                         if (EXPECTED(zend_verify_property_access(property_info, ce) != 0)) {
     333       73066 :                                 if (UNEXPECTED(!(flags & ZEND_ACC_CHANGED))
     334       36552 :                                         || UNEXPECTED((flags & ZEND_ACC_PRIVATE))) {
     335       36493 :                                         if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
     336          16 :                                                 if (!silent) {
     337          12 :                                                         zend_error(E_NOTICE, "Accessing static property %s::$%s as non static", ZSTR_VAL(ce->name), ZSTR_VAL(member));
     338             :                                                 }
     339          16 :                                                 return ZEND_DYNAMIC_PROPERTY_OFFSET;
     340             :                                         }
     341             :                                         goto exit;
     342             :                                 }
     343             :                         } else {
     344             :                                 /* Try to look in the scope instead */
     345          77 :                                 property_info = ZEND_WRONG_PROPERTY_INFO;
     346             :                         }
     347             :                 }
     348             :         }
     349             : 
     350       20009 :         if (EG(scope) != ce
     351        4583 :                 && EG(scope)
     352             :                 && is_derived_class(ce, EG(scope))
     353        7171 :                 && (zv = zend_hash_find(&EG(scope)->properties_info, member)) != NULL
     354        3147 :                 && ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE) {
     355        3143 :                 property_info = (zend_property_info*)Z_PTR_P(zv);
     356        3143 :                 if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0)) {
     357           2 :                         return ZEND_DYNAMIC_PROPERTY_OFFSET;
     358             :                 }
     359        1965 :         } else if (UNEXPECTED(property_info == NULL)) {
     360             : exit_dynamic:
     361      429543 :                 if (cache_slot) {
     362        1875 :                         CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, (void*)(intptr_t)ZEND_DYNAMIC_PROPERTY_OFFSET);
     363             :                 }
     364      429543 :                 return ZEND_DYNAMIC_PROPERTY_OFFSET;
     365          79 :         } else if (UNEXPECTED(property_info == ZEND_WRONG_PROPERTY_INFO)) {
     366             :                 /* Information was available, but we were denied access.  Error out. */
     367          69 :                 if (!silent) {
     368          23 :                         zend_throw_error(NULL, "Cannot access %s property %s::$%s", zend_visibility_string(flags), ZSTR_VAL(ce->name), ZSTR_VAL(member));
     369             :                 }
     370          69 :                 return ZEND_WRONG_PROPERTY_OFFSET;
     371             :         }
     372             : 
     373             : exit:
     374       39628 :         if (cache_slot) {
     375        2737 :                 CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, (void*)(intptr_t)property_info->offset);
     376             :         }
     377       39628 :         return property_info->offset;
     378             : }
     379             : /* }}} */
     380             : 
     381        1051 : ZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent) /* {{{ */
     382             : {
     383             :         zval *zv;
     384        1051 :         zend_property_info *property_info = NULL;
     385             :         uint32_t flags;
     386             : 
     387        1051 :         if (UNEXPECTED(ZSTR_VAL(member)[0] == '\0')) {
     388           0 :                 if (!silent) {
     389           0 :                         if (ZSTR_LEN(member) == 0) {
     390           0 :                                 zend_throw_error(NULL, "Cannot access empty property");
     391             :                         } else {
     392           0 :                                 zend_throw_error(NULL, "Cannot access property started with '\\0'");
     393             :                         }
     394             :                 }
     395           0 :                 return ZEND_WRONG_PROPERTY_INFO;
     396             :         }
     397             : 
     398        1051 :         if (UNEXPECTED(zend_hash_num_elements(&ce->properties_info) == 0)) {
     399         172 :                 goto exit_dynamic;
     400             :         }
     401             : 
     402         879 :         zv = zend_hash_find(&ce->properties_info, member);
     403         879 :         if (EXPECTED(zv != NULL)) {
     404         766 :                 property_info = (zend_property_info*)Z_PTR_P(zv);
     405         766 :                 flags = property_info->flags;
     406         766 :                 if (UNEXPECTED((flags & ZEND_ACC_SHADOW) != 0)) {
     407             :                         /* if it's a shadow - go to access it's private */
     408          51 :                         property_info = NULL;
     409             :                 } else {
     410         715 :                         if (EXPECTED(zend_verify_property_access(property_info, ce) != 0)) {
     411        1271 :                                 if (UNEXPECTED(!(flags & ZEND_ACC_CHANGED))
     412         643 :                                         || UNEXPECTED((flags & ZEND_ACC_PRIVATE))) {
     413         628 :                                         if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
     414           0 :                                                 if (!silent) {
     415           0 :                                                         zend_error(E_NOTICE, "Accessing static property %s::$%s as non static", ZSTR_VAL(ce->name), ZSTR_VAL(member));
     416             :                                                 }
     417             :                                         }
     418         628 :                                         goto exit;
     419             :                                 }
     420             :                         } else {
     421             :                                 /* Try to look in the scope instead */
     422          87 :                                 property_info = ZEND_WRONG_PROPERTY_INFO;
     423             :                         }
     424             :                 }
     425             :         }
     426             : 
     427         685 :         if (EG(scope) != ce
     428         186 :                 && EG(scope)
     429             :                 && is_derived_class(ce, EG(scope))
     430         154 :                 && (zv = zend_hash_find(&EG(scope)->properties_info, member)) != NULL
     431          48 :                 && ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE) {
     432          46 :                 property_info = (zend_property_info*)Z_PTR_P(zv);
     433         205 :         } else if (UNEXPECTED(property_info == NULL)) {
     434             : exit_dynamic:
     435         302 :                 return NULL;
     436          75 :         } else if (UNEXPECTED(property_info == ZEND_WRONG_PROPERTY_INFO)) {
     437             :                 /* Information was available, but we were denied access.  Error out. */
     438          75 :                 if (!silent) {
     439           0 :                         zend_throw_error(NULL, "Cannot access %s property %s::$%s", zend_visibility_string(flags), ZSTR_VAL(ce->name), ZSTR_VAL(member));
     440             :                 }
     441          75 :                 return ZEND_WRONG_PROPERTY_INFO;
     442             :         }
     443             : 
     444             : exit:
     445         674 :         return property_info;
     446             : }
     447             : /* }}} */
     448             : 
     449         907 : ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_info_name) /* {{{ */
     450             : {
     451             :         zend_property_info *property_info;
     452         907 :         const char *class_name = NULL;
     453             :         const char *prop_name;
     454             :         zend_string *member;
     455             :         size_t prop_name_len;
     456             : 
     457         907 :         if (ZSTR_VAL(prop_info_name)[0] == 0) {
     458         329 :                 zend_unmangle_property_name_ex(prop_info_name, &class_name, &prop_name, &prop_name_len);
     459         658 :                 member = zend_string_init(prop_name, prop_name_len, 0);
     460             :         } else {
     461         578 :                 member = zend_string_copy(prop_info_name);
     462             :         }
     463         907 :         property_info = zend_get_property_info(zobj->ce, member, 1);
     464             :         zend_string_release(member);
     465         907 :         if (property_info == NULL) {
     466             :                 /* undefined public property */
     467         167 :                 if (class_name && class_name[0] != '*') {
     468             :                         /* we we're looking for a private prop */
     469          18 :                         return FAILURE;
     470             :                 }
     471         149 :                 return SUCCESS;
     472         740 :         } else if (property_info == ZEND_WRONG_PROPERTY_INFO) {
     473          73 :                 return FAILURE;
     474             :         }
     475         667 :         if (class_name && class_name[0] != '*') {
     476         100 :                 if (!(property_info->flags & ZEND_ACC_PRIVATE)) {
     477             :                         /* we we're looking for a private prop but found a non private one of the same name */
     478           0 :                         return FAILURE;
     479         100 :                 } else if (strcmp(ZSTR_VAL(prop_info_name)+1, ZSTR_VAL(property_info->name)+1)) {
     480             :                         /* we we're looking for a private prop but found a private one of the same name but another class */
     481          11 :                         return FAILURE;
     482             :                 }
     483             :         }
     484        1312 :         return zend_verify_property_access(property_info, zobj->ce) ? SUCCESS : FAILURE;
     485             : }
     486             : /* }}} */
     487             : 
     488         143 : static void zend_property_guard_dtor(zval *el) /* {{{ */ {
     489         143 :         efree_size(Z_PTR_P(el), sizeof(zend_ulong));
     490         143 : }
     491             : /* }}} */
     492             : 
     493         375 : static zend_long *zend_get_property_guard(zend_object *zobj, zend_string *member) /* {{{ */
     494             : {
     495             :         HashTable *guards;
     496             :         zend_long stub, *guard;
     497             : 
     498             :         ZEND_ASSERT(GC_FLAGS(zobj) & IS_OBJ_USE_GUARDS);
     499         375 :         if (GC_FLAGS(zobj) & IS_OBJ_HAS_GUARDS) {
     500         290 :                 guards = Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]);
     501             :                 ZEND_ASSERT(guards != NULL);
     502         290 :                 if ((guard = (zend_long *)zend_hash_find_ptr(guards, member)) != NULL) {
     503         232 :                         return guard;
     504             :                 }
     505             :         } else {
     506          85 :                 ALLOC_HASHTABLE(guards);
     507          85 :                 zend_hash_init(guards, 8, NULL, zend_property_guard_dtor, 0);
     508          85 :                 Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]) = guards;
     509          85 :                 GC_FLAGS(zobj) |= IS_OBJ_HAS_GUARDS;
     510             :         }
     511             : 
     512         143 :         stub = 0;
     513         143 :         return (zend_long *)zend_hash_add_mem(guards, member, &stub, sizeof(zend_ulong));
     514             : }
     515             : /* }}} */
     516             : 
     517       10135 : zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */
     518             : {
     519             :         zend_object *zobj;
     520             :         zval tmp_member;
     521             :         zval *retval;
     522             :         uint32_t property_offset;
     523             : 
     524       10135 :         zobj = Z_OBJ_P(object);
     525             : 
     526       10135 :         ZVAL_UNDEF(&tmp_member);
     527       10135 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     528          11 :                 ZVAL_STR(&tmp_member, zval_get_string(member));
     529           5 :                 member = &tmp_member;
     530           5 :                 cache_slot = NULL;
     531             :         }
     532             : 
     533             : #if DEBUG_OBJECT_HANDLERS
     534             :         fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
     535             : #endif
     536             : 
     537             :         /* make zend_get_property_info silent if we have getter - we may want to use it */
     538       20268 :         property_offset = zend_get_property_offset(zobj->ce, Z_STR_P(member), (type == BP_VAR_IS) || (zobj->ce->__get != NULL), cache_slot);
     539             : 
     540       10134 :         if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
     541       10102 :                 if (EXPECTED(property_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
     542        8073 :                         retval = OBJ_PROP(zobj, property_offset);
     543        8073 :                         if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
     544        8048 :                                 goto exit;
     545             :                         }
     546        2029 :                 } else if (EXPECTED(zobj->properties != NULL)) {
     547        1735 :                         retval = zend_hash_find(zobj->properties, Z_STR_P(member));
     548        1735 :                         if (EXPECTED(retval)) goto exit;
     549             :                 }
     550          32 :         } else if (UNEXPECTED(EG(exception))) {
     551           9 :                 retval = &EG(uninitialized_zval);
     552           9 :                 goto exit;
     553             :         }
     554             : 
     555             :         /* magic get */
     556         459 :         if (zobj->ce->__get) {
     557         165 :                 zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
     558         165 :                 if (!((*guard) & IN_GET)) {
     559             :                         zval tmp_object;
     560             : 
     561             :                         /* have getter - try with it! */
     562         153 :                         ZVAL_COPY(&tmp_object, object);
     563         153 :                         *guard |= IN_GET; /* prevent circular getting */
     564         153 :                         zend_std_call_getter(&tmp_object, member, rv);
     565         153 :                         *guard &= ~IN_GET;
     566             : 
     567         153 :                         if (Z_TYPE_P(rv) != IS_UNDEF) {
     568         143 :                                 retval = rv;
     569         143 :                                 if (!Z_ISREF_P(rv) &&
     570             :                                     (type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET)) {
     571          44 :                                         SEPARATE_ZVAL(rv);
     572          22 :                                         if (UNEXPECTED(Z_TYPE_P(rv) != IS_OBJECT)) {
     573          14 :                                                 zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", ZSTR_VAL(zobj->ce->name), Z_STRVAL_P(member));
     574             :                                         }
     575             :                                 }
     576             :                         } else {
     577          10 :                                 retval = &EG(uninitialized_zval);
     578             :                         }
     579         153 :                         zval_ptr_dtor(&tmp_object);
     580         153 :                         goto exit;
     581             :                 } else {
     582          12 :                         if (Z_STRVAL_P(member)[0] == '\0') {
     583           1 :                                 if (Z_STRLEN_P(member) == 0) {
     584           1 :                                         zend_throw_error(NULL, "Cannot access empty property");
     585           1 :                                         retval = &EG(uninitialized_zval);
     586           1 :                                         goto exit;
     587             :                                 } else {
     588           0 :                                         zend_throw_error(NULL, "Cannot access property started with '\\0'");
     589           0 :                                         retval = &EG(uninitialized_zval);
     590           0 :                                         goto exit;
     591             :                                 }
     592             :                         }
     593             :                 }
     594             :         }
     595         305 :         if ((type != BP_VAR_IS)) {
     596          60 :                 zend_error(E_NOTICE,"Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), Z_STRVAL_P(member));
     597             :         }
     598         305 :         retval = &EG(uninitialized_zval);
     599             : 
     600             : exit:
     601       10134 :         if (UNEXPECTED(Z_REFCOUNTED(tmp_member))) {
     602           3 :                 zval_ptr_dtor(&tmp_member);
     603             :         }
     604             : 
     605       10134 :         return retval;
     606             : }
     607             : /* }}} */
     608             : 
     609      458163 : ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */
     610             : {
     611             :         zend_object *zobj;
     612             :         zval tmp_member;
     613             :         zval *variable_ptr;
     614             :         uint32_t property_offset;
     615             : 
     616      458163 :         zobj = Z_OBJ_P(object);
     617             : 
     618      458163 :         ZVAL_UNDEF(&tmp_member);
     619      458163 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     620           8 :                 ZVAL_STR(&tmp_member, zval_get_string(member));
     621           4 :                 member = &tmp_member;
     622           4 :                 cache_slot = NULL;
     623             :         }
     624             : 
     625      916326 :         property_offset = zend_get_property_offset(zobj->ce, Z_STR_P(member), (zobj->ce->__set != NULL), cache_slot);
     626             : 
     627      458163 :         if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
     628      458135 :                 if (EXPECTED(property_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
     629       31108 :                         variable_ptr = OBJ_PROP(zobj, property_offset);
     630       31108 :                         if (Z_TYPE_P(variable_ptr) != IS_UNDEF) {
     631       31087 :                                 goto found;
     632             :                         }
     633      427027 :                 } else if (EXPECTED(zobj->properties != NULL)) {
     634       30672 :                         if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
     635           2 :                                 if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
     636           2 :                                         GC_REFCOUNT(zobj->properties)--;
     637             :                                 }
     638           2 :                                 zobj->properties = zend_array_dup(zobj->properties);
     639             :                         }
     640       30672 :                         if ((variable_ptr = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) {
     641             : found:
     642             :                                 zend_assign_to_variable(variable_ptr, value, IS_CV);
     643       31139 :                                 goto exit;
     644             :                         }
     645             :                 }
     646          28 :         } else if (UNEXPECTED(EG(exception))) {
     647          11 :                 goto exit;
     648             :         }
     649             : 
     650             :         /* magic set */
     651      427013 :         if (zobj->ce->__set) {
     652         121 :                 zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
     653             : 
     654         121 :             if (!((*guard) & IN_SET)) {
     655             :                         zval tmp_object;
     656             : 
     657         100 :                         ZVAL_COPY(&tmp_object, object);
     658         100 :                         (*guard) |= IN_SET; /* prevent circular setting */
     659         100 :                         if (zend_std_call_setter(&tmp_object, member, value) != SUCCESS) {
     660             :                                 /* for now, just ignore it - __set should take care of warnings, etc. */
     661             :                         }
     662         100 :                         (*guard) &= ~IN_SET;
     663         100 :                         zval_ptr_dtor(&tmp_object);
     664          21 :                 } else if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
     665          19 :                         goto write_std_property;
     666             :                 } else {
     667           2 :                         if (Z_STRVAL_P(member)[0] == '\0') {
     668           1 :                                 if (Z_STRLEN_P(member) == 0) {
     669           1 :                                         zend_throw_error(NULL, "Cannot access empty property");
     670           1 :                                         goto exit;
     671             :                                 } else {
     672           0 :                                         zend_throw_error(NULL, "Cannot access property started with '\\0'");
     673           0 :                                         goto exit;
     674             :                                 }
     675             :                         }
     676             :                 }
     677      426892 :         } else if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
     678             :                 zval tmp;
     679             : 
     680             : write_std_property:
     681      426911 :                 if (Z_REFCOUNTED_P(value)) {
     682      416317 :                         if (Z_ISREF_P(value)) {
     683             :                                 /* if we assign referenced variable, we should separate it */
     684           0 :                                 ZVAL_COPY(&tmp, Z_REFVAL_P(value));
     685           0 :                                 value = &tmp;
     686             :                         } else {
     687             :                                 Z_ADDREF_P(value);
     688             :                         }
     689             :                 }
     690      426911 :                 if (EXPECTED(property_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
     691          15 :                         ZVAL_COPY_VALUE(OBJ_PROP(zobj, property_offset), value);
     692             :                 } else {
     693      426896 :                         if (!zobj->properties) {
     694      396279 :                                 rebuild_object_properties(zobj);
     695             :                         }
     696      426896 :                         zend_hash_add_new(zobj->properties, Z_STR_P(member), value);
     697             :                 }
     698             :         }
     699             : 
     700             : exit:
     701      458163 :         if (UNEXPECTED(Z_REFCOUNTED(tmp_member))) {
     702           3 :                 zval_ptr_dtor(&tmp_member);
     703             :         }
     704      458163 : }
     705             : /* }}} */
     706             : 
     707         490 : zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */
     708             : {
     709         490 :         zend_class_entry *ce = Z_OBJCE_P(object);
     710             :         zval tmp;
     711             : 
     712         490 :         if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) {
     713         485 :                 if(offset == NULL) {
     714             :                         /* [] construct */
     715           1 :                         ZVAL_UNDEF(&tmp);
     716           1 :                         offset = &tmp;
     717             :                 } else {
     718         484 :                         SEPARATE_ARG_IF_REF(offset);
     719             :                 }
     720         485 :                 zend_call_method_with_1_params(object, ce, NULL, "offsetget", rv, offset);
     721             : 
     722         485 :                 zval_ptr_dtor(offset);
     723             : 
     724         485 :                 if (UNEXPECTED(Z_TYPE_P(rv) == IS_UNDEF)) {
     725           5 :                         if (UNEXPECTED(!EG(exception))) {
     726           0 :                                 zend_throw_error(NULL, "Undefined offset for object of type %s used as array", ZSTR_VAL(ce->name));
     727             :                         }
     728           5 :                         return NULL;
     729             :                 }
     730         480 :                 return rv;
     731             :         } else {
     732           5 :                 zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name));
     733           5 :                 return NULL;
     734             :         }
     735             : }
     736             : /* }}} */
     737             : 
     738        1327 : static void zend_std_write_dimension(zval *object, zval *offset, zval *value) /* {{{ */
     739             : {
     740        1327 :         zend_class_entry *ce = Z_OBJCE_P(object);
     741             :         zval tmp;
     742             : 
     743        1327 :         if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) {
     744        1326 :                 if (!offset) {
     745          11 :                         ZVAL_NULL(&tmp);
     746          11 :                         offset = &tmp;
     747             :                 } else {
     748        1315 :                         SEPARATE_ARG_IF_REF(offset);
     749             :                 }
     750        1326 :                 zend_call_method_with_2_params(object, ce, NULL, "offsetset", NULL, offset, value);
     751        1326 :                 zval_ptr_dtor(offset);
     752             :         } else {
     753           1 :                 zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name));
     754             :         }
     755        1327 : }
     756             : /* }}} */
     757             : 
     758        1078 : static int zend_std_has_dimension(zval *object, zval *offset, int check_empty) /* {{{ */
     759             : {
     760        1078 :         zend_class_entry *ce = Z_OBJCE_P(object);
     761             :         zval retval;
     762             :         int result;
     763             : 
     764        1078 :         if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) {
     765        1078 :                 SEPARATE_ARG_IF_REF(offset);
     766        1078 :                 zend_call_method_with_1_params(object, ce, NULL, "offsetexists", &retval, offset);
     767        1078 :                 if (EXPECTED(Z_TYPE(retval) != IS_UNDEF)) {
     768        1076 :                         result = i_zend_is_true(&retval);
     769        1076 :                         zval_ptr_dtor(&retval);
     770        1076 :                         if (check_empty && result && EXPECTED(!EG(exception))) {
     771           8 :                                 zend_call_method_with_1_params(object, ce, NULL, "offsetget", &retval, offset);
     772           8 :                                 if (EXPECTED(Z_TYPE(retval) != IS_UNDEF)) {
     773           8 :                                         result = i_zend_is_true(&retval);
     774           8 :                                         zval_ptr_dtor(&retval);
     775             :                                 }
     776             :                         }
     777             :                 } else {
     778           2 :                         result = 0;
     779             :                 }
     780        1078 :                 zval_ptr_dtor(offset);
     781             :         } else {
     782           0 :                 zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name));
     783           0 :                 return 0;
     784             :         }
     785        1078 :         return result;
     786             : }
     787             : /* }}} */
     788             : 
     789        4967 : static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */
     790             : {
     791             :         zend_object *zobj;
     792             :         zend_string *name;
     793        4967 :         zval *retval = NULL;
     794             :         uint32_t property_offset;
     795             : 
     796        4967 :         zobj = Z_OBJ_P(object);
     797        4967 :         if (EXPECTED(Z_TYPE_P(member) == IS_STRING)) {
     798        4967 :                 name = Z_STR_P(member);
     799             :         } else {
     800           0 :                 name = zval_get_string(member);
     801             :         }
     802             : 
     803             : #if DEBUG_OBJECT_HANDLERS
     804             :         fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name));
     805             : #endif
     806             : 
     807        9934 :         property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot);
     808             : 
     809        4967 :         if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
     810        4959 :                 if (EXPECTED(property_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
     811        4484 :                         retval = OBJ_PROP(zobj, property_offset);
     812        4484 :                         if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
     813           0 :                                 if (EXPECTED(!zobj->ce->__get) ||
     814           0 :                                     UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
     815           0 :                                         ZVAL_NULL(retval);
     816             :                                         /* Notice is thrown after creation of the property, to avoid EG(std_property_info)
     817             :                                          * being overwritten in an error handler. */
     818           0 :                                         if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
     819           0 :                                                 zend_error(E_NOTICE, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
     820             :                                         }
     821             :                                 } else {
     822             :                                         /* we do have getter - fail and let it try again with usual get/set */
     823           0 :                                         retval = NULL;
     824             :                                 }
     825             :                         }
     826             :                 } else {
     827         475 :                         if (EXPECTED(zobj->properties)) {
     828         366 :                                 if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
     829           3 :                                         if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
     830           3 :                                                 GC_REFCOUNT(zobj->properties)--;
     831             :                                         }
     832           3 :                                         zobj->properties = zend_array_dup(zobj->properties);
     833             :                                 }
     834         366 :                             if (EXPECTED((retval = zend_hash_find(zobj->properties, name)) != NULL)) {
     835         130 :                                         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     836             :                                                 zend_string_release(name);
     837             :                                         }
     838         130 :                                         return retval;
     839             :                             }
     840             :                         }
     841         386 :                         if (EXPECTED(!zobj->ce->__get) ||
     842          41 :                             UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
     843         304 :                                 if (UNEXPECTED(!zobj->properties)) {
     844          69 :                                         rebuild_object_properties(zobj);
     845             :                                 }
     846         304 :                                 retval = zend_hash_update(zobj->properties, name, &EG(uninitialized_zval));
     847             :                                 /* Notice is thrown after creation of the property, to avoid EG(std_property_info)
     848             :                                  * being overwritten in an error handler. */
     849         304 :                                 if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
     850          15 :                                         zend_error(E_NOTICE, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
     851             :                                 }
     852             :                         }
     853             :                 }
     854             :         }
     855             : 
     856        4837 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     857             :                 zend_string_release(name);
     858             :         }
     859        4837 :         return retval;
     860             : }
     861             : /* }}} */
     862             : 
     863         186 : static void zend_std_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */
     864             : {
     865             :         zend_object *zobj;
     866             :         zval tmp_member;
     867             :         uint32_t property_offset;
     868             : 
     869         186 :         zobj = Z_OBJ_P(object);
     870             : 
     871         186 :         ZVAL_UNDEF(&tmp_member);
     872         186 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     873           2 :                 ZVAL_STR(&tmp_member, zval_get_string(member));
     874           1 :                 member = &tmp_member;
     875           1 :                 cache_slot = NULL;
     876             :         }
     877             : 
     878         372 :         property_offset = zend_get_property_offset(zobj->ce, Z_STR_P(member), (zobj->ce->__unset != NULL), cache_slot);
     879             : 
     880         186 :         if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
     881         183 :                 if (EXPECTED(property_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
     882          66 :                         zval *slot = OBJ_PROP(zobj, property_offset);
     883             : 
     884          66 :                         if (Z_TYPE_P(slot) != IS_UNDEF) {
     885          66 :                                 zval_ptr_dtor(slot);
     886          66 :                                 ZVAL_UNDEF(slot);
     887          66 :                                 if (zobj->properties) {
     888          25 :                                         zobj->properties->u.v.flags |= HASH_FLAG_HAS_EMPTY_IND;
     889             :                                 }
     890          66 :                                 goto exit;
     891             :                         }
     892         117 :                 } else if (EXPECTED(zobj->properties != NULL)) {
     893         109 :                         if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
     894           1 :                                 if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
     895           1 :                                         GC_REFCOUNT(zobj->properties)--;
     896             :                                 }
     897           1 :                                 zobj->properties = zend_array_dup(zobj->properties);
     898             :                         }
     899         109 :                         if (EXPECTED(zend_hash_del(zobj->properties, Z_STR_P(member)) != FAILURE)) {
     900         103 :                                 goto exit;
     901             :                         }
     902             :                 }
     903           3 :         } else if (UNEXPECTED(EG(exception))) {
     904           1 :                 goto exit;
     905             :         }
     906             : 
     907             :         /* magic unset */
     908          16 :         if (zobj->ce->__unset) {
     909           9 :                 zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
     910           9 :                 if (!((*guard) & IN_UNSET)) {
     911             :                         zval tmp_object;
     912             : 
     913             :                         /* have unseter - try with it! */
     914           8 :                         ZVAL_COPY(&tmp_object, object);
     915           8 :                         (*guard) |= IN_UNSET; /* prevent circular unsetting */
     916           8 :                         zend_std_call_unsetter(&tmp_object, member);
     917           8 :                         (*guard) &= ~IN_UNSET;
     918           8 :                         zval_ptr_dtor(&tmp_object);
     919             :                 } else {
     920           1 :                         if (Z_STRVAL_P(member)[0] == '\0') {
     921           1 :                                 if (Z_STRLEN_P(member) == 0) {
     922           1 :                                         zend_throw_error(NULL, "Cannot access empty property");
     923           1 :                                         goto exit;
     924             :                                 } else {
     925           0 :                                         zend_throw_error(NULL, "Cannot access property started with '\\0'");
     926             :                                         goto exit;
     927             :                                 }
     928             :                         }
     929             :                 }
     930             :         }
     931             : 
     932             : exit:
     933         186 :         if (UNEXPECTED(Z_REFCOUNTED(tmp_member))) {
     934           0 :                 zval_ptr_dtor(&tmp_member);
     935             :         }
     936         186 : }
     937             : /* }}} */
     938             : 
     939          27 : static void zend_std_unset_dimension(zval *object, zval *offset) /* {{{ */
     940             : {
     941          27 :         zend_class_entry *ce = Z_OBJCE_P(object);
     942             : 
     943          27 :         if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1)) {
     944          27 :                 SEPARATE_ARG_IF_REF(offset);
     945          27 :                 zend_call_method_with_1_params(object, ce, NULL, "offsetunset", NULL, offset);
     946          27 :                 zval_ptr_dtor(offset);
     947             :         } else {
     948           0 :                 zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name));
     949             :         }
     950          27 : }
     951             : /* }}} */
     952             : 
     953             : /* Ensures that we're allowed to call a private method.
     954             :  * Returns the function address that should be called, or NULL
     955             :  * if no such function exists.
     956             :  */
     957         199 : static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, zend_string *function_name) /* {{{ */
     958             : {
     959             :     zval *func;
     960             : 
     961         199 :         if (!ce) {
     962           6 :                 return 0;
     963             :         }
     964             : 
     965             :         /* We may call a private function if:
     966             :          * 1.  The class of our object is the same as the scope, and the private
     967             :          *     function (EX(fbc)) has the same scope.
     968             :          * 2.  One of our parent classes are the same as the scope, and it contains
     969             :          *     a private function with the same name that has the same scope.
     970             :          */
     971         193 :         if (fbc->common.scope == ce && EG(scope) == ce) {
     972             :                 /* rule #1 checks out ok, allow the function call */
     973         148 :                 return fbc;
     974             :         }
     975             : 
     976             : 
     977             :         /* Check rule #2 */
     978          45 :         ce = ce->parent;
     979         103 :         while (ce) {
     980          25 :                 if (ce == EG(scope)) {
     981          12 :                         if ((func = zend_hash_find(&ce->function_table, function_name))) {
     982          12 :                                 fbc = Z_FUNC_P(func);
     983          24 :                                 if (fbc->common.fn_flags & ZEND_ACC_PRIVATE
     984          24 :                                         && fbc->common.scope == EG(scope)) {
     985          10 :                                         return fbc;
     986             :                                 }
     987             :                         }
     988           2 :                         break;
     989             :                 }
     990          13 :                 ce = ce->parent;
     991             :         }
     992          35 :         return NULL;
     993             : }
     994             : /* }}} */
     995             : 
     996          32 : ZEND_API int zend_check_private(zend_function *fbc, zend_class_entry *ce, zend_string *function_name) /* {{{ */
     997             : {
     998          32 :         return zend_check_private_int(fbc, ce, function_name) != NULL;
     999             : }
    1000             : /* }}} */
    1001             : 
    1002             : /* Ensures that we're allowed to call a protected method.
    1003             :  */
    1004       15046 : ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) /* {{{ */
    1005             : {
    1006       15046 :         zend_class_entry *fbc_scope = ce;
    1007             : 
    1008             :         /* Is the context that's calling the function, the same as one of
    1009             :          * the function's parents?
    1010             :          */
    1011       32382 :         while (fbc_scope) {
    1012       15310 :                 if (fbc_scope==scope) {
    1013       13020 :                         return 1;
    1014             :                 }
    1015        2290 :                 fbc_scope = fbc_scope->parent;
    1016             :         }
    1017             : 
    1018             :         /* Is the function's scope the same as our current object context,
    1019             :          * or any of the parents of our context?
    1020             :          */
    1021        6482 :         while (scope) {
    1022        4324 :                 if (scope==ce) {
    1023        1894 :                         return 1;
    1024             :                 }
    1025        2430 :                 scope = scope->parent;
    1026             :         }
    1027         132 :         return 0;
    1028             : }
    1029             : /* }}} */
    1030             : 
    1031        3505 : ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend_string *method_name, int is_static) /* {{{ */
    1032             : {
    1033             :         zend_op_array *func;
    1034        3505 :         zend_function *fbc = is_static ? ce->__callstatic : ce->__call;
    1035             : 
    1036             :         ZEND_ASSERT(fbc);
    1037             : 
    1038        3505 :         if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
    1039        3504 :                 func = &EG(trampoline).op_array;
    1040             :         } else {
    1041           1 :                 func = ecalloc(1, sizeof(zend_op_array));
    1042             :         }
    1043             : 
    1044        3505 :         func->type = ZEND_USER_FUNCTION;
    1045        3505 :         func->arg_flags[0] = 0;
    1046        3505 :         func->arg_flags[1] = 0;
    1047        3505 :         func->arg_flags[2] = 0;
    1048        3505 :         func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC;
    1049        3505 :         if (is_static) {
    1050          54 :                 func->fn_flags |= ZEND_ACC_STATIC;
    1051             :         }
    1052        3505 :         func->this_var = -1;
    1053        3505 :         func->opcodes = &EG(call_trampoline_op);
    1054             : 
    1055        3505 :         func->prototype = fbc;
    1056        3505 :         func->scope = fbc->common.scope;
    1057             :         /* reserve space for arguments, local and temorary variables */
    1058        3505 :         func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, 2) : 2;
    1059        3505 :         func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : ZSTR_EMPTY_ALLOC();
    1060        3505 :         func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
    1061        3505 :         func->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0;
    1062             : 
    1063             :         //??? keep compatibility for "\0" characters
    1064             :         //??? see: Zend/tests/bug46238.phpt
    1065        3505 :         if (UNEXPECTED(strlen(ZSTR_VAL(method_name)) != ZSTR_LEN(method_name))) {
    1066          10 :                 func->function_name = zend_string_init(ZSTR_VAL(method_name), strlen(ZSTR_VAL(method_name)), 0);
    1067             :         } else {
    1068        3500 :                 func->function_name = zend_string_copy(method_name);
    1069             :         }
    1070             : 
    1071        3505 :         return (zend_function*)func;
    1072             : }
    1073             : /* }}} */
    1074             : 
    1075             : static zend_always_inline zend_function *zend_get_user_call_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
    1076             : {
    1077        3448 :         return zend_get_call_trampoline_func(ce, method_name, 0);
    1078             : }
    1079             : /* }}} */
    1080             : 
    1081       27909 : static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key) /* {{{ */
    1082             : {
    1083       27909 :         zend_object *zobj = *obj_ptr;
    1084             :         zval *func;
    1085             :         zend_function *fbc;
    1086             :         zend_string *lc_method_name;
    1087             :         ALLOCA_FLAG(use_heap);
    1088             : 
    1089       27909 :         if (EXPECTED(key != NULL)) {
    1090       27474 :                 lc_method_name = Z_STR_P(key);
    1091             : #ifdef ZEND_ALLOCA_MAX_SIZE
    1092       27474 :                 use_heap = 0;
    1093             : #endif
    1094             :         } else {
    1095         870 :                 ZSTR_ALLOCA_ALLOC(lc_method_name, ZSTR_LEN(method_name), use_heap);
    1096         435 :                 zend_str_tolower_copy(ZSTR_VAL(lc_method_name), ZSTR_VAL(method_name), ZSTR_LEN(method_name));
    1097             :         }
    1098             : 
    1099       27909 :         if (UNEXPECTED((func = zend_hash_find(&zobj->ce->function_table, lc_method_name)) == NULL)) {
    1100        4827 :                 if (UNEXPECTED(!key)) {
    1101         266 :                         ZSTR_ALLOCA_FREE(lc_method_name, use_heap);
    1102             :                 }
    1103        4827 :                 if (zobj->ce->__call) {
    1104        6804 :                         return zend_get_user_call_function(zobj->ce, method_name);
    1105             :                 } else {
    1106        1425 :                         return NULL;
    1107             :                 }
    1108             :         }
    1109             : 
    1110       23082 :         fbc = Z_FUNC_P(func);
    1111             :         /* Check access level */
    1112       23082 :         if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
    1113             :                 zend_function *updated_fbc;
    1114             : 
    1115             :                 /* Ensure that if we're calling a private function, we're allowed to do so.
    1116             :                  * If we're not and __call() handler exists, invoke it, otherwise error out.
    1117             :                  */
    1118         151 :                 updated_fbc = zend_check_private_int(fbc, zobj->ce, lc_method_name);
    1119         151 :                 if (EXPECTED(updated_fbc != NULL)) {
    1120         139 :                         fbc = updated_fbc;
    1121             :                 } else {
    1122          12 :                         if (zobj->ce->__call) {
    1123           8 :                                 fbc = zend_get_user_call_function(zobj->ce, method_name);
    1124             :                         } else {
    1125           8 :                                 zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(method_name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : "");
    1126           8 :                                 fbc = NULL;
    1127             :                         }
    1128             :                 }
    1129             :         } else {
    1130             :                 /* Ensure that we haven't overridden a private function and end up calling
    1131             :                  * the overriding public function...
    1132             :                  */
    1133       27548 :                 if (EG(scope) &&
    1134        4607 :                     is_derived_class(fbc->common.scope, EG(scope)) &&
    1135          10 :                     fbc->op_array.fn_flags & ZEND_ACC_CHANGED) {
    1136           7 :                         if ((func = zend_hash_find(&EG(scope)->function_table, lc_method_name)) != NULL) {
    1137           7 :                                 zend_function *priv_fbc = Z_FUNC_P(func);
    1138          14 :                                 if (priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
    1139          14 :                                         && priv_fbc->common.scope == EG(scope)) {
    1140           6 :                                         fbc = priv_fbc;
    1141             :                                 }
    1142             :                         }
    1143             :                 }
    1144       22931 :                 if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
    1145             :                         /* Ensure that if we're calling a protected function, we're allowed to do so.
    1146             :                          * If we're not and __call() handler exists, invoke it, otherwise error out.
    1147             :                          */
    1148          36 :                         if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) {
    1149          13 :                                 if (zobj->ce->__call) {
    1150           6 :                                         fbc = zend_get_user_call_function(zobj->ce, method_name);
    1151             :                                 } else {
    1152          10 :                                         zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(method_name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : "");
    1153          10 :                                         fbc = NULL;
    1154             :                                 }
    1155             :                         }
    1156             :                 }
    1157             :         }
    1158             : 
    1159       23082 :         if (UNEXPECTED(!key)) {
    1160         169 :                 ZSTR_ALLOCA_FREE(lc_method_name, use_heap);
    1161             :         }
    1162       23082 :         return fbc;
    1163             : }
    1164             : /* }}} */
    1165             : 
    1166             : static zend_always_inline zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
    1167             : {
    1168          54 :         return zend_get_call_trampoline_func(ce, method_name, 1);
    1169             : }
    1170             : /* }}} */
    1171             : 
    1172        4129 : ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */
    1173             : {
    1174        4129 :         zend_function *fbc = NULL;
    1175             :         char *lc_class_name;
    1176             :         zend_string *lc_function_name;
    1177             :         zend_object *object;
    1178             : 
    1179        4129 :         if (EXPECTED(key != NULL)) {
    1180        3972 :                 lc_function_name = Z_STR_P(key);
    1181             :         } else {
    1182         157 :                 lc_function_name = zend_string_tolower(function_name);
    1183             :         }
    1184             : 
    1185        4129 :         if (ZSTR_LEN(function_name) == ZSTR_LEN(ce->name) && ce->constructor) {
    1186          52 :                 lc_class_name = zend_str_tolower_dup(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name));
    1187             :                 /* Only change the method to the constructor if the constructor isn't called __construct
    1188             :                  * we check for __ so we can be binary safe for lowering, we should use ZEND_CONSTRUCTOR_FUNC_NAME
    1189             :                  */
    1190          52 :                 if (!memcmp(lc_class_name, ZSTR_VAL(lc_function_name), ZSTR_LEN(function_name)) && memcmp(ZSTR_VAL(ce->constructor->common.function_name), "__", sizeof("__") - 1)) {
    1191           5 :                         fbc = ce->constructor;
    1192             :                 }
    1193          52 :                 efree(lc_class_name);
    1194             :         }
    1195             : 
    1196        4129 :         if (EXPECTED(!fbc)) {
    1197        4124 :                 zval *func = zend_hash_find(&ce->function_table, lc_function_name);
    1198        4124 :                 if (EXPECTED(func != NULL)) {
    1199        4011 :                         fbc = Z_FUNC_P(func);
    1200             :                 } else {
    1201         113 :                         if (UNEXPECTED(!key)) {
    1202             :                                 zend_string_release(lc_function_name);
    1203             :                         }
    1204         222 :                         if (ce->__call &&
    1205          69 :                                 (object = zend_get_this_object(EG(current_execute_data))) != NULL &&
    1206          40 :                             instanceof_function(object->ce, ce)) {
    1207             :                                 /* Call the top-level defined __call().
    1208             :                                  * see: tests/classes/__call_004.phpt  */
    1209             : 
    1210          39 :                                 zend_class_entry *call_ce = object->ce;
    1211             : 
    1212          78 :                                 while (!call_ce->__call) {
    1213           0 :                                         call_ce = call_ce->parent;
    1214             :                                 }
    1215          39 :                                 return zend_get_user_call_function(call_ce, function_name);
    1216          74 :                         } else if (ce->__callstatic) {
    1217          52 :                                 return zend_get_user_callstatic_function(ce, function_name);
    1218             :                         } else {
    1219          22 :                                 return NULL;
    1220             :                         }
    1221             :                 }
    1222             :         }
    1223             : 
    1224             : #if MBO_0
    1225             :         /* right now this function is used for non static method lookup too */
    1226             :         /* Is the function static */
    1227             :         if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) {
    1228             :                 zend_error_noreturn(E_ERROR, "Cannot call non static method %s::%s() without object", ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(fbc->common.function_name));
    1229             :         }
    1230             : #endif
    1231        4016 :         if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) {
    1232             :                 /* No further checks necessary, most common case */
    1233          44 :         } else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
    1234             :                 zend_function *updated_fbc;
    1235             : 
    1236             :                 /* Ensure that if we're calling a private function, we're allowed to do so.
    1237             :                  */
    1238          16 :                 updated_fbc = zend_check_private_int(fbc, EG(scope), lc_function_name);
    1239          16 :                 if (EXPECTED(updated_fbc != NULL)) {
    1240           9 :                         fbc = updated_fbc;
    1241             :                 } else {
    1242           7 :                         if (ce->__callstatic) {
    1243           1 :                                 fbc = zend_get_user_callstatic_function(ce, function_name);
    1244             :                         } else {
    1245           6 :                                 zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(function_name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : "");
    1246           6 :                                 fbc = NULL;
    1247             :                         }
    1248             :                 }
    1249          28 :         } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
    1250             :                 /* Ensure that if we're calling a protected function, we're allowed to do so.
    1251             :                  */
    1252          28 :                 if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) {
    1253           3 :                         if (ce->__callstatic) {
    1254           1 :                                 fbc = zend_get_user_callstatic_function(ce, function_name);
    1255             :                         } else {
    1256           2 :                                 zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(function_name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : "");
    1257           2 :                                 fbc = NULL;
    1258             :                         }
    1259             :                 }
    1260             :         }
    1261             : 
    1262        4016 :         if (UNEXPECTED(!key)) {
    1263             :                 zend_string_release(lc_function_name);
    1264             :         }
    1265             : 
    1266        4016 :         return fbc;
    1267             : }
    1268             : /* }}} */
    1269             : 
    1270         788 : ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent) /* {{{ */
    1271             : {
    1272        1576 :         zend_property_info *property_info = zend_hash_find_ptr(&ce->properties_info, property_name);
    1273             :         zval *ret;
    1274             : 
    1275         788 :         if (UNEXPECTED(property_info == NULL)) {
    1276          23 :                 goto undeclared_property;
    1277             :         }
    1278             : 
    1279         765 :         if (UNEXPECTED(!zend_verify_property_access(property_info, ce))) {
    1280          29 :                 if (!silent) {
    1281           4 :                         zend_throw_error(NULL, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ZSTR_VAL(ce->name), ZSTR_VAL(property_name));
    1282             :                 }
    1283          29 :                 return NULL;
    1284             :         }
    1285             : 
    1286         736 :         if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
    1287           0 :                 goto undeclared_property;
    1288             :         }
    1289             : 
    1290         736 :         if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
    1291          16 :                 if (UNEXPECTED(zend_update_class_constants(ce)) != SUCCESS) {
    1292           0 :                         return NULL;
    1293             :                 }
    1294             :         }
    1295         736 :         ret = CE_STATIC_MEMBERS(ce) + property_info->offset;
    1296             : 
    1297             :         /* check if static properties were destoyed */
    1298         736 :         if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
    1299             : undeclared_property:
    1300          23 :                 if (!silent) {
    1301          16 :                         zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(property_name));
    1302             :                 }
    1303          23 :                 ret = NULL;
    1304             :         }
    1305             : 
    1306         759 :         return ret;
    1307             : }
    1308             : /* }}} */
    1309             : 
    1310           1 : ZEND_API ZEND_COLD zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name) /* {{{ */
    1311             : {
    1312           1 :         zend_throw_error(NULL, "Attempt to unset static property %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(property_name));
    1313           1 :         return 0;
    1314             : }
    1315             : /* }}} */
    1316             : 
    1317      672893 : ZEND_API union _zend_function *zend_std_get_constructor(zend_object *zobj) /* {{{ */
    1318             : {
    1319      672893 :         zend_function *constructor = zobj->ce->constructor;
    1320             : 
    1321      672893 :         if (constructor) {
    1322      488028 :                 if (constructor->op_array.fn_flags & ZEND_ACC_PUBLIC) {
    1323             :                         /* No further checks necessary */
    1324          21 :                 } else if (constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
    1325             :                         /* Ensure that if we're calling a private function, we're allowed to do so.
    1326             :                          */
    1327          13 :                         if (UNEXPECTED(constructor->common.scope != EG(scope))) {
    1328           4 :                                 if (EG(scope)) {
    1329           1 :                                         zend_throw_error(NULL, "Call to private %s::%s() from context '%s'", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name), ZSTR_VAL(EG(scope)->name));
    1330           1 :                                         constructor = NULL;
    1331             :                                 } else {
    1332           3 :                                         zend_throw_error(NULL, "Call to private %s::%s() from invalid context", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name));
    1333           3 :                                         constructor = NULL;
    1334             :                                 }
    1335             :                         }
    1336           8 :                 } else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
    1337             :                         /* Ensure that if we're calling a protected function, we're allowed to do so.
    1338             :                          * Constructors only have prototype if they are defined by an interface but
    1339             :                          * it is the compilers responsibility to take care of the prototype.
    1340             :                          */
    1341           8 :                         if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(constructor), EG(scope)))) {
    1342           2 :                                 if (EG(scope)) {
    1343           1 :                                         zend_throw_error(NULL, "Call to protected %s::%s() from context '%s'", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name), ZSTR_VAL(EG(scope)->name));
    1344           1 :                                         constructor = NULL;
    1345             :                                 } else {
    1346           1 :                                         zend_throw_error(NULL, "Call to protected %s::%s() from invalid context", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name));
    1347           1 :                                         constructor = NULL;
    1348             :                                 }
    1349             :                         }
    1350             :                 }
    1351             :         }
    1352             : 
    1353      672893 :         return constructor;
    1354             : }
    1355             : /* }}} */
    1356             : 
    1357         528 : static int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
    1358             : {
    1359             :         zend_object *zobj1, *zobj2;
    1360             : 
    1361         528 :         zobj1 = Z_OBJ_P(o1);
    1362         528 :         zobj2 = Z_OBJ_P(o2);
    1363             : 
    1364         528 :         if (zobj1->ce != zobj2->ce) {
    1365          34 :                 return 1; /* different classes */
    1366             :         }
    1367         494 :         if (!zobj1->properties && !zobj2->properties) {
    1368             :                 zval *p1, *p2, *end;
    1369             : 
    1370         194 :                 if (!zobj1->ce->default_properties_count) {
    1371          20 :                         return 0;
    1372             :                 }
    1373         174 :                 p1 = zobj1->properties_table;
    1374         174 :                 p2 = zobj2->properties_table;
    1375         174 :                 end = p1 + zobj1->ce->default_properties_count;
    1376         174 :                 Z_OBJ_PROTECT_RECURSION(o1);
    1377         173 :                 Z_OBJ_PROTECT_RECURSION(o2);
    1378             :                 do {
    1379         191 :                         if (Z_TYPE_P(p1) != IS_UNDEF) {
    1380         190 :                                 if (Z_TYPE_P(p2) != IS_UNDEF) {
    1381             :                                         zval result;
    1382             : 
    1383         190 :                                         if (compare_function(&result, p1, p2)==FAILURE) {
    1384           0 :                                                 Z_OBJ_UNPROTECT_RECURSION(o1);
    1385           0 :                                                 Z_OBJ_UNPROTECT_RECURSION(o2);
    1386           0 :                                                 return 1;
    1387             :                                         }
    1388         187 :                                         if (Z_LVAL(result) != 0) {
    1389         170 :                                                 Z_OBJ_UNPROTECT_RECURSION(o1);
    1390         170 :                                                 Z_OBJ_UNPROTECT_RECURSION(o2);
    1391         170 :                                                 return Z_LVAL(result);
    1392             :                                         }
    1393             :                                 } else {
    1394           0 :                                         Z_OBJ_UNPROTECT_RECURSION(o1);
    1395           0 :                                         Z_OBJ_UNPROTECT_RECURSION(o2);
    1396           0 :                                         return 1;
    1397             :                                 }
    1398             :                         } else {
    1399           1 :                                 if (Z_TYPE_P(p2) != IS_UNDEF) {
    1400           0 :                                         Z_OBJ_UNPROTECT_RECURSION(o1);
    1401           0 :                                         Z_OBJ_UNPROTECT_RECURSION(o2);
    1402           0 :                                         return 1;
    1403             :                                 }
    1404             :                         }
    1405          18 :                         p1++;
    1406          18 :                         p2++;
    1407          18 :                 } while (p1 != end);
    1408           0 :                 Z_OBJ_UNPROTECT_RECURSION(o1);
    1409           0 :                 Z_OBJ_UNPROTECT_RECURSION(o2);
    1410           0 :                 return 0;
    1411             :         } else {
    1412         300 :                 if (!zobj1->properties) {
    1413           1 :                         rebuild_object_properties(zobj1);
    1414             :                 }
    1415         300 :                 if (!zobj2->properties) {
    1416           2 :                         rebuild_object_properties(zobj2);
    1417             :                 }
    1418         300 :                 return zend_compare_symbol_tables(zobj1->properties, zobj2->properties);
    1419             :         }
    1420             : }
    1421             : /* }}} */
    1422             : 
    1423         388 : static int zend_std_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot) /* {{{ */
    1424             : {
    1425             :         zend_object *zobj;
    1426             :         int result;
    1427         388 :         zval *value = NULL;
    1428             :         zval tmp_member;
    1429             :         uint32_t property_offset;
    1430             : 
    1431         388 :         zobj = Z_OBJ_P(object);
    1432             : 
    1433         388 :         ZVAL_UNDEF(&tmp_member);
    1434         388 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
    1435          76 :                 ZVAL_STR(&tmp_member, zval_get_string(member));
    1436          38 :                 member = &tmp_member;
    1437          38 :                 cache_slot = NULL;
    1438             :         }
    1439             : 
    1440         776 :         property_offset = zend_get_property_offset(zobj->ce, Z_STR_P(member), 1, cache_slot);
    1441             : 
    1442         388 :         if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
    1443         370 :                 if (EXPECTED(property_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
    1444         136 :                         value = OBJ_PROP(zobj, property_offset);
    1445         136 :                         if (Z_TYPE_P(value) != IS_UNDEF) {
    1446         101 :                                 goto found;
    1447             :                         }
    1448         386 :                 } else if (EXPECTED(zobj->properties != NULL) &&
    1449         152 :                            (value = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) {
    1450             : found:
    1451         197 :                         switch (has_set_exists) {
    1452             :                                 case 0:
    1453         111 :                                         ZVAL_DEREF(value);
    1454         111 :                                         result = (Z_TYPE_P(value) != IS_NULL);
    1455         111 :                                         break;
    1456             :                                 default:
    1457          60 :                                         result = zend_is_true(value);
    1458          60 :                                         break;
    1459             :                                 case 2:
    1460          26 :                                         result = 1;
    1461             :                                         break;
    1462             :                         }
    1463         197 :                         goto exit;
    1464             :                 }
    1465          18 :         } else if (UNEXPECTED(EG(exception))) {
    1466           0 :                 result = 0;
    1467           0 :                 goto exit;
    1468             :         }
    1469             : 
    1470         191 :         result = 0;
    1471         191 :         if ((has_set_exists != 2) && zobj->ce->__isset) {
    1472          39 :                 zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
    1473             : 
    1474          39 :                 if (!((*guard) & IN_ISSET)) {
    1475             :                         zval rv;
    1476             :                         zval tmp_object;
    1477             : 
    1478             :                         /* have issetter - try with it! */
    1479          28 :                         ZVAL_COPY(&tmp_object, object);
    1480          28 :                         (*guard) |= IN_ISSET; /* prevent circular getting */
    1481          28 :                         zend_std_call_issetter(&tmp_object, member, &rv);
    1482          28 :                         if (Z_TYPE(rv) != IS_UNDEF) {
    1483          28 :                                 result = zend_is_true(&rv);
    1484          28 :                                 zval_ptr_dtor(&rv);
    1485          28 :                                 if (has_set_exists && result) {
    1486           5 :                                         if (EXPECTED(!EG(exception)) && zobj->ce->__get && !((*guard) & IN_GET)) {
    1487           2 :                                                 (*guard) |= IN_GET;
    1488           2 :                                                 zend_std_call_getter(&tmp_object, member, &rv);
    1489           2 :                                                 (*guard) &= ~IN_GET;
    1490           2 :                                                 if (Z_TYPE(rv) != IS_UNDEF) {
    1491           2 :                                                         result = i_zend_is_true(&rv);
    1492           2 :                                                         zval_ptr_dtor(&rv);
    1493             :                                                 } else {
    1494           0 :                                                         result = 0;
    1495             :                                                 }
    1496             :                                         } else {
    1497           1 :                                                 result = 0;
    1498             :                                         }
    1499             :                                 }
    1500             :                         }
    1501          28 :                         (*guard) &= ~IN_ISSET;
    1502          28 :                         zval_ptr_dtor(&tmp_object);
    1503             :                 }
    1504             :         }
    1505             : 
    1506             : exit:
    1507         388 :         if (UNEXPECTED(Z_REFCOUNTED(tmp_member))) {
    1508          34 :                 zval_ptr_dtor(&tmp_member);
    1509             :         }
    1510         388 :         return result;
    1511             : }
    1512             : /* }}} */
    1513             : 
    1514        4280 : zend_string *zend_std_object_get_class_name(const zend_object *zobj) /* {{{ */
    1515             : {
    1516        8560 :         return zend_string_copy(zobj->ce->name);
    1517             : }
    1518             : /* }}} */
    1519             : 
    1520      467206 : ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type) /* {{{ */
    1521             : {
    1522             :         zval retval;
    1523             :         zend_class_entry *ce;
    1524             : 
    1525      467206 :         switch (type) {
    1526             :                 case IS_STRING:
    1527      304309 :                         ce = Z_OBJCE_P(readobj);
    1528      608218 :                         if (ce->__tostring &&
    1529      303909 :                                 (zend_call_method_with_0_params(readobj, ce, &ce->__tostring, "__tostring", &retval) || EG(exception))) {
    1530      303909 :                                 if (UNEXPECTED(EG(exception) != NULL)) {
    1531             :                                         zval *msg, ex, rv;
    1532           5 :                                         zval_ptr_dtor(&retval);
    1533           5 :                                         ZVAL_OBJ(&ex, EG(exception));
    1534           5 :                                         EG(exception) = NULL;
    1535           5 :                                         msg = zend_read_property(Z_OBJCE(ex), &ex, "message", sizeof("message") - 1, 1, &rv);
    1536           5 :                                         if (UNEXPECTED(Z_TYPE_P(msg) != IS_STRING)) {
    1537           0 :                                                 ZVAL_EMPTY_STRING(&rv);
    1538           0 :                                                 msg = &rv;
    1539             :                                         }
    1540          15 :                                         zend_error_noreturn(E_ERROR,
    1541             :                                                         "Method %s::__toString() must not throw an exception, caught %s: %s",
    1542          15 :                                                         ZSTR_VAL(ce->name), ZSTR_VAL(Z_OBJCE(ex)->name), Z_STRVAL_P(msg));
    1543             :                                         return FAILURE;
    1544             :                                 }
    1545      303904 :                                 if (EXPECTED(Z_TYPE(retval) == IS_STRING)) {
    1546      303900 :                                         if (readobj == writeobj) {
    1547           0 :                                                 zval_ptr_dtor(readobj);
    1548             :                                         }
    1549      303900 :                                         ZVAL_COPY_VALUE(writeobj, &retval);
    1550      303900 :                                         return SUCCESS;
    1551             :                                 } else {
    1552           4 :                                         zval_ptr_dtor(&retval);
    1553           4 :                                         if (readobj == writeobj) {
    1554           0 :                                                 zval_ptr_dtor(readobj);
    1555             :                                         }
    1556           4 :                                         ZVAL_EMPTY_STRING(writeobj);
    1557           4 :                                         zend_error(E_RECOVERABLE_ERROR, "Method %s::__toString() must return a string value", ZSTR_VAL(ce->name));
    1558           4 :                                         return SUCCESS;
    1559             :                                 }
    1560             :                         }
    1561         400 :                         return FAILURE;
    1562             :                 case _IS_BOOL:
    1563      162652 :                         ZVAL_BOOL(writeobj, 1);
    1564      162652 :                         return SUCCESS;
    1565             :                 case IS_LONG:
    1566         137 :                         ce = Z_OBJCE_P(readobj);
    1567         137 :                         zend_error(E_NOTICE, "Object of class %s could not be converted to int", ZSTR_VAL(ce->name));
    1568         137 :                         if (readobj == writeobj) {
    1569             :                                 zval_dtor(readobj);
    1570             :                         }
    1571         137 :                         ZVAL_LONG(writeobj, 1);
    1572         137 :                         return SUCCESS;
    1573             :                 case IS_DOUBLE:
    1574          43 :                         ce = Z_OBJCE_P(readobj);
    1575          43 :                         zend_error(E_NOTICE, "Object of class %s could not be converted to float", ZSTR_VAL(ce->name));
    1576          43 :                         if (readobj == writeobj) {
    1577             :                                 zval_dtor(readobj);
    1578             :                         }
    1579          43 :                         ZVAL_DOUBLE(writeobj, 1);
    1580          43 :                         return SUCCESS;
    1581             :                 default:
    1582          65 :                         ZVAL_NULL(writeobj);
    1583             :                         break;
    1584             :         }
    1585          65 :         return FAILURE;
    1586             : }
    1587             : /* }}} */
    1588             : 
    1589          77 : int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */
    1590             : {
    1591             :         zval *func;
    1592             :         zend_class_entry *ce;
    1593             : 
    1594          77 :         if (Z_TYPE_P(obj) != IS_OBJECT) {
    1595           0 :                 return FAILURE;
    1596             :         }
    1597             : 
    1598          77 :         ce = Z_OBJCE_P(obj);
    1599             : 
    1600          77 :         if ((func = zend_hash_str_find(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1)) == NULL) {
    1601          50 :                 return FAILURE;
    1602             :         }
    1603          27 :         *fptr_ptr = Z_FUNC_P(func);
    1604             : 
    1605          27 :         *ce_ptr = ce;
    1606          27 :         if ((*fptr_ptr)->common.fn_flags & ZEND_ACC_STATIC) {
    1607           1 :                 if (obj_ptr) {
    1608           1 :                         *obj_ptr = NULL;
    1609             :                 }
    1610             :         } else {
    1611          26 :                 if (obj_ptr) {
    1612          26 :                         *obj_ptr = Z_OBJ_P(obj);
    1613             :                 }
    1614             :         }
    1615          27 :         return SUCCESS;
    1616             : }
    1617             : /* }}} */
    1618             : 
    1619             : ZEND_API zend_object_handlers std_object_handlers = {
    1620             :         0,                                                                              /* offset */
    1621             : 
    1622             :         zend_object_std_dtor,                                   /* free_obj */
    1623             :         zend_objects_destroy_object,                    /* dtor_obj */
    1624             :         zend_objects_clone_obj,                                 /* clone_obj */
    1625             : 
    1626             :         zend_std_read_property,                                 /* read_property */
    1627             :         zend_std_write_property,                                /* write_property */
    1628             :         zend_std_read_dimension,                                /* read_dimension */
    1629             :         zend_std_write_dimension,                               /* write_dimension */
    1630             :         zend_std_get_property_ptr_ptr,                  /* get_property_ptr_ptr */
    1631             :         NULL,                                                                   /* get */
    1632             :         NULL,                                                                   /* set */
    1633             :         zend_std_has_property,                                  /* has_property */
    1634             :         zend_std_unset_property,                                /* unset_property */
    1635             :         zend_std_has_dimension,                                 /* has_dimension */
    1636             :         zend_std_unset_dimension,                               /* unset_dimension */
    1637             :         zend_std_get_properties,                                /* get_properties */
    1638             :         zend_std_get_method,                                    /* get_method */
    1639             :         NULL,                                                                   /* call_method */
    1640             :         zend_std_get_constructor,                               /* get_constructor */
    1641             :         zend_std_object_get_class_name,                 /* get_class_name */
    1642             :         zend_std_compare_objects,                               /* compare_objects */
    1643             :         zend_std_cast_object_tostring,                  /* cast_object */
    1644             :         NULL,                                                                   /* count_elements */
    1645             :         zend_std_get_debug_info,                                /* get_debug_info */
    1646             :         zend_std_get_closure,                                   /* get_closure */
    1647             :         zend_std_get_gc,                                                /* get_gc */
    1648             :         NULL,                                                                   /* do_operation */
    1649             :         NULL,                                                                   /* compare */
    1650             : };
    1651             : 
    1652             : /*
    1653             :  * Local variables:
    1654             :  * tab-width: 4
    1655             :  * c-basic-offset: 4
    1656             :  * indent-tabs-mode: t
    1657             :  * End:
    1658             :  */

Generated by: LCOV version 1.10

Generated at Sun, 29 May 2016 00:48:18 +0000 (22 hours ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.