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: 777 836 92.9 %
Date: 2014-08-04 Functions: 36 37 97.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 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             :    +----------------------------------------------------------------------+
      18             : */
      19             : 
      20             : /* $Id$ */
      21             : 
      22             : #include "zend.h"
      23             : #include "zend_globals.h"
      24             : #include "zend_variables.h"
      25             : #include "zend_API.h"
      26             : #include "zend_objects.h"
      27             : #include "zend_objects_API.h"
      28             : #include "zend_object_handlers.h"
      29             : #include "zend_interfaces.h"
      30             : #include "zend_closures.h"
      31             : #include "zend_compile.h"
      32             : #include "zend_hash.h"
      33             : 
      34             : #define DEBUG_OBJECT_HANDLERS 0
      35             : 
      36             : #define Z_OBJ_P(zval_p) \
      37             :         ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].bucket.obj.object))
      38             : 
      39             : #define Z_OBJ_PROTECT_RECURSION(zval_p) \
      40             :         do { \
      41             :                 if (EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count++ >= 3) { \
      42             :                         zend_error(E_ERROR, "Nesting level too deep - recursive dependency?"); \
      43             :                 } \
      44             :         } while (0)
      45             : 
      46             : 
      47             : #define Z_OBJ_UNPROTECT_RECURSION(zval_p) \
      48             :         EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count--
      49             : 
      50             : /*
      51             :   __X accessors explanation:
      52             : 
      53             :   if we have __get and property that is not part of the properties array is
      54             :   requested, we call __get handler. If it fails, we return uninitialized.
      55             : 
      56             :   if we have __set and property that is not part of the properties array is
      57             :   set, we call __set handler. If it fails, we do not change the array.
      58             : 
      59             :   for both handlers above, when we are inside __get/__set, no further calls for
      60             :   __get/__set for this property of this object will be made, to prevent endless
      61             :   recursion and enable accessors to change properties array.
      62             : 
      63             :   if we have __call and method which is not part of the class function table is
      64             :   called, we cal __call handler.
      65             : */
      66             : 
      67      608880 : ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
      68             : {
      69      608880 :         if (!zobj->properties) {
      70             :                 HashPosition pos;
      71             :                 zend_property_info *prop_info;
      72      608880 :                 zend_class_entry *ce = zobj->ce;
      73             : 
      74      608880 :                 ALLOC_HASHTABLE(zobj->properties);
      75      608880 :                 zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
      76      608880 :                 if (ce->default_properties_count) {
      77       42162 :                         for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
      78       29904 :                              zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
      79       17646 :                              zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
      80       52884 :                                 if (/*prop_info->ce == ce &&*/
      81       17646 :                                     (prop_info->flags & ZEND_ACC_STATIC) == 0 &&
      82       17619 :                                     prop_info->offset >= 0 &&
      83       17619 :                                     zobj->properties_table[prop_info->offset]) {
      84       17607 :                                         zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
      85             :                                 }
      86             :                         }
      87       25534 :                         while (ce->parent && ce->parent->default_properties_count) {
      88        1018 :                                 ce = ce->parent;
      89        6481 :                                 for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
      90        5463 :                                      zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
      91        4445 :                                      zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
      92       15880 :                                         if (prop_info->ce == ce &&
      93        4211 :                                             (prop_info->flags & ZEND_ACC_STATIC) == 0 &&
      94        4200 :                                             (prop_info->flags & ZEND_ACC_PRIVATE) != 0 &&
      95        1512 :                                             prop_info->offset >= 0 &&
      96        1512 :                                                 zobj->properties_table[prop_info->offset]) {
      97        1510 :                                                 zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
      98             :                                         }
      99             :                                 }
     100             :                         }
     101             :                 }
     102             :         }
     103      608880 : }
     104             : /* }}} */
     105             : 
     106      466829 : ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) /* {{{ */
     107             : {
     108             :         zend_object *zobj;
     109      466829 :         zobj = Z_OBJ_P(object);
     110      466829 :         if (!zobj->properties) {
     111      200770 :                 rebuild_object_properties(zobj);
     112             :         }
     113      466829 :         return zobj->properties;
     114             : }
     115             : /* }}} */
     116             : 
     117      530216 : ZEND_API HashTable *zend_std_get_gc(zval *object, zval ***table, int *n TSRMLS_DC) /* {{{ */
     118             : {
     119      530216 :         if (Z_OBJ_HANDLER_P(object, get_properties) != zend_std_get_properties) {
     120           3 :                 *table = NULL;
     121           3 :                 *n = 0;
     122           3 :                 return Z_OBJ_HANDLER_P(object, get_properties)(object TSRMLS_CC);
     123             :         } else {
     124      530213 :                 zend_object *zobj = Z_OBJ_P(object);
     125             : 
     126      530213 :                 if (zobj->properties) {
     127      250040 :                         *table = NULL;
     128      250040 :                         *n = 0;
     129      250040 :                         return zobj->properties;
     130             :                 } else {
     131      280173 :                         *table = zobj->properties_table;
     132      280173 :                         *n = zobj->ce->default_properties_count;
     133      280173 :                         return NULL;
     134             :                 }
     135             :         }
     136             : }
     137             : /* }}} */
     138             : 
     139        3569 : ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
     140             : {
     141        3569 :         zend_class_entry *ce = Z_OBJCE_P(object);
     142        3569 :         zval *retval = NULL;
     143             : 
     144        3569 :         if (!ce->__debugInfo) {
     145        3557 :                 *is_temp = 0;
     146        7114 :                 return Z_OBJ_HANDLER_P(object, get_properties)
     147        3557 :                         ? Z_OBJ_HANDLER_P(object, get_properties)(object TSRMLS_CC)
     148             :                         : NULL;
     149             :         }
     150             : 
     151          12 :         zend_call_method_with_0_params(&object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval);
     152          12 :         if (retval && Z_TYPE_P(retval) == IS_ARRAY) {
     153           1 :                 HashTable *ht = Z_ARRVAL_P(retval);
     154           2 :                 if (Z_REFCOUNT_P(retval) <= 1) {
     155           1 :                         *is_temp = 1;
     156           1 :                         efree(retval);
     157           1 :                         return ht;
     158             :                 } else {
     159           0 :                         *is_temp = 0;
     160           0 :                         zval_ptr_dtor(&retval);
     161             :                 }
     162           0 :                 return ht;
     163             :         }
     164          11 :         if (retval && Z_TYPE_P(retval) == IS_NULL) {
     165             :                 zval ret;
     166           1 :                 array_init(&ret);
     167           1 :                 *is_temp = 1;
     168           1 :                 zval_ptr_dtor(&retval);
     169           1 :                 return Z_ARRVAL(ret);
     170             :         }
     171             : 
     172          10 :         zend_error_noreturn(E_ERROR, ZEND_DEBUGINFO_FUNC_NAME "() must return an array");
     173             : 
     174             :         return NULL; /* Compilers are dumb and don't understand that noreturn means that the function does NOT need a return value... */
     175             : }
     176             : /* }}} */
     177             : 
     178         135 : static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) /* {{{ */
     179             : {
     180         135 :         zval *retval = NULL;
     181         135 :         zend_class_entry *ce = Z_OBJCE_P(object);
     182             : 
     183             :         /* __get handler is called with one argument:
     184             :               property name
     185             : 
     186             :            it should return whether the call was successfull or not
     187             :         */
     188             : 
     189         524 :         SEPARATE_ARG_IF_REF(member);
     190             : 
     191         135 :         zend_call_method_with_1_params(&object, ce, &ce->__get, ZEND_GET_FUNC_NAME, &retval, member);
     192             : 
     193         134 :         zval_ptr_dtor(&member);
     194             : 
     195         134 :         if (retval) {
     196         132 :                 Z_DELREF_P(retval);
     197             :         }
     198             : 
     199         134 :         return retval;
     200             : }
     201             : /* }}} */
     202             : 
     203          98 : static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */
     204             : {
     205          98 :         zval *retval = NULL;
     206             :         int result;
     207          98 :         zend_class_entry *ce = Z_OBJCE_P(object);
     208             : 
     209         364 :         SEPARATE_ARG_IF_REF(member);
     210          98 :         Z_ADDREF_P(value);
     211             : 
     212             :         /* __set handler is called with two arguments:
     213             :              property name
     214             :              value to be set
     215             : 
     216             :            it should return whether the call was successfull or not
     217             :         */
     218          98 :         zend_call_method_with_2_params(&object, ce, &ce->__set, ZEND_SET_FUNC_NAME, &retval, member, value);
     219             : 
     220          97 :         zval_ptr_dtor(&member);
     221          97 :         zval_ptr_dtor(&value);
     222             : 
     223          97 :         if (retval) {
     224         192 :                 result = i_zend_is_true(retval TSRMLS_CC) ? SUCCESS : FAILURE;
     225          96 :                 zval_ptr_dtor(&retval);
     226          96 :                 return result;
     227             :         } else {
     228           1 :                 return FAILURE;
     229             :         }
     230             : }
     231             : /* }}} */
     232             : 
     233           8 : static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{ */
     234             : {
     235           8 :         zend_class_entry *ce = Z_OBJCE_P(object);
     236             : 
     237             :         /* __unset handler is called with one argument:
     238             :               property name
     239             :         */
     240             : 
     241          29 :         SEPARATE_ARG_IF_REF(member);
     242             : 
     243           8 :         zend_call_method_with_1_params(&object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
     244             : 
     245           7 :         zval_ptr_dtor(&member);
     246           7 : }
     247             : /* }}} */
     248             : 
     249          20 : static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) /* {{{ */
     250             : {
     251          20 :         zval *retval = NULL;
     252          20 :         zend_class_entry *ce = Z_OBJCE_P(object);
     253             : 
     254             :         /* __isset handler is called with one argument:
     255             :               property name
     256             : 
     257             :            it should return whether the property is set or not
     258             :         */
     259             : 
     260          80 :         SEPARATE_ARG_IF_REF(member);
     261             : 
     262          20 :         zend_call_method_with_1_params(&object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, &retval, member);
     263             : 
     264          20 :         zval_ptr_dtor(&member);
     265             : 
     266          20 :         return retval;
     267             : }
     268             : /* }}} */
     269             : 
     270             : static zend_always_inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) /* {{{ */
     271             : {
     272       18711 :         switch (property_info->flags & ZEND_ACC_PPP_MASK) {
     273             :                 case ZEND_ACC_PUBLIC:
     274        9235 :                         return 1;
     275             :                 case ZEND_ACC_PROTECTED:
     276        7324 :                         return zend_check_protected(property_info->ce, EG(scope));
     277             :                 case ZEND_ACC_PRIVATE:
     278        2152 :                         if ((ce==EG(scope) || property_info->ce == EG(scope)) && EG(scope)) {
     279        2030 :                                 return 1;
     280             :                         } else {
     281         122 :                                 return 0;
     282             :                         }
     283             :                         break;
     284             :         }
     285           0 :         return 0;
     286             : }
     287             : /* }}} */
     288             : 
     289             : static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */
     290             : {
     291        7181 :         child_class = child_class->parent;
     292        8462 :         while (child_class) {
     293        3119 :                 if (child_class == parent_class) {
     294        1838 :                         return 1;
     295             :                 }
     296        1281 :                 child_class = child_class->parent;
     297             :         }
     298             : 
     299        5343 :         return 0;
     300             : }
     301             : /* }}} */
     302             : 
     303             : static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent, const zend_literal *key TSRMLS_DC) /* {{{ */
     304             : {
     305             :         zend_property_info *property_info;
     306             :         zend_property_info *scope_property_info;
     307      761323 :         zend_bool denied_access = 0;
     308             :         ulong h;
     309             : 
     310      761323 :         if (key && (property_info = CACHED_POLYMORPHIC_PTR(key->cache_slot, ce)) != NULL) {
     311      300315 :                 return property_info;
     312             :         }
     313             : 
     314      461008 :         if (UNEXPECTED(Z_STRVAL_P(member)[0] == '\0')) {
     315          17 :                 if (!silent) {
     316           1 :                         if (Z_STRLEN_P(member) == 0) {
     317           1 :                                 zend_error_noreturn(E_ERROR, "Cannot access empty property");
     318             :                         } else {
     319           0 :                                 zend_error_noreturn(E_ERROR, "Cannot access property started with '\\0'");
     320             :                         }
     321             :                 }
     322          16 :                 return NULL;
     323             :         }
     324      460991 :         property_info = NULL;
     325      460991 :         h = key ? key->hash_value : zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
     326      460991 :         if (zend_hash_quick_find(&ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) {
     327       19191 :                 if (UNEXPECTED((property_info->flags & ZEND_ACC_SHADOW) != 0)) {
     328             :                         /* if it's a shadow - go to access it's private */
     329        1665 :                         property_info = NULL;
     330             :                 } else {
     331       35052 :                         if (EXPECTED(zend_verify_property_access(property_info, ce TSRMLS_CC) != 0)) {
     332       34801 :                                 if (EXPECTED((property_info->flags & ZEND_ACC_CHANGED) != 0)
     333       17426 :                                         && EXPECTED(!(property_info->flags & ZEND_ACC_PRIVATE))) {
     334             :                                         /* We still need to make sure that we're not in a context
     335             :                                          * where the right property is a different 'statically linked' private
     336             :                                          * continue checking below...
     337             :                                          */
     338             :                                 } else {
     339       17354 :                                         if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0) && !silent) {
     340          12 :                                                 zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name, Z_STRVAL_P(member));
     341             :                                         }
     342       17354 :                                         if (key) {
     343        2487 :                                                 CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
     344             :                                         }
     345       17354 :                                         return property_info;
     346             :                                 }
     347             :                         } else {
     348             :                                 /* Try to look in the scope instead */
     349         151 :                                 denied_access = 1;
     350             :                         }
     351             :                 }
     352             :         }
     353      879273 :         if (EG(scope) != ce
     354      429400 :                 && EG(scope)
     355             :                 && is_derived_class(ce, EG(scope))
     356        6411 :                 && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
     357        7137 :                 && scope_property_info->flags & ZEND_ACC_PRIVATE) {
     358        1647 :                 if (key) {
     359          61 :                         CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, scope_property_info);
     360             :                 }
     361        1647 :                 return scope_property_info;
     362      441990 :         } else if (property_info) {
     363         143 :                 if (UNEXPECTED(denied_access != 0)) {
     364             :                         /* Information was available, but we were denied access.  Error out. */
     365         133 :                         if (!silent) {
     366          18 :                                 zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member));
     367             :                         }
     368         115 :                         return NULL;
     369             :                 } else {
     370             :                         /* fall through, return property_info... */
     371          10 :                         if (key) {
     372          10 :                                 CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
     373             :                         }
     374             :                 }
     375             :         } else {
     376      441847 :                 EG(std_property_info).flags = ZEND_ACC_PUBLIC;
     377      441847 :                 EG(std_property_info).name = Z_STRVAL_P(member);
     378      441847 :                 EG(std_property_info).name_length = Z_STRLEN_P(member);
     379      441847 :                 EG(std_property_info).h = h;
     380      441847 :                 EG(std_property_info).ce = ce;
     381      441847 :                 EG(std_property_info).offset = -1;
     382      441847 :                 property_info = &EG(std_property_info);
     383             :         }
     384      441857 :         return property_info;
     385             : }
     386             : /* }}} */
     387             : 
     388         151 : ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) /* {{{ */
     389             : {
     390         151 :         return zend_get_property_info_quick(ce, member, silent, NULL TSRMLS_CC);
     391             : }
     392             : /* }}} */
     393             : 
     394         637 : ZEND_API int zend_check_property_access(zend_object *zobj, const char *prop_info_name, int prop_info_name_len TSRMLS_DC) /* {{{ */
     395             : {
     396             :         zend_property_info *property_info;
     397             :         const char *class_name, *prop_name;
     398             :         zval member;
     399             :         int prop_name_len;
     400             : 
     401         637 :         zend_unmangle_property_name_ex(prop_info_name, prop_info_name_len, &class_name, &prop_name, &prop_name_len);
     402         637 :         ZVAL_STRINGL(&member, prop_name, prop_name_len, 0);
     403        1274 :         property_info = zend_get_property_info_quick(zobj->ce, &member, 1, NULL TSRMLS_CC);
     404         637 :         if (!property_info) {
     405          73 :                 return FAILURE;
     406             :         }
     407         564 :         if (class_name && class_name[0] != '*') {
     408          87 :                 if (!(property_info->flags & ZEND_ACC_PRIVATE)) {
     409             :                         /* we we're looking for a private prop but found a non private one of the same name */
     410          18 :                         return FAILURE;
     411          69 :                 } else if (strcmp(prop_info_name+1, property_info->name+1)) {
     412             :                         /* we we're looking for a private prop but found a private one of the same name but another class */
     413          11 :                         return FAILURE;
     414             :                 }
     415             :         }
     416        1070 :         return zend_verify_property_access(property_info, zobj->ce TSRMLS_CC) ? SUCCESS : FAILURE;
     417             : }
     418             : /* }}} */
     419             : 
     420         341 : static int zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member, zend_guard **pguard) /* {{{ */
     421             : {
     422             :         zend_property_info info;
     423             :         zend_guard stub;
     424             : 
     425         341 :         if (!property_info) {
     426          50 :                 property_info = &info;
     427          50 :                 info.name = Z_STRVAL_P(member);
     428          50 :                 info.name_length = Z_STRLEN_P(member);
     429          50 :                 info.h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
     430         291 :         } else if(property_info->name[0] == '\0'){
     431          20 :                 const char *class_name = NULL, *prop_name = NULL;
     432          20 :                 zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name);
     433          20 :                 if(class_name) {
     434             :                         /* use unmangled name for protected properties */
     435          20 :                         info.name = prop_name;
     436          20 :                         info.name_length = strlen(prop_name);
     437          20 :                         info.h = zend_get_hash_value(info.name, info.name_length+1);
     438          20 :                         property_info = &info;
     439             :                 }
     440             :         }
     441         341 :         if (!zobj->guards) {
     442          69 :                 ALLOC_HASHTABLE(zobj->guards);
     443          69 :                 zend_hash_init(zobj->guards, 0, NULL, NULL, 0);
     444         272 :         } else if (zend_hash_quick_find(zobj->guards, property_info->name, property_info->name_length+1, property_info->h, (void **) pguard) == SUCCESS) {
     445         221 :                 return SUCCESS;
     446             :         }
     447         120 :         stub.in_get = 0;
     448         120 :         stub.in_set = 0;
     449         120 :         stub.in_unset = 0;
     450         120 :         stub.in_isset = 0;
     451         120 :         return zend_hash_quick_add(zobj->guards, property_info->name, property_info->name_length+1, property_info->h, (void**)&stub, sizeof(stub), (void**) pguard);
     452             : }
     453             : /* }}} */
     454             : 
     455       36870 : zval *zend_std_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
     456             : {
     457             :         zend_object *zobj;
     458       36870 :         zval *tmp_member = NULL;
     459             :         zval **retval;
     460       36870 :         zval *rv = NULL;
     461             :         zend_property_info *property_info;
     462             :         int silent;
     463             : 
     464       36870 :         silent = (type == BP_VAR_IS);
     465       36870 :         zobj = Z_OBJ_P(object);
     466             : 
     467       36870 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     468           7 :                 ALLOC_ZVAL(tmp_member);
     469           7 :                 *tmp_member = *member;
     470           7 :                 INIT_PZVAL(tmp_member);
     471           7 :                 zval_copy_ctor(tmp_member);
     472           7 :                 convert_to_string(tmp_member);
     473           7 :                 member = tmp_member;
     474           7 :                 key = NULL;
     475             :         }
     476             : 
     477             : #if DEBUG_OBJECT_HANDLERS
     478             :         fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
     479             : #endif
     480             : 
     481             :         /* make zend_get_property_info silent if we have getter - we may want to use it */
     482       73736 :         property_info = zend_get_property_info_quick(zobj->ce, member, silent || (zobj->ce->__get != NULL), key TSRMLS_CC);
     483             : 
     484      215386 :         if (UNEXPECTED(!property_info) ||
     485       36846 :             ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
     486       36840 :              property_info->offset >= 0) ?
     487       33994 :                 (zobj->properties ?
     488       20330 :                     ((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
     489       47658 :                     (*(retval = &zobj->properties_table[property_info->offset]) == NULL)) :
     490        5454 :                 (UNEXPECTED(!zobj->properties) ||
     491        2602 :                   UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) {
     492         401 :                 zend_guard *guard = NULL;
     493             : 
     494         822 :                 if (zobj->ce->__get &&
     495         144 :                     zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
     496         144 :                     !guard->in_get) {
     497             :                         /* have getter - try with it! */
     498         134 :                         Z_ADDREF_P(object);
     499         268 :                         if (PZVAL_IS_REF(object)) {
     500           4 :                                 SEPARATE_ZVAL(&object);
     501             :                         }
     502         134 :                         guard->in_get = 1; /* prevent circular getting */
     503         134 :                         rv = zend_std_call_getter(object, member TSRMLS_CC);
     504         133 :                         guard->in_get = 0;
     505             : 
     506         133 :                         if (rv) {
     507         131 :                                 retval = &rv;
     508         262 :                                 if (!Z_ISREF_P(rv) &&
     509             :                                     (type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET)) {
     510          38 :                                         if (Z_REFCOUNT_P(rv) > 0) {
     511          10 :                                                 zval *tmp = rv;
     512             : 
     513          10 :                                                 ALLOC_ZVAL(rv);
     514          10 :                                                 *rv = *tmp;
     515          10 :                                                 zval_copy_ctor(rv);
     516          10 :                                                 Z_UNSET_ISREF_P(rv);
     517          10 :                                                 Z_SET_REFCOUNT_P(rv, 0);
     518             :                                         }
     519          19 :                                         if (UNEXPECTED(Z_TYPE_P(rv) != IS_OBJECT)) {
     520          13 :                                                 zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", zobj->ce->name, Z_STRVAL_P(member));
     521             :                                         }
     522             :                                 }
     523             :                         } else {
     524           2 :                                 retval = &EG(uninitialized_zval_ptr);
     525             :                         }
     526         133 :                         if (EXPECTED(*retval != object)) {
     527         132 :                                 zval_ptr_dtor(&object);
     528             :                         } else {
     529           1 :                                 Z_DELREF_P(object);
     530             :                         }
     531             :                 } else {
     532         267 :                         if (zobj->ce->__get && guard && guard->in_get == 1) {
     533          10 :                                 if (Z_STRVAL_P(member)[0] == '\0') {
     534           1 :                                         if (Z_STRLEN_P(member) == 0) {
     535           1 :                                                 zend_error(E_ERROR, "Cannot access empty property");
     536             :                                         } else {
     537           0 :                                                 zend_error(E_ERROR, "Cannot access property started with '\\0'");
     538             :                                         }
     539             :                                 }
     540             :                         }
     541         266 :                         if (!silent) {
     542          51 :                                 zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
     543             :                         }
     544         266 :                         retval = &EG(uninitialized_zval_ptr);
     545             :                 }
     546             :         }
     547       36864 :         if (UNEXPECTED(tmp_member != NULL)) {
     548           6 :                 Z_ADDREF_PP(retval);
     549           6 :                 zval_ptr_dtor(&tmp_member);
     550           6 :                 Z_DELREF_PP(retval);
     551             :         }
     552       36864 :         return *retval;
     553             : }
     554             : /* }}} */
     555             : 
     556      543430 : ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
     557             : {
     558             :         zend_object *zobj;
     559      543430 :         zval *tmp_member = NULL;
     560             :         zval **variable_ptr;
     561             :         zend_property_info *property_info;
     562             : 
     563      543430 :         zobj = Z_OBJ_P(object);
     564             : 
     565      543430 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     566           7 :                 ALLOC_ZVAL(tmp_member);
     567           7 :                 *tmp_member = *member;
     568           7 :                 INIT_PZVAL(tmp_member);
     569           7 :                 zval_copy_ctor(tmp_member);
     570           7 :                 convert_to_string(tmp_member);
     571           7 :                 member = tmp_member;
     572           7 :                 key = NULL;
     573             :         }
     574             : 
     575     1086849 :         property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__set != NULL), key TSRMLS_CC);
     576             : 
     577     2489320 :         if (EXPECTED(property_info != NULL) &&
     578      543402 :             ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
     579      543393 :              property_info->offset >= 0) ?
     580      105162 :                 (zobj->properties ?
     581        5824 :                     ((variable_ptr = (zval**)zobj->properties_table[property_info->offset]) != NULL) :
     582      204500 :                     (*(variable_ptr = &zobj->properties_table[property_info->offset]) != NULL)) :
     583      469913 :                 (EXPECTED(zobj->properties != NULL) &&
     584       31673 :                   EXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS)))) {
     585             :                 /* if we already have this value there, we don't actually need to do anything */
     586      105380 :                 if (EXPECTED(*variable_ptr != value)) {
     587             :                         /* if we are assigning reference, we shouldn't move it, but instead assign variable
     588             :                            to the same pointer */
     589      210742 :                         if (PZVAL_IS_REF(*variable_ptr)) {
     590          42 :                                 zval garbage = **variable_ptr; /* old value should be destroyed */
     591             : 
     592             :                                 /* To check: can't *variable_ptr be some system variable like error_zval here? */
     593          42 :                                 Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value);
     594          42 :                                 (*variable_ptr)->value = value->value;
     595          84 :                                 if (Z_REFCOUNT_P(value) > 0) {
     596          42 :                                         zval_copy_ctor(*variable_ptr);
     597             :                                 } else {
     598           0 :                                         efree(value);
     599             :                                 }
     600             :                                 zval_dtor(&garbage);
     601             :                         } else {
     602      105329 :                                 zval *garbage = *variable_ptr;
     603             : 
     604             :                                 /* if we assign referenced variable, we should separate it */
     605      105329 :                                 Z_ADDREF_P(value);
     606      210658 :                                 if (PZVAL_IS_REF(value)) {
     607          28 :                                         SEPARATE_ZVAL(&value);
     608             :                                 }
     609      105329 :                                 *variable_ptr = value;
     610      105329 :                                 zval_ptr_dtor(&garbage);
     611             :                         }
     612             :                 }
     613             :         } else {
     614      438039 :                 zend_guard *guard = NULL;
     615             : 
     616      438374 :                 if (zobj->ce->__set &&
     617         119 :                     zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
     618         119 :                     !guard->in_set) {
     619          98 :                         Z_ADDREF_P(object);
     620         196 :                         if (PZVAL_IS_REF(object)) {
     621           4 :                                 SEPARATE_ZVAL(&object);
     622             :                         }
     623          98 :                         guard->in_set = 1; /* prevent circular setting */
     624          98 :                         if (zend_std_call_setter(object, member, value TSRMLS_CC) != SUCCESS) {
     625             :                                 /* for now, just ignore it - __set should take care of warnings, etc. */
     626             :                         }
     627          97 :                         guard->in_set = 0;
     628          97 :                         zval_ptr_dtor(&object);
     629      437941 :                 } else if (EXPECTED(property_info != NULL)) {
     630             :                         /* if we assign referenced variable, we should separate it */
     631      437939 :                         Z_ADDREF_P(value);
     632      875878 :                         if (PZVAL_IS_REF(value)) {
     633       40034 :                                 SEPARATE_ZVAL(&value);
     634             :                         }
     635      875887 :                         if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
     636      437934 :                             property_info->offset >= 0) {
     637          14 :                                         if (!zobj->properties) {
     638           8 :                                                 zobj->properties_table[property_info->offset] = value;
     639           6 :                                         } else if (zobj->properties_table[property_info->offset]) {
     640           0 :                                                 *(zval**)zobj->properties_table[property_info->offset] = value;
     641             :                                         } else {
     642           6 :                                                 zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]);
     643             :                                         }
     644             :                                 } else {
     645      437925 :                                         if (!zobj->properties) {
     646      406493 :                                         rebuild_object_properties(zobj);
     647             :                                 }
     648      437925 :                                 zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), NULL);
     649             :                         }
     650           2 :                 } else if (zobj->ce->__set && guard && guard->in_set == 1) {
     651           2 :                         if (Z_STRVAL_P(member)[0] == '\0') {
     652           1 :                                 if (Z_STRLEN_P(member) == 0) {
     653           1 :                                         zend_error(E_ERROR, "Cannot access empty property");
     654             :                                 } else {
     655           0 :                                         zend_error(E_ERROR, "Cannot access property started with '\\0'");
     656             :                                 }
     657             :                         }
     658             :                 }
     659             :         }
     660             : 
     661      543417 :         if (UNEXPECTED(tmp_member != NULL)) {
     662           6 :                 zval_ptr_dtor(&tmp_member);
     663             :         }
     664      543417 : }
     665             : /* }}} */
     666             : 
     667         482 : zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
     668             : {
     669         482 :         zend_class_entry *ce = Z_OBJCE_P(object);
     670             :         zval *retval;
     671             : 
     672         482 :         if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC) != 0)) {
     673         478 :                 if(offset == NULL) {
     674             :                         /* [] construct */
     675           0 :                         ALLOC_INIT_ZVAL(offset);
     676             :                 } else {
     677        1852 :                         SEPARATE_ARG_IF_REF(offset);
     678             :                 }
     679         478 :                 zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);
     680             : 
     681         478 :                 zval_ptr_dtor(&offset);
     682             : 
     683         478 :                 if (UNEXPECTED(!retval)) {
     684           5 :                         if (UNEXPECTED(!EG(exception))) {
     685           0 :                                 zend_error_noreturn(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
     686             :                         }
     687           5 :                         return 0;
     688             :                 }
     689             : 
     690             :                 /* Undo PZVAL_LOCK() */
     691         473 :                 Z_DELREF_P(retval);
     692             : 
     693         473 :                 return retval;
     694             :         } else {
     695           4 :                 zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
     696             :                 return 0;
     697             :         }
     698             : }
     699             : /* }}} */
     700             : 
     701        1322 : static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */
     702             : {
     703        1322 :         zend_class_entry *ce = Z_OBJCE_P(object);
     704             : 
     705        1322 :         if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC) != 0)) {
     706        1321 :                 if (!offset) {
     707          10 :                         ALLOC_INIT_ZVAL(offset);
     708             :                 } else {
     709        4157 :                         SEPARATE_ARG_IF_REF(offset);
     710             :                 }
     711        1321 :                 zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, offset, value);
     712        1321 :                 zval_ptr_dtor(&offset);
     713             :         } else {
     714           1 :                 zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
     715             :         }
     716        1321 : }
     717             : /* }}} */
     718             : 
     719        1078 : static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */
     720             : {
     721        1078 :         zend_class_entry *ce = Z_OBJCE_P(object);
     722             :         zval *retval;
     723             :         int result;
     724             : 
     725        1078 :         if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC) != 0)) {
     726        3304 :                 SEPARATE_ARG_IF_REF(offset);
     727        1078 :                 zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", &retval, offset);
     728        1078 :                 if (EXPECTED(retval != NULL)) {
     729        2152 :                         result = i_zend_is_true(retval TSRMLS_CC);
     730        1076 :                         zval_ptr_dtor(&retval);
     731        1076 :                         if (check_empty && result && EXPECTED(!EG(exception))) {
     732           8 :                                 zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);
     733           8 :                                 if (retval) {
     734          16 :                                         result = i_zend_is_true(retval TSRMLS_CC);
     735           8 :                                         zval_ptr_dtor(&retval);
     736             :                                 }
     737             :                         }
     738             :                 } else {
     739           2 :                         result = 0;
     740             :                 }
     741        1078 :                 zval_ptr_dtor(&offset);
     742             :         } else {
     743           0 :                 zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
     744             :                 return 0;
     745             :         }
     746        1078 :         return result;
     747             : }
     748             : /* }}} */
     749             : 
     750      179751 : static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
     751             : {
     752             :         zend_object *zobj;
     753             :         zval tmp_member;
     754             :         zval **retval;
     755             :         zend_property_info *property_info;
     756             : 
     757      179751 :         zobj = Z_OBJ_P(object);
     758             : 
     759      179751 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     760           0 :                 tmp_member = *member;
     761             :                 zval_copy_ctor(&tmp_member);
     762           0 :                 convert_to_string(&tmp_member);
     763           0 :                 member = &tmp_member;
     764           0 :                 key = NULL;
     765             :         }
     766             : 
     767             : #if DEBUG_OBJECT_HANDLERS
     768             :         fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
     769             : #endif
     770             : 
     771      359499 :         property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC);
     772             : 
     773     1077975 :         if (UNEXPECTED(!property_info) ||
     774      179744 :             ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
     775      179743 :              property_info->offset >= 0) ?
     776      179498 :                 (zobj->properties ?
     777        2432 :                     ((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
     778      356564 :                     (*(retval = &zobj->properties_table[property_info->offset]) == NULL)) :
     779         386 :                 (UNEXPECTED(!zobj->properties) ||
     780         140 :                   UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) {
     781             :                 zval *new_zval;
     782             :                 zend_guard *guard;
     783             : 
     784         340 :                 if (!zobj->ce->__get ||
     785          38 :                         zend_get_property_guard(zobj, property_info, member, &guard) != SUCCESS ||
     786          34 :                         (property_info && guard->in_get)) {
     787             :                         /* we don't have access controls - will just add it */
     788         115 :                         new_zval = &EG(uninitialized_zval);
     789             : 
     790         115 :                         if(UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
     791          14 :                                 zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
     792             :                         }
     793         115 :                         Z_ADDREF_P(new_zval);
     794         230 :                         if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
     795         115 :                             property_info->offset >= 0) {
     796           0 :                                 if (!zobj->properties) {
     797           0 :                                         zobj->properties_table[property_info->offset] = new_zval;
     798           0 :                                         retval = &zobj->properties_table[property_info->offset];
     799           0 :                                 } else if (zobj->properties_table[property_info->offset]) {
     800           0 :                                         *(zval**)zobj->properties_table[property_info->offset] = new_zval;
     801           0 :                                         retval = (zval**)zobj->properties_table[property_info->offset];
     802             :                                 } else {
     803           0 :                                         zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]);
     804           0 :                                         retval = (zval**)zobj->properties_table[property_info->offset];
     805             :                                 }
     806             :                         } else {
     807         115 :                                 if (!zobj->properties) {
     808          73 :                                         rebuild_object_properties(zobj);
     809             :                                 }
     810         115 :                                 zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
     811             :                         }
     812             :                 } else {
     813             :                         /* we do have getter - fail and let it try again with usual get/set */
     814          38 :                         retval = NULL;
     815             :                 }
     816             :         }
     817      179748 :         if (UNEXPECTED(member == &tmp_member)) {
     818             :                 zval_dtor(member);
     819             :         }
     820      179748 :         return retval;
     821             : }
     822             : /* }}} */
     823             : 
     824         164 : static void zend_std_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
     825             : {
     826             :         zend_object *zobj;
     827         164 :         zval *tmp_member = NULL;
     828             :         zend_property_info *property_info;
     829             : 
     830         164 :         zobj = Z_OBJ_P(object);
     831             : 
     832         164 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
     833           1 :                 ALLOC_ZVAL(tmp_member);
     834           1 :                 *tmp_member = *member;
     835           1 :                 INIT_PZVAL(tmp_member);
     836           1 :                 zval_copy_ctor(tmp_member);
     837           1 :                 convert_to_string(tmp_member);
     838           1 :                 member = tmp_member;
     839           1 :                 key = NULL;
     840             :         }
     841             : 
     842         327 :         property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__unset != NULL), key TSRMLS_CC);
     843             : 
     844         608 :         if (EXPECTED(property_info != NULL) &&
     845         161 :             EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
     846         160 :             !zobj->properties &&
     847          46 :             property_info->offset >= 0 &&
     848          39 :             EXPECTED(zobj->properties_table[property_info->offset] != NULL)) {
     849          39 :                 zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
     850          39 :                 zobj->properties_table[property_info->offset] = NULL;
     851         375 :         } else if (UNEXPECTED(!property_info) ||
     852         122 :                    !zobj->properties ||
     853         114 :                    UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) {
     854          17 :                 zend_guard *guard = NULL;
     855             : 
     856          42 :                 if (zobj->ce->__unset &&
     857           9 :                     zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
     858           9 :                     !guard->in_unset) {
     859             :                         /* have unseter - try with it! */
     860           8 :                         Z_ADDREF_P(object);
     861          16 :                         if (PZVAL_IS_REF(object)) {
     862           0 :                                 SEPARATE_ZVAL(&object);
     863             :                         }
     864           8 :                         guard->in_unset = 1; /* prevent circular unsetting */
     865           8 :                         zend_std_call_unsetter(object, member TSRMLS_CC);
     866           7 :                         guard->in_unset = 0;
     867           7 :                         zval_ptr_dtor(&object);
     868           9 :                 } else if (zobj->ce->__unset && guard && guard->in_unset == 1) {
     869           1 :                         if (Z_STRVAL_P(member)[0] == '\0') {
     870           1 :                                 if (Z_STRLEN_P(member) == 0) {
     871           1 :                                         zend_error(E_ERROR, "Cannot access empty property");
     872             :                                 } else {
     873           0 :                                         zend_error(E_ERROR, "Cannot access property started with '\\0'");
     874             :                                 }
     875             :                         }
     876             :                 }
     877         321 :         } else if (EXPECTED(property_info != NULL) &&
     878         107 :                    EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
     879         107 :                    property_info->offset >= 0) {
     880          13 :                 zobj->properties_table[property_info->offset] = NULL;
     881             :         }
     882             : 
     883         161 :         if (UNEXPECTED(tmp_member != NULL)) {
     884           0 :                 zval_ptr_dtor(&tmp_member);
     885             :         }
     886         161 : }
     887             : /* }}} */
     888             : 
     889          27 : static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */
     890             : {
     891          27 :         zend_class_entry *ce = Z_OBJCE_P(object);
     892             : 
     893          27 :         if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
     894         105 :                 SEPARATE_ARG_IF_REF(offset);
     895          27 :                 zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", NULL, offset);
     896          27 :                 zval_ptr_dtor(&offset);
     897             :         } else {
     898           0 :                 zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
     899             :         }
     900          27 : }
     901             : /* }}} */
     902             : 
     903         442 : ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
     904             : {
     905         442 :         zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
     906             :         zval *method_name_ptr, *method_args_ptr;
     907         442 :         zval *method_result_ptr = NULL;
     908         442 :         zend_class_entry *ce = Z_OBJCE_P(this_ptr);
     909             : 
     910         442 :         ALLOC_ZVAL(method_args_ptr);
     911         442 :         INIT_PZVAL(method_args_ptr);
     912         442 :         array_init_size(method_args_ptr, ZEND_NUM_ARGS());
     913             : 
     914         442 :         if (UNEXPECTED(zend_copy_parameters_array(ZEND_NUM_ARGS(), method_args_ptr TSRMLS_CC) == FAILURE)) {
     915           0 :                 zval_dtor(method_args_ptr);
     916           0 :                 zend_error_noreturn(E_ERROR, "Cannot get arguments for __call");
     917             :                 RETURN_FALSE;
     918             :         }
     919             : 
     920         442 :         ALLOC_ZVAL(method_name_ptr);
     921         442 :         INIT_PZVAL(method_name_ptr);
     922         442 :         ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
     923             : 
     924             :         /* __call handler is called with two arguments:
     925             :            method name
     926             :            array of method parameters
     927             : 
     928             :         */
     929         442 :         zend_call_method_with_2_params(&this_ptr, ce, &ce->__call, ZEND_CALL_FUNC_NAME, &method_result_ptr, method_name_ptr, method_args_ptr);
     930             : 
     931         432 :         if (method_result_ptr) {
     932        1676 :                 RETVAL_ZVAL_FAST(method_result_ptr);
     933         419 :                 zval_ptr_dtor(&method_result_ptr);
     934             :         }
     935             : 
     936             :         /* now destruct all auxiliaries */
     937         432 :         zval_ptr_dtor(&method_args_ptr);
     938         432 :         zval_ptr_dtor(&method_name_ptr);
     939             : 
     940             :         /* destruct the function also, then - we have allocated it in get_method */
     941         432 :         efree(func);
     942             : }
     943             : /* }}} */
     944             : 
     945             : /* Ensures that we're allowed to call a private method.
     946             :  * Returns the function address that should be called, or NULL
     947             :  * if no such function exists.
     948             :  */
     949         181 : static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen, ulong hash_value TSRMLS_DC) /* {{{ */
     950             : {
     951         181 :         if (!ce) {
     952           7 :                 return 0;
     953             :         }
     954             : 
     955             :         /* We may call a private function if:
     956             :          * 1.  The class of our object is the same as the scope, and the private
     957             :          *     function (EX(fbc)) has the same scope.
     958             :          * 2.  One of our parent classes are the same as the scope, and it contains
     959             :          *     a private function with the same name that has the same scope.
     960             :          */
     961         174 :         if (fbc->common.scope == ce && EG(scope) == ce) {
     962             :                 /* rule #1 checks out ok, allow the function call */
     963         132 :                 return fbc;
     964             :         }
     965             : 
     966             : 
     967             :         /* Check rule #2 */
     968          42 :         ce = ce->parent;
     969          96 :         while (ce) {
     970          23 :                 if (ce == EG(scope)) {
     971          55 :                         if (zend_hash_quick_find(&ce->function_table, function_name_strval, function_name_strlen+1, hash_value, (void **) &fbc)==SUCCESS
     972          44 :                                 && fbc->op_array.fn_flags & ZEND_ACC_PRIVATE
     973          22 :                                 && fbc->common.scope == EG(scope)) {
     974           9 :                                 return fbc;
     975             :                         }
     976           2 :                         break;
     977             :                 }
     978          12 :                 ce = ce->parent;
     979             :         }
     980          33 :         return NULL;
     981             : }
     982             : /* }}} */
     983             : 
     984          32 : ZEND_API int zend_check_private(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) /* {{{ */
     985             : {
     986          32 :         return zend_check_private_int(fbc, ce, function_name_strval, function_name_strlen, zend_hash_func(function_name_strval, function_name_strlen+1) TSRMLS_CC) != NULL;
     987             : }
     988             : /* }}} */
     989             : 
     990             : /* Ensures that we're allowed to call a protected method.
     991             :  */
     992        7592 : ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) /* {{{ */
     993             : {
     994        7592 :         zend_class_entry *fbc_scope = ce;
     995             : 
     996             :         /* Is the context that's calling the function, the same as one of
     997             :          * the function's parents?
     998             :          */
     999       15667 :         while (fbc_scope) {
    1000        7789 :                 if (fbc_scope==scope) {
    1001        7306 :                         return 1;
    1002             :                 }
    1003         483 :                 fbc_scope = fbc_scope->parent;
    1004             :         }
    1005             : 
    1006             :         /* Is the function's scope the same as our current object context,
    1007             :          * or any of the parents of our context?
    1008             :          */
    1009         770 :         while (scope) {
    1010         356 :                 if (scope==ce) {
    1011         158 :                         return 1;
    1012             :                 }
    1013         198 :                 scope = scope->parent;
    1014             :         }
    1015         128 :         return 0;
    1016             : }
    1017             : /* }}} */
    1018             : 
    1019         442 : static inline union _zend_function *zend_get_user_call_function(zend_class_entry *ce, const char *method_name, int method_len) /* {{{ */
    1020             : {
    1021         442 :         zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
    1022         442 :         call_user_call->type = ZEND_INTERNAL_FUNCTION;
    1023         442 :         call_user_call->module = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL;
    1024         442 :         call_user_call->handler = zend_std_call_user_call;
    1025         442 :         call_user_call->arg_info = NULL;
    1026         442 :         call_user_call->num_args = 0;
    1027         442 :         call_user_call->scope = ce;
    1028         442 :         call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
    1029         442 :         call_user_call->function_name = estrndup(method_name, method_len);
    1030             : 
    1031         442 :         return (union _zend_function *)call_user_call;
    1032             : }
    1033             : /* }}} */
    1034             : 
    1035       23404 : static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len, const zend_literal *key TSRMLS_DC) /* {{{ */
    1036             : {
    1037             :         zend_function *fbc;
    1038       23404 :         zval *object = *object_ptr;
    1039       23404 :         zend_object *zobj = Z_OBJ_P(object);
    1040             :         ulong hash_value;
    1041             :         char *lc_method_name;
    1042             :         ALLOCA_FLAG(use_heap)
    1043             : 
    1044       23404 :         if (EXPECTED(key != NULL)) {
    1045       22951 :                 lc_method_name = Z_STRVAL(key->constant);
    1046       22951 :                 hash_value = key->hash_value;
    1047             :         } else {
    1048         453 :                 lc_method_name = do_alloca(method_len+1, use_heap);
    1049             :                 /* Create a zend_copy_str_tolower(dest, src, src_length); */
    1050         453 :                 zend_str_tolower_copy(lc_method_name, method_name, method_len);
    1051         453 :                 hash_value = zend_hash_func(lc_method_name, method_len+1);
    1052             :         }
    1053             : 
    1054       23404 :         if (UNEXPECTED(zend_hash_quick_find(&zobj->ce->function_table, lc_method_name, method_len+1, hash_value, (void **)&fbc) == FAILURE)) {
    1055        1804 :                 if (UNEXPECTED(!key)) {
    1056         297 :                         free_alloca(lc_method_name, use_heap);
    1057             :                 }
    1058        1804 :                 if (zobj->ce->__call) {
    1059         397 :                         return zend_get_user_call_function(zobj->ce, method_name, method_len);
    1060             :                 } else {
    1061        1407 :                         return NULL;
    1062             :                 }
    1063             :         }
    1064             : 
    1065             :         /* Check access level */
    1066       21600 :         if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
    1067             :                 zend_function *updated_fbc;
    1068             : 
    1069             :                 /* Ensure that if we're calling a private function, we're allowed to do so.
    1070             :                  * If we're not and __call() handler exists, invoke it, otherwise error out.
    1071             :                  */
    1072         132 :                 updated_fbc = zend_check_private_int(fbc, Z_OBJ_HANDLER_P(object, get_class_entry)(object TSRMLS_CC), lc_method_name, method_len, hash_value TSRMLS_CC);
    1073         132 :                 if (EXPECTED(updated_fbc != NULL)) {
    1074         121 :                         fbc = updated_fbc;
    1075             :                 } else {
    1076          11 :                         if (zobj->ce->__call) {
    1077           3 :                                 fbc = zend_get_user_call_function(zobj->ce, method_name, method_len);
    1078             :                         } else {
    1079           8 :                                 zend_error_noreturn(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
    1080             :                         }
    1081             :                 }
    1082             :         } else {
    1083             :                 /* Ensure that we haven't overridden a private function and end up calling
    1084             :                  * the overriding public function...
    1085             :                  */
    1086       25904 :                 if (EG(scope) &&
    1087        4426 :                     is_derived_class(fbc->common.scope, EG(scope)) &&
    1088          10 :                     fbc->op_array.fn_flags & ZEND_ACC_CHANGED) {
    1089             :                         zend_function *priv_fbc;
    1090             : 
    1091          35 :                         if (zend_hash_quick_find(&EG(scope)->function_table, lc_method_name, method_len+1, hash_value, (void **) &priv_fbc)==SUCCESS
    1092          28 :                                 && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
    1093          14 :                                 && priv_fbc->common.scope == EG(scope)) {
    1094           6 :                                 fbc = priv_fbc;
    1095             :                         }
    1096             :                 }
    1097       21468 :                 if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
    1098             :                         /* Ensure that if we're calling a protected function, we're allowed to do so.
    1099             :                          * If we're not and __call() handler exists, invoke it, otherwise error out.
    1100             :                          */
    1101          34 :                         if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) {
    1102          13 :                                 if (zobj->ce->__call) {
    1103           3 :                                         fbc = zend_get_user_call_function(zobj->ce, method_name, method_len);
    1104             :                                 } else {
    1105          10 :                                         zend_error_noreturn(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
    1106             :                                 }
    1107             :                         }
    1108             :                 }
    1109             :         }
    1110             : 
    1111       21582 :         if (UNEXPECTED(!key)) {
    1112         156 :                 free_alloca(lc_method_name, use_heap);
    1113             :         }
    1114       21582 :         return fbc;
    1115             : }
    1116             : /* }}} */
    1117             : 
    1118          49 : ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
    1119             : {
    1120          49 :         zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
    1121             :         zval *method_name_ptr, *method_args_ptr;
    1122          49 :         zval *method_result_ptr = NULL;
    1123          49 :         zend_class_entry *ce = EG(scope);
    1124             : 
    1125          49 :         ALLOC_ZVAL(method_args_ptr);
    1126          49 :         INIT_PZVAL(method_args_ptr);
    1127          49 :         array_init_size(method_args_ptr, ZEND_NUM_ARGS());
    1128             : 
    1129          49 :         if (UNEXPECTED(zend_copy_parameters_array(ZEND_NUM_ARGS(), method_args_ptr TSRMLS_CC) == FAILURE)) {
    1130           0 :                 zval_dtor(method_args_ptr);
    1131           0 :                 zend_error_noreturn(E_ERROR, "Cannot get arguments for " ZEND_CALLSTATIC_FUNC_NAME);
    1132             :                 RETURN_FALSE;
    1133             :         }
    1134             : 
    1135          49 :         ALLOC_ZVAL(method_name_ptr);
    1136          49 :         INIT_PZVAL(method_name_ptr);
    1137          49 :         ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
    1138             : 
    1139             :         /* __callStatic handler is called with two arguments:
    1140             :            method name
    1141             :            array of method parameters
    1142             :         */
    1143          49 :         zend_call_method_with_2_params(NULL, ce, &ce->__callstatic, ZEND_CALLSTATIC_FUNC_NAME, &method_result_ptr, method_name_ptr, method_args_ptr);
    1144             : 
    1145          49 :         if (method_result_ptr) {
    1146         188 :                 RETVAL_ZVAL_FAST(method_result_ptr);
    1147          47 :                 zval_ptr_dtor(&method_result_ptr);
    1148             :         }
    1149             : 
    1150             :         /* now destruct all auxiliaries */
    1151          49 :         zval_ptr_dtor(&method_args_ptr);
    1152          49 :         zval_ptr_dtor(&method_name_ptr);
    1153             : 
    1154             :         /* destruct the function also, then - we have allocated it in get_method */
    1155          49 :         efree(func);
    1156             : }
    1157             : /* }}} */
    1158             : 
    1159          49 : static inline union _zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, const char *method_name, int method_len) /* {{{ */
    1160             : {
    1161          49 :         zend_internal_function *callstatic_user_call = emalloc(sizeof(zend_internal_function));
    1162          49 :         callstatic_user_call->type     = ZEND_INTERNAL_FUNCTION;
    1163          49 :         callstatic_user_call->module   = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL;
    1164          49 :         callstatic_user_call->handler  = zend_std_callstatic_user_call;
    1165          49 :         callstatic_user_call->arg_info = NULL;
    1166          49 :         callstatic_user_call->num_args = 0;
    1167          49 :         callstatic_user_call->scope    = ce;
    1168          49 :         callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER;
    1169          49 :         callstatic_user_call->function_name = estrndup(method_name, method_len);
    1170             : 
    1171          49 :         return (zend_function *)callstatic_user_call;
    1172             : }
    1173             : /* }}} */
    1174             : 
    1175             : /* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */
    1176             : 
    1177        3755 : ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, const char *function_name_strval, int function_name_strlen, const zend_literal *key TSRMLS_DC) /* {{{ */
    1178             : {
    1179        3755 :         zend_function *fbc = NULL;
    1180        3755 :         char *lc_class_name, *lc_function_name = NULL;
    1181             :         ulong hash_value;
    1182             :         ALLOCA_FLAG(use_heap)
    1183             : 
    1184        3755 :         if (EXPECTED(key != NULL)) {
    1185        3689 :                 lc_function_name = Z_STRVAL(key->constant);
    1186        3689 :                 hash_value = key->hash_value;
    1187             :         } else {
    1188          66 :                 lc_function_name = do_alloca(function_name_strlen+1, use_heap);
    1189             :                 /* Create a zend_copy_str_tolower(dest, src, src_length); */
    1190          66 :                 zend_str_tolower_copy(lc_function_name, function_name_strval, function_name_strlen);
    1191          66 :                 hash_value = zend_hash_func(lc_function_name, function_name_strlen+1);
    1192             :         }
    1193             : 
    1194        3755 :         if (function_name_strlen == ce->name_length && ce->constructor) {
    1195          52 :                 lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
    1196             :                 /* Only change the method to the constructor if the constructor isn't called __construct
    1197             :                  * we check for __ so we can be binary safe for lowering, we should use ZEND_CONSTRUCTOR_FUNC_NAME
    1198             :                  */
    1199          52 :                 if (!memcmp(lc_class_name, lc_function_name, function_name_strlen) && memcmp(ce->constructor->common.function_name, "__", sizeof("__") - 1)) {
    1200           5 :                         fbc = ce->constructor;
    1201             :                 }
    1202          52 :                 efree(lc_class_name);
    1203             :         }
    1204        7505 :         if (EXPECTED(!fbc) &&
    1205        3750 :             UNEXPECTED(zend_hash_quick_find(&ce->function_table, lc_function_name, function_name_strlen+1, hash_value, (void **) &fbc)==FAILURE)) {
    1206         105 :                 if (UNEXPECTED(!key)) {
    1207          52 :                         free_alloca(lc_function_name, use_heap);
    1208             :                 }
    1209             : 
    1210         252 :                 if (ce->__call &&
    1211          67 :                     EG(This) &&
    1212          40 :                     Z_OBJ_HT_P(EG(This))->get_class_entry &&
    1213          40 :                     instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
    1214          39 :                         return zend_get_user_call_function(ce, function_name_strval, function_name_strlen);
    1215          66 :                 } else if (ce->__callstatic) {
    1216          47 :                         return zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
    1217             :                 } else {
    1218          19 :                         return NULL;
    1219             :                 }
    1220             :         }
    1221             : 
    1222             : #if MBO_0
    1223             :         /* right now this function is used for non static method lookup too */
    1224             :         /* Is the function static */
    1225             :         if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) {
    1226             :                 zend_error_noreturn(E_ERROR, "Cannot call non static method %s::%s() without object", ZEND_FN_SCOPE_NAME(fbc), fbc->common.function_name);
    1227             :         }
    1228             : #endif
    1229        3650 :         if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) {
    1230             :                 /* No further checks necessary, most common case */
    1231          45 :         } else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
    1232             :                 zend_function *updated_fbc;
    1233             : 
    1234             :                 /* Ensure that if we're calling a private function, we're allowed to do so.
    1235             :                  */
    1236          17 :                 updated_fbc = zend_check_private_int(fbc, EG(scope), lc_function_name, function_name_strlen, hash_value TSRMLS_CC);
    1237          17 :                 if (EXPECTED(updated_fbc != NULL)) {
    1238          10 :                         fbc = updated_fbc;
    1239             :                 } else {
    1240           7 :                         if (ce->__callstatic) {
    1241           1 :                                 fbc = zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
    1242             :                         } else {
    1243           6 :                                 zend_error_noreturn(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
    1244             :                         }
    1245             :                 }
    1246          28 :         } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
    1247             :                 /* Ensure that if we're calling a protected function, we're allowed to do so.
    1248             :                  */
    1249          28 :                 if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) {
    1250           3 :                         if (ce->__callstatic) {
    1251           1 :                                 fbc = zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
    1252             :                         } else {
    1253           2 :                                 zend_error_noreturn(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
    1254             :                         }
    1255             :                 }
    1256             :         }
    1257             : 
    1258        3642 :         if (UNEXPECTED(!key)) {
    1259          14 :                 free_alloca(lc_function_name, use_heap);
    1260             :         }
    1261             : 
    1262        3642 :         return fbc;
    1263             : }
    1264             : /* }}} */
    1265             : 
    1266        1222 : ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, zend_bool silent, const zend_literal *key TSRMLS_DC) /* {{{ */
    1267             : {
    1268             :         zend_property_info *property_info;
    1269             :         ulong hash_value;
    1270             : 
    1271        3612 :         if (UNEXPECTED(!key) ||
    1272        2390 :             (property_info = CACHED_POLYMORPHIC_PTR(key->cache_slot, ce)) == NULL) {
    1273         667 :                 if (EXPECTED(key != NULL)) {
    1274         640 :                         hash_value = key->hash_value;
    1275             :                 } else {
    1276          27 :                         hash_value = zend_hash_func(property_name, property_name_len+1);
    1277             :                 }
    1278             : 
    1279         667 :                 if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+1, hash_value, (void **) &property_info)==FAILURE)) {
    1280          17 :                         if (!silent) {
    1281          10 :                                 zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
    1282             :                         }
    1283           7 :                         return NULL;
    1284             :                 }
    1285             : 
    1286             : #if DEBUG_OBJECT_HANDLERS
    1287             :                 zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
    1288             : #endif
    1289             : 
    1290        1300 :                 if (UNEXPECTED(!zend_verify_property_access(property_info, ce TSRMLS_CC))) {
    1291          29 :                         if (!silent) {
    1292           2 :                                 zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
    1293             :                         }
    1294          27 :                         return NULL;
    1295             :                 }
    1296             : 
    1297         621 :                 if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
    1298           0 :                         if (!silent) {
    1299           0 :                                 zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
    1300             :                         }
    1301           0 :                         return NULL;
    1302             :                 }
    1303             : 
    1304         621 :                 zend_update_class_constants(ce TSRMLS_CC);
    1305             : 
    1306         621 :                 if (EXPECTED(key != NULL)) {
    1307         607 :                         CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
    1308             :                 }
    1309             :         }
    1310             : 
    1311        2352 :         if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL) ||
    1312        1176 :             UNEXPECTED(CE_STATIC_MEMBERS(ce)[property_info->offset] == NULL)) {
    1313           1 :                 if (!silent) {
    1314           1 :                         zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
    1315             :                 }
    1316           0 :                 return NULL;
    1317             :         }
    1318             :         
    1319        1175 :         return &CE_STATIC_MEMBERS(ce)[property_info->offset];
    1320             : }
    1321             : /* }}} */
    1322             : 
    1323           0 : ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, const zend_literal *key TSRMLS_DC) /* {{{ */
    1324             : {
    1325           0 :         zend_error_noreturn(E_ERROR, "Attempt to unset static property %s::$%s", ce->name, property_name);
    1326             :         return 0;
    1327             : }
    1328             : /* }}} */
    1329             : 
    1330      461422 : ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC) /* {{{ */
    1331             : {
    1332      461422 :         zend_object *zobj = Z_OBJ_P(object);
    1333      461422 :         zend_function *constructor = zobj->ce->constructor;
    1334             : 
    1335      461422 :         if (constructor) {
    1336      287035 :                 if (constructor->op_array.fn_flags & ZEND_ACC_PUBLIC) {
    1337             :                         /* No further checks necessary */
    1338          22 :                 } else if (constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
    1339             :                         /* Ensure that if we're calling a private function, we're allowed to do so.
    1340             :                          */
    1341          14 :                         if (UNEXPECTED(constructor->common.scope != EG(scope))) {
    1342           5 :                                 if (EG(scope)) {
    1343           1 :                                         zend_error_noreturn(E_ERROR, "Call to private %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name);
    1344             :                                 } else {
    1345           4 :                                         zend_error_noreturn(E_ERROR, "Call to private %s::%s() from invalid context", constructor->common.scope->name, constructor->common.function_name);
    1346             :                                 }
    1347             :                         }
    1348           8 :                 } else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
    1349             :                         /* Ensure that if we're calling a protected function, we're allowed to do so.
    1350             :                          * Constructors only have prototype if they are defined by an interface but
    1351             :                          * it is the compilers responsibility to take care of the prototype.
    1352             :                          */
    1353           8 :                         if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(constructor), EG(scope)))) {
    1354           2 :                                 if (EG(scope)) {
    1355           1 :                                         zend_error_noreturn(E_ERROR, "Call to protected %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name);
    1356             :                                 } else {
    1357           1 :                                         zend_error_noreturn(E_ERROR, "Call to protected %s::%s() from invalid context", constructor->common.scope->name, constructor->common.function_name);
    1358             :                                 }
    1359             :                         }
    1360             :                 }
    1361             :         }
    1362             : 
    1363      461415 :         return constructor;
    1364             : }
    1365             : /* }}} */
    1366             : 
    1367             : int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC);
    1368             : 
    1369        1231 : static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
    1370             : {
    1371             :         zend_object *zobj1, *zobj2;
    1372             : 
    1373        1231 :         zobj1 = Z_OBJ_P(o1);
    1374        1231 :         zobj2 = Z_OBJ_P(o2);
    1375             : 
    1376        1231 :         if (zobj1->ce != zobj2->ce) {
    1377          34 :                 return 1; /* different classes */
    1378             :         }
    1379        1197 :         if (!zobj1->properties && !zobj2->properties) {
    1380             :                 int i;
    1381             : 
    1382         890 :                 Z_OBJ_PROTECT_RECURSION(o1);
    1383         889 :                 Z_OBJ_PROTECT_RECURSION(o2);
    1384         907 :                 for (i = 0; i < zobj1->ce->default_properties_count; i++) {
    1385         884 :                         if (zobj1->properties_table[i]) {
    1386         883 :                                 if (zobj2->properties_table[i]) {
    1387             :                                         zval result;
    1388             : 
    1389         883 :                                         if (compare_function(&result, zobj1->properties_table[i], zobj2->properties_table[i] TSRMLS_CC)==FAILURE) {
    1390           0 :                                                 Z_OBJ_UNPROTECT_RECURSION(o1);
    1391           0 :                                                 Z_OBJ_UNPROTECT_RECURSION(o2);
    1392           0 :                                                 return 1;
    1393             :                                         }
    1394         880 :                                         if (Z_LVAL(result) != 0) {
    1395         863 :                                                 Z_OBJ_UNPROTECT_RECURSION(o1);
    1396         863 :                                                 Z_OBJ_UNPROTECT_RECURSION(o2);
    1397         863 :                                                 return Z_LVAL(result);
    1398             :                                         }
    1399             :                                 } else {
    1400           0 :                                         Z_OBJ_UNPROTECT_RECURSION(o1);
    1401           0 :                                         Z_OBJ_UNPROTECT_RECURSION(o2);
    1402           0 :                                         return 1;
    1403             :                                 }
    1404             :                         } else {
    1405           1 :                                 if (zobj2->properties_table[i]) {
    1406           0 :                                         Z_OBJ_UNPROTECT_RECURSION(o1);
    1407           0 :                                         Z_OBJ_UNPROTECT_RECURSION(o2);
    1408           0 :                                         return 1;
    1409             :                                 }
    1410             :                         }
    1411             :                 }
    1412          23 :                 Z_OBJ_UNPROTECT_RECURSION(o1);
    1413          23 :                 Z_OBJ_UNPROTECT_RECURSION(o2);
    1414          23 :                 return 0;
    1415             :         } else {
    1416         307 :                 if (!zobj1->properties) {
    1417           1 :                         rebuild_object_properties(zobj1);
    1418             :                 }
    1419         307 :                 if (!zobj2->properties) {
    1420           0 :                         rebuild_object_properties(zobj2);
    1421             :                 }
    1422         307 :                 return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC);
    1423             :         }
    1424             : }
    1425             : /* }}} */
    1426             : 
    1427         320 : static int zend_std_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */
    1428             : {
    1429             :         zend_object *zobj;
    1430             :         int result;
    1431         320 :         zval **value = NULL;
    1432         320 :         zval *tmp_member = NULL;
    1433             :         zend_property_info *property_info;
    1434             : 
    1435         320 :         zobj = Z_OBJ_P(object);
    1436             : 
    1437         320 :         if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
    1438           4 :                 ALLOC_ZVAL(tmp_member);
    1439           4 :                 *tmp_member = *member;
    1440           4 :                 INIT_PZVAL(tmp_member);
    1441           4 :                 zval_copy_ctor(tmp_member);
    1442           4 :                 convert_to_string(tmp_member);
    1443           4 :                 member = tmp_member;
    1444           4 :                 key = NULL;
    1445             :         }
    1446             : 
    1447             : #if DEBUG_OBJECT_HANDLERS
    1448             :         fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
    1449             : #endif
    1450             : 
    1451         640 :         property_info = zend_get_property_info_quick(zobj->ce, member, 1, key TSRMLS_CC);
    1452             : 
    1453        1636 :         if (UNEXPECTED(!property_info) ||
    1454         305 :             ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
    1455         304 :              property_info->offset >= 0) ?
    1456         124 :                 (zobj->properties ?
    1457         106 :                     ((value = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
    1458         142 :                     (*(value = &zobj->properties_table[property_info->offset]) == NULL)) :
    1459         302 :                 (UNEXPECTED(!zobj->properties) ||
    1460         121 :                   UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE)))) {
    1461             :                 zend_guard *guard;
    1462             : 
    1463         154 :                 result = 0;
    1464         279 :                 if ((has_set_exists != 2) &&
    1465          63 :                     zobj->ce->__isset &&
    1466          31 :                     zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
    1467          31 :                     !guard->in_isset) {
    1468             :                         zval *rv;
    1469             : 
    1470             :                         /* have issetter - try with it! */
    1471          20 :                         Z_ADDREF_P(object);
    1472          40 :                         if (PZVAL_IS_REF(object)) {
    1473           0 :                                 SEPARATE_ZVAL(&object);
    1474             :                         }
    1475          20 :                         guard->in_isset = 1; /* prevent circular getting */
    1476          20 :                         rv = zend_std_call_issetter(object, member TSRMLS_CC);
    1477          20 :                         if (rv) {
    1478          20 :                                 result = zend_is_true(rv TSRMLS_CC);
    1479          20 :                                 zval_ptr_dtor(&rv);
    1480          20 :                                 if (has_set_exists && result) {
    1481           3 :                                         if (EXPECTED(!EG(exception)) && zobj->ce->__get && !guard->in_get) {
    1482           1 :                                                 guard->in_get = 1;
    1483           1 :                                                 rv = zend_std_call_getter(object, member TSRMLS_CC);
    1484           1 :                                                 guard->in_get = 0;
    1485           1 :                                                 if (rv) {
    1486           1 :                                                         Z_ADDREF_P(rv);
    1487           2 :                                                         result = i_zend_is_true(rv TSRMLS_CC);
    1488           1 :                                                         zval_ptr_dtor(&rv);
    1489             :                                                 } else {
    1490           0 :                                                         result = 0;
    1491             :                                                 }
    1492             :                                         } else {
    1493           1 :                                                 result = 0;
    1494             :                                         }
    1495             :                                 }
    1496             :                         }
    1497          20 :                         guard->in_isset = 0;
    1498          20 :                         zval_ptr_dtor(&object);
    1499             :                 }
    1500             :         } else {
    1501         166 :                 switch (has_set_exists) {
    1502             :                 case 0:
    1503         110 :                         result = (Z_TYPE_PP(value) != IS_NULL);
    1504         110 :                         break;
    1505             :                 default:
    1506          24 :                         result = zend_is_true(*value TSRMLS_CC);
    1507          24 :                         break;
    1508             :                 case 2:
    1509          32 :                         result = 1;
    1510             :                         break;
    1511             :                 }
    1512             :         }
    1513             : 
    1514         320 :         if (UNEXPECTED(tmp_member != NULL)) {
    1515           4 :                 zval_ptr_dtor(&tmp_member);
    1516             :         }
    1517         320 :         return result;
    1518             : }
    1519             : /* }}} */
    1520             : 
    1521     3020178 : zend_class_entry *zend_std_object_get_class(const zval *object TSRMLS_DC) /* {{{ */
    1522             : {
    1523             :         zend_object *zobj;
    1524     3020178 :         zobj = Z_OBJ_P(object);
    1525             : 
    1526     3020178 :         return zobj->ce;
    1527             : }
    1528             : /* }}} */
    1529             : 
    1530      137242 : int zend_std_object_get_class_name(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) /* {{{ */
    1531             : {
    1532             :         zend_object *zobj;
    1533             :         zend_class_entry *ce;
    1534      137242 :         zobj = Z_OBJ_P(object);
    1535             : 
    1536      137242 :         if (parent) {
    1537          11 :                 if (!zobj->ce->parent) {
    1538           8 :                         return FAILURE;
    1539             :                 }
    1540           3 :                 ce = zobj->ce->parent;
    1541             :         } else {
    1542      137231 :                 ce = zobj->ce;
    1543             :         }
    1544             : 
    1545      137234 :         *class_name_len = ce->name_length;
    1546      137234 :         *class_name = estrndup(ce->name, ce->name_length);
    1547      137234 :         return SUCCESS;
    1548             : }
    1549             : /* }}} */
    1550             : 
    1551      367316 : ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* {{{ */
    1552             : {
    1553             :         zval *retval;
    1554             :         zend_class_entry *ce;
    1555             : 
    1556      367316 :         switch (type) {
    1557             :                 case IS_STRING:
    1558      204490 :                         ce = Z_OBJCE_P(readobj);
    1559      408286 :                         if (ce->__tostring &&
    1560      203796 :                                 (zend_call_method_with_0_params(&readobj, ce, &ce->__tostring, "__tostring", &retval) || EG(exception))) {
    1561      203792 :                                 if (UNEXPECTED(EG(exception) != NULL)) {
    1562           4 :                                         if (retval) {
    1563           0 :                                                 zval_ptr_dtor(&retval);
    1564             :                                         }
    1565           4 :                                         EG(exception) = NULL;
    1566           4 :                                         zend_error_noreturn(E_ERROR, "Method %s::__toString() must not throw an exception", ce->name);
    1567             :                                         return FAILURE;
    1568             :                                 }
    1569      203788 :                                 if (EXPECTED(Z_TYPE_P(retval) == IS_STRING)) {
    1570      203784 :                                         INIT_PZVAL(writeobj);
    1571      203784 :                                         if (readobj == writeobj) {
    1572           0 :                                                 zval_dtor(readobj);
    1573             :                                         }
    1574      407568 :                                         ZVAL_ZVAL(writeobj, retval, 1, 1);
    1575      203784 :                                         if (Z_TYPE_P(writeobj) != type) {
    1576           0 :                                                 convert_to_explicit_type(writeobj, type);
    1577             :                                         }
    1578      203784 :                                         return SUCCESS;
    1579             :                                 } else {
    1580           4 :                                         zval_ptr_dtor(&retval);
    1581           4 :                                         INIT_PZVAL(writeobj);
    1582           4 :                                         if (readobj == writeobj) {
    1583           0 :                                                 zval_dtor(readobj);
    1584             :                                         }
    1585           4 :                                         ZVAL_EMPTY_STRING(writeobj);
    1586           4 :                                         zend_error(E_RECOVERABLE_ERROR, "Method %s::__toString() must return a string value", ce->name);
    1587           4 :                                         return SUCCESS;
    1588             :                                 }
    1589             :                         }
    1590         698 :                         return FAILURE;
    1591             :                 case IS_BOOL:
    1592      162575 :                         INIT_PZVAL(writeobj);
    1593      162575 :                         ZVAL_BOOL(writeobj, 1);
    1594      162575 :                         return SUCCESS;
    1595             :                 case IS_LONG:
    1596         143 :                         ce = Z_OBJCE_P(readobj);
    1597         143 :                         zend_error(E_NOTICE, "Object of class %s could not be converted to int", ce->name);
    1598         143 :                         INIT_PZVAL(writeobj);
    1599         143 :                         if (readobj == writeobj) {
    1600           0 :                                 zval_dtor(readobj);
    1601             :                         }
    1602         143 :                         ZVAL_LONG(writeobj, 1);
    1603         143 :                         return SUCCESS;
    1604             :                 case IS_DOUBLE:
    1605          43 :                         ce = Z_OBJCE_P(readobj);
    1606          43 :                         zend_error(E_NOTICE, "Object of class %s could not be converted to double", ce->name);
    1607          43 :                         INIT_PZVAL(writeobj);
    1608          43 :                         if (readobj == writeobj) {
    1609           0 :                                 zval_dtor(readobj);
    1610             :                         }
    1611          43 :                         ZVAL_DOUBLE(writeobj, 1);
    1612          43 :                         return SUCCESS;
    1613             :                 default:
    1614          65 :                         INIT_PZVAL(writeobj);
    1615          65 :                         Z_TYPE_P(writeobj) = IS_NULL;
    1616             :                         break;
    1617             :         }
    1618          65 :         return FAILURE;
    1619             : }
    1620             : /* }}} */
    1621             : 
    1622          71 : int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) /* {{{ */
    1623             : {
    1624             :         zend_class_entry *ce;
    1625          71 :         if (Z_TYPE_P(obj) != IS_OBJECT) {
    1626           0 :                 return FAILURE;
    1627             :         }
    1628             : 
    1629          71 :         ce = Z_OBJCE_P(obj);
    1630             : 
    1631          71 :         if (zend_hash_find(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME), (void**)fptr_ptr) == FAILURE) {
    1632          50 :                 return FAILURE;
    1633             :         }
    1634             : 
    1635          21 :         *ce_ptr = ce;
    1636          21 :         if ((*fptr_ptr)->common.fn_flags & ZEND_ACC_STATIC) {
    1637           0 :                 if (zobj_ptr) {
    1638           0 :                         *zobj_ptr = NULL;
    1639             :                 }
    1640             :         } else {
    1641          21 :                 if (zobj_ptr) {
    1642          21 :                         *zobj_ptr = obj;
    1643             :                 }
    1644             :         }
    1645          21 :         return SUCCESS;
    1646             : }
    1647             : /* }}} */
    1648             : 
    1649             : ZEND_API zend_object_handlers std_object_handlers = {
    1650             :         zend_objects_store_add_ref,                             /* add_ref */
    1651             :         zend_objects_store_del_ref,                             /* del_ref */
    1652             :         zend_objects_clone_obj,                                 /* clone_obj */
    1653             : 
    1654             :         zend_std_read_property,                                 /* read_property */
    1655             :         zend_std_write_property,                                /* write_property */
    1656             :         zend_std_read_dimension,                                /* read_dimension */
    1657             :         zend_std_write_dimension,                               /* write_dimension */
    1658             :         zend_std_get_property_ptr_ptr,                  /* get_property_ptr_ptr */
    1659             :         NULL,                                                                   /* get */
    1660             :         NULL,                                                                   /* set */
    1661             :         zend_std_has_property,                                  /* has_property */
    1662             :         zend_std_unset_property,                                /* unset_property */
    1663             :         zend_std_has_dimension,                                 /* has_dimension */
    1664             :         zend_std_unset_dimension,                               /* unset_dimension */
    1665             :         zend_std_get_properties,                                /* get_properties */
    1666             :         zend_std_get_method,                                    /* get_method */
    1667             :         NULL,                                                                   /* call_method */
    1668             :         zend_std_get_constructor,                               /* get_constructor */
    1669             :         zend_std_object_get_class,                              /* get_class_entry */
    1670             :         zend_std_object_get_class_name,                 /* get_class_name */
    1671             :         zend_std_compare_objects,                               /* compare_objects */
    1672             :         zend_std_cast_object_tostring,                  /* cast_object */
    1673             :         NULL,                                                                   /* count_elements */
    1674             :         zend_std_get_debug_info,                                /* get_debug_info */
    1675             :         zend_std_get_closure,                                   /* get_closure */
    1676             :         zend_std_get_gc,                                                /* get_gc */
    1677             :         NULL,                                                                   /* do_operation */
    1678             :         NULL,                                                                   /* compare */
    1679             : };
    1680             : 
    1681             : /*
    1682             :  * Local variables:
    1683             :  * tab-width: 4
    1684             :  * c-basic-offset: 4
    1685             :  * indent-tabs-mode: t
    1686             :  * End:
    1687             :  */

Generated by: LCOV version 1.10

Generated at Mon, 04 Aug 2014 15:49:00 +0000 (42 days ago)

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