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: 717 773 92.8 %
Date: 2015-09-02 Functions: 34 34 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 02 Sep 2015 17:19:05 +0000 (25 hours ago)

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