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

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_2/Zend - zend_object_handlers.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 544
Code covered: 92.1 % Executed lines: 501
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | Zend Engine                                                          |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1998-2009 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: zend_object_handlers.c 288082 2009-09-05 17:11:44Z jani $ */
      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                 : 
      31                 : #define DEBUG_OBJECT_HANDLERS 0
      32                 : 
      33                 : #define Z_OBJ_P(zval_p) zend_objects_get_address(zval_p TSRMLS_CC)
      34                 : 
      35                 : /*
      36                 :   __X accessors explanation:
      37                 : 
      38                 :   if we have __get and property that is not part of the properties array is
      39                 :   requested, we call __get handler. If it fails, we return uninitialized.
      40                 : 
      41                 :   if we have __set and property that is not part of the properties array is
      42                 :   set, we call __set handler. If it fails, we do not change the array.
      43                 : 
      44                 :   for both handlers above, when we are inside __get/__set, no further calls for
      45                 :   __get/__set for this property of this object will be made, to prevent endless 
      46                 :   recursion and enable accessors to change properties array.
      47                 : 
      48                 :   if we have __call and method which is not part of the class function table is
      49                 :   called, we cal __call handler.
      50                 : */
      51                 : 
      52                 : static HashTable *zend_std_get_properties(zval *object TSRMLS_DC)
      53          201594 : {
      54                 :         zend_object *zobj;
      55          201594 :         zobj = Z_OBJ_P(object);
      56          201594 :         return zobj->properties;
      57                 : }
      58                 : 
      59                 : static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC)
      60             107 : {
      61             107 :         zval *retval = NULL;
      62             107 :         zend_class_entry *ce = Z_OBJCE_P(object);
      63                 : 
      64                 :         /* __get handler is called with one argument:
      65                 :               property name
      66                 : 
      67                 :            it should return whether the call was successfull or not
      68                 :         */
      69                 : 
      70             107 :         SEPARATE_ARG_IF_REF(member);
      71                 : 
      72             107 :         zend_call_method_with_1_params(&object, ce, &ce->__get, ZEND_GET_FUNC_NAME, &retval, member);
      73                 : 
      74             107 :         zval_ptr_dtor(&member);
      75                 : 
      76             107 :         if (retval) {
      77             105 :                 retval->refcount--;
      78                 :         }
      79                 : 
      80             107 :         return retval;
      81                 : }
      82                 : 
      83                 : static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_DC)
      84              61 : {
      85              61 :         zval *retval = NULL;
      86                 :         int result;
      87              61 :         zend_class_entry *ce = Z_OBJCE_P(object);
      88                 : 
      89              61 :         SEPARATE_ARG_IF_REF(member);
      90              61 :         value->refcount++;
      91                 : 
      92                 :         /* __set handler is called with two arguments:
      93                 :              property name
      94                 :              value to be set
      95                 : 
      96                 :            it should return whether the call was successfull or not
      97                 :         */
      98              61 :         zend_call_method_with_2_params(&object, ce, &ce->__set, ZEND_SET_FUNC_NAME, &retval, member, value);
      99                 : 
     100              61 :         zval_ptr_dtor(&member);
     101              61 :         zval_ptr_dtor(&value);
     102                 : 
     103              61 :         if (retval) {
     104              60 :                 result = i_zend_is_true(retval) ? SUCCESS : FAILURE;
     105              60 :                 zval_ptr_dtor(&retval);
     106              60 :                 return result;
     107                 :         } else {
     108               1 :                 return FAILURE;
     109                 :         }
     110                 : }
     111                 : 
     112                 : static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC)
     113               5 : {
     114               5 :         zend_class_entry *ce = Z_OBJCE_P(object);
     115                 : 
     116                 :         /* __unset handler is called with one argument:
     117                 :               property name
     118                 :         */
     119                 : 
     120               5 :         SEPARATE_ARG_IF_REF(member);
     121                 : 
     122               5 :         zend_call_method_with_1_params(&object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
     123                 : 
     124               5 :         zval_ptr_dtor(&member);
     125               5 : }
     126                 : 
     127                 : static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC)
     128               3 : {
     129               3 :         zval *retval = NULL;
     130               3 :         zend_class_entry *ce = Z_OBJCE_P(object);
     131                 : 
     132                 :         /* __isset handler is called with one argument:
     133                 :               property name
     134                 : 
     135                 :            it should return whether the property is set or not
     136                 :         */
     137                 : 
     138               3 :         SEPARATE_ARG_IF_REF(member);
     139                 : 
     140               3 :         zend_call_method_with_1_params(&object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, &retval, member);
     141                 : 
     142               3 :         zval_ptr_dtor(&member);
     143                 : 
     144               3 :         return retval;
     145                 : }
     146                 : 
     147                 : static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC)
     148           30464 : {
     149           30464 :         switch (property_info->flags & ZEND_ACC_PPP_MASK) {
     150                 :                 case ZEND_ACC_PUBLIC:
     151           16189 :                         return 1;
     152                 :                 case ZEND_ACC_PROTECTED:
     153            4992 :                         return zend_check_protected(property_info->ce, EG(scope));
     154                 :                 case ZEND_ACC_PRIVATE:
     155            9283 :                         if ((ce==EG(scope) || property_info->ce == EG(scope)) && EG(scope)) {
     156            9161 :                                 return 1;
     157                 :                         } else {
     158             122 :                                 return 0;
     159                 :                         }
     160                 :                         break;
     161                 :         }
     162               0 :         return 0;
     163                 : }
     164                 : 
     165                 : static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class)
     166          356820 : {
     167          356820 :         child_class = child_class->parent;
     168          716026 :         while (child_class) {
     169            4201 :                 if (child_class == parent_class) {
     170            1815 :                         return 1;
     171                 :                 }
     172            2386 :                 child_class = child_class->parent;
     173                 :         }
     174                 : 
     175          355005 :         return 0;
     176                 : }
     177                 : 
     178                 : ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC)
     179          383828 : {
     180          383828 :         zend_property_info *property_info = NULL;
     181                 :         zend_property_info *scope_property_info;
     182          383828 :         zend_bool denied_access = 0;
     183                 :         ulong h;
     184                 : 
     185          383828 :         if (Z_STRVAL_P(member)[0] == '\0') {
     186               5 :                 if (!silent) {
     187               1 :                         if (Z_STRLEN_P(member) == 0) {
     188               1 :                                 zend_error(E_ERROR, "Cannot access empty property");
     189                 :                         } else {
     190               0 :                                 zend_error(E_ERROR, "Cannot access property started with '\\0'");
     191                 :                         }
     192                 :                 }
     193               4 :                 return NULL;
     194                 :         }
     195          383823 :         h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
     196          383823 :         if (zend_hash_quick_find(&ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) {
     197           31068 :                 if(property_info->flags & ZEND_ACC_SHADOW) {
     198                 :                         /* if it's a shadow - go to access it's private */
     199            1597 :                         property_info = NULL;
     200                 :                 } else {
     201           29471 :                         if (zend_verify_property_access(property_info, ce TSRMLS_CC)) {
     202           29295 :                                 if (property_info->flags & ZEND_ACC_CHANGED
     203                 :                                         && !(property_info->flags & ZEND_ACC_PRIVATE)) {
     204                 :                                         /* We still need to make sure that we're not in a context
     205                 :                                          * where the right property is a different 'statically linked' private
     206                 :                                          * continue checking below...
     207                 :                                          */
     208                 :                                 } else {
     209           29274 :                                         if (!silent && (property_info->flags & ZEND_ACC_STATIC)) {
     210              12 :                                                 zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name, Z_STRVAL_P(member));
     211                 :                                         }
     212           29274 :                                         return property_info;
     213                 :                                 }
     214                 :                         } else {
     215                 :                                 /* Try to look in the scope instead */
     216             176 :                                 denied_access = 1;
     217                 :                         }
     218                 :                 }
     219                 :         }
     220          354549 :         if (EG(scope) != ce
     221                 :                 && is_derived_class(ce, EG(scope))
     222                 :                 && EG(scope)
     223                 :                 && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
     224                 :                 && scope_property_info->flags & ZEND_ACC_PRIVATE) {
     225            1570 :                 return scope_property_info;
     226          352979 :         } else if (property_info) {
     227             172 :                 if (denied_access) {
     228                 :                         /* Information was available, but we were denied access.  Error out. */
     229             162 :                         if (silent) {
     230             149 :                                 return NULL;
     231                 :                         }
     232              13 :                         zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member));
     233                 :                 } else {
     234                 :                         /* fall through, return property_info... */
     235                 :                 }
     236                 :         } else {
     237          352807 :                 EG(std_property_info).flags = ZEND_ACC_PUBLIC;
     238          352807 :                 EG(std_property_info).name = Z_STRVAL_P(member);
     239          352807 :                 EG(std_property_info).name_length = Z_STRLEN_P(member);
     240          352807 :                 EG(std_property_info).h = h;
     241          352807 :                 EG(std_property_info).ce = ce;
     242          352807 :                 property_info = &EG(std_property_info);
     243                 :         }
     244          352817 :         return property_info;
     245                 : }
     246                 : 
     247                 : 
     248                 : ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name, int prop_info_name_len TSRMLS_DC)
     249             516 : {
     250                 :         zend_property_info *property_info;
     251                 :         char *class_name, *prop_name;
     252                 :         zval member;
     253                 : 
     254             516 :         zend_unmangle_property_name(prop_info_name, prop_info_name_len, &class_name, &prop_name);
     255             516 :         ZVAL_STRING(&member, prop_name, 0);
     256             516 :         property_info = zend_get_property_info(zobj->ce, &member, 1 TSRMLS_CC);
     257             516 :         if (!property_info) {
     258              70 :                 return FAILURE;
     259                 :         }
     260             446 :         if (prop_info_name[0] == '\0' && prop_info_name[1] != '*') {
     261              82 :                 if (!(property_info->flags & ZEND_ACC_PRIVATE)) {
     262                 :                         /* we we're looking for a private prop but found a non private one of the same name */
     263              17 :                         return FAILURE;
     264              65 :                 } else if (strcmp(prop_info_name+1, property_info->name+1)) {
     265                 :                         /* we we're looking for a private prop but found a private one of the same name but another class */
     266              11 :                         return FAILURE;
     267                 :                 }
     268                 :         }
     269             418 :         return zend_verify_property_access(property_info, zobj->ce TSRMLS_CC) ? SUCCESS : FAILURE;
     270                 : }
     271                 : 
     272                 : static int zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member, zend_guard **pguard)
     273             214 : {
     274                 :         zend_property_info info;
     275                 :         zend_guard stub;
     276                 : 
     277             214 :         if (!property_info) {
     278              22 :                 property_info = &info;
     279              22 :                 info.name = Z_STRVAL_P(member);
     280              22 :                 info.name_length = Z_STRLEN_P(member);
     281              22 :                 info.h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
     282                 :         }
     283             214 :         if (!zobj->guards) {
     284              40 :                 ALLOC_HASHTABLE(zobj->guards);
     285              40 :                 zend_hash_init(zobj->guards, 0, NULL, NULL, 0);
     286             174 :         } else if (zend_hash_quick_find(zobj->guards, property_info->name, property_info->name_length+1, property_info->h, (void **) pguard) == SUCCESS) {
     287             141 :                 return SUCCESS;
     288                 :         }
     289              73 :         stub.in_get = 0;
     290              73 :         stub.in_set = 0;
     291              73 :         stub.in_unset = 0;
     292              73 :         stub.in_isset = 0;
     293              73 :         return zend_hash_quick_add(zobj->guards, property_info->name, property_info->name_length+1, property_info->h, (void**)&stub, sizeof(stub), (void**) pguard);
     294                 : }
     295                 : 
     296                 : zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
     297           21679 : {
     298                 :         zend_object *zobj;
     299           21679 :         zval *tmp_member = NULL;
     300                 :         zval **retval;
     301           21679 :         zval *rv = NULL;
     302                 :         zend_property_info *property_info;
     303                 :         int silent;
     304                 : 
     305           21679 :         silent = (type == BP_VAR_IS);
     306           21679 :         zobj = Z_OBJ_P(object);
     307                 : 
     308           21679 :         if (member->type != IS_STRING) {
     309               4 :                 ALLOC_ZVAL(tmp_member);
     310               4 :                 *tmp_member = *member;
     311               4 :                 INIT_PZVAL(tmp_member);
     312               4 :                 zval_copy_ctor(tmp_member);
     313               4 :                 convert_to_string(tmp_member);
     314               4 :                 member = tmp_member;
     315                 :         }
     316                 : 
     317                 : #if DEBUG_OBJECT_HANDLERS
     318                 :         fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
     319                 : #endif                  
     320                 : 
     321                 :         /* make zend_get_property_info silent if we have getter - we may want to use it */
     322           21679 :         property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__get != NULL) TSRMLS_CC);
     323                 : 
     324           21676 :         if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
     325                 :                 zend_guard *guard;
     326                 : 
     327             425 :                 if (zobj->ce->__get &&
     328                 :                     zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
     329                 :                     !guard->in_get) {
     330                 :                         /* have getter - try with it! */
     331             107 :                         ZVAL_ADDREF(object);
     332             107 :                         guard->in_get = 1; /* prevent circular getting */
     333             107 :                         rv = zend_std_call_getter(object, member TSRMLS_CC);
     334             107 :                         guard->in_get = 0;
     335                 : 
     336             107 :                         if (rv) {
     337             105 :                                 retval = &rv;
     338             105 :                                 if (!rv->is_ref &&
     339                 :                                     (type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET)) {
     340              17 :                                         if (rv->refcount > 0) {
     341               8 :                                                 zval *tmp = rv;
     342                 : 
     343               8 :                                                 ALLOC_ZVAL(rv);
     344               8 :                                                 *rv = *tmp;
     345               8 :                                                 zval_copy_ctor(rv);
     346               8 :                                                 rv->is_ref = 0;
     347               8 :                                                 rv->refcount = 0;
     348                 :                                         }
     349              17 :                                         if (Z_TYPE_P(rv) != IS_OBJECT) {
     350              13 :                                                 zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", zobj->ce->name, Z_STRVAL_P(member));
     351                 :                                         }
     352                 :                                 }
     353                 :                         } else {
     354               2 :                                 retval = &EG(uninitialized_zval_ptr);
     355                 :                         }
     356             107 :                         zval_ptr_dtor(&object);
     357                 :                 } else {
     358             211 :                         if (!silent) {
     359              30 :                                 zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
     360                 :                         }
     361             211 :                         retval = &EG(uninitialized_zval_ptr);
     362                 :                 }
     363                 :         }
     364           21676 :         if (tmp_member) {
     365               4 :                 (*retval)->refcount++;
     366               4 :                 zval_ptr_dtor(&tmp_member);
     367               4 :                 (*retval)->refcount--;
     368                 :         }
     369           21676 :         return *retval;
     370                 : }
     371                 : 
     372                 : 
     373                 : static void zend_std_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
     374          359241 : {
     375                 :         zend_object *zobj;
     376          359241 :         zval *tmp_member = NULL;
     377                 :         zval **variable_ptr;
     378                 :         zend_property_info *property_info;
     379                 : 
     380          359241 :         zobj = Z_OBJ_P(object);
     381                 : 
     382          359241 :         if (member->type != IS_STRING) {
     383               4 :                 ALLOC_ZVAL(tmp_member);
     384               4 :                 *tmp_member = *member;
     385               4 :                 INIT_PZVAL(tmp_member);
     386               4 :                 zval_copy_ctor(tmp_member);
     387               4 :                 convert_to_string(tmp_member);
     388               4 :                 member = tmp_member;
     389                 :         }
     390                 : 
     391          359241 :         property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__set != NULL) TSRMLS_CC);
     392                 : 
     393          368125 :         if (property_info && zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
     394                 :                 /* if we already have this value there, we don't actually need to do anything */
     395            8893 :                 if (*variable_ptr != value) {
     396                 :                         /* if we are assigning reference, we shouldn't move it, but instead assign variable
     397                 :                            to the same pointer */
     398            8882 :                         if (PZVAL_IS_REF(*variable_ptr)) {
     399              39 :                                 zval garbage = **variable_ptr; /* old value should be destroyed */
     400                 : 
     401                 :                                 /* To check: can't *variable_ptr be some system variable like error_zval here? */
     402              39 :                                 (*variable_ptr)->type = value->type;
     403              39 :                                 (*variable_ptr)->value = value->value;
     404              39 :                                 if (value->refcount>0) {
     405              39 :                                         zval_copy_ctor(*variable_ptr);
     406                 :                                 }
     407              39 :                                 zval_dtor(&garbage);
     408                 :                         } else {
     409            8843 :                                 zval *garbage = *variable_ptr;
     410                 : 
     411                 :                                 /* if we assign referenced variable, we should separate it */
     412            8843 :                                 value->refcount++;
     413            8843 :                                 if (PZVAL_IS_REF(value)) {
     414               7 :                                         SEPARATE_ZVAL(&value);
     415                 :                                 }
     416            8843 :                                 *variable_ptr = value;
     417            8843 :                                 zval_ptr_dtor(&garbage);
     418                 :                         }
     419                 :                 }
     420                 :         } else {
     421          350339 :                 int setter_done = 0;
     422                 :                 zend_guard *guard;
     423                 : 
     424          350339 :                 if (zobj->ce->__set &&
     425                 :                     zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
     426                 :                     !guard->in_set) {
     427              61 :                         ZVAL_ADDREF(object);
     428              61 :                         guard->in_set = 1; /* prevent circular setting */
     429              61 :                         if (zend_std_call_setter(object, member, value TSRMLS_CC) != SUCCESS) {
     430                 :                                 /* for now, just ignore it - __set should take care of warnings, etc. */
     431                 :                         }
     432              61 :                         setter_done = 1;
     433              61 :                         guard->in_set = 0;
     434              61 :                         zval_ptr_dtor(&object);
     435                 :                 }
     436          350339 :                 if (!setter_done && property_info) {
     437                 :                         zval **foo;
     438                 : 
     439                 :                         /* if we assign referenced variable, we should separate it */
     440          350277 :                         value->refcount++;
     441          350277 :                         if (PZVAL_IS_REF(value)) {
     442              11 :                                 SEPARATE_ZVAL(&value);
     443                 :                         }
     444          350277 :                         zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo);
     445                 :                 }
     446                 :         }
     447                 : 
     448          359232 :         if (tmp_member) {
     449               4 :                 zval_ptr_dtor(&tmp_member);
     450                 :         }
     451          359232 : }
     452                 : 
     453                 : zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
     454             132 : {
     455             132 :         zend_class_entry *ce = Z_OBJCE_P(object);
     456                 :         zval *retval;
     457                 : 
     458             132 :         if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
     459             131 :                 if(offset == NULL) {
     460                 :                         /* [] construct */
     461               0 :                         ALLOC_INIT_ZVAL(offset);
     462                 :                 } else {
     463             131 :                         SEPARATE_ARG_IF_REF(offset);
     464                 :                 }
     465             131 :                 zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);
     466                 : 
     467             131 :                 zval_ptr_dtor(&offset);
     468                 : 
     469             131 :                 if (!retval) {
     470               1 :                         if (!EG(exception)) {
     471               0 :                                 zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
     472                 :                         }
     473               1 :                         return 0;
     474                 :                 }
     475             130 :                 if (EG(exception)) {
     476               0 :                         zval_ptr_dtor(&retval);
     477               0 :                         return 0;
     478                 :                 }
     479                 : 
     480                 :                 /* Undo PZVAL_LOCK() */
     481             130 :                 retval->refcount--;
     482                 : 
     483             130 :                 return retval;
     484                 :         } else {
     485               1 :                 zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
     486               0 :                 return 0;
     487                 :         }
     488                 : }
     489                 : 
     490                 : 
     491                 : static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
     492              46 : {
     493              46 :         zend_class_entry *ce = Z_OBJCE_P(object);
     494                 : 
     495              46 :         if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
     496              46 :                 if (!offset) {
     497               4 :                         ALLOC_INIT_ZVAL(offset);
     498                 :                 } else {
     499              42 :                         SEPARATE_ARG_IF_REF(offset);
     500                 :                 }
     501              46 :                 zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, offset, value);
     502              46 :                 zval_ptr_dtor(&offset);
     503                 :         } else {
     504               0 :                 zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
     505                 :         }
     506              46 : }
     507                 : 
     508                 : 
     509                 : static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC)
     510              45 : {
     511              45 :         zend_class_entry *ce = Z_OBJCE_P(object);
     512                 :         zval *retval;
     513                 :         int result;
     514                 : 
     515              45 :         if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
     516              45 :                 SEPARATE_ARG_IF_REF(offset);
     517              45 :                 zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", &retval, offset);
     518              45 :                 if (retval) {
     519              43 :                         result = i_zend_is_true(retval);
     520              43 :                         zval_ptr_dtor(&retval);
     521              43 :                         if (check_empty && result && !EG(exception)) {
     522               8 :                                 zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);
     523               8 :                                 if (retval) {
     524               8 :                                         result = i_zend_is_true(retval);
     525               8 :                                         zval_ptr_dtor(&retval);
     526                 :                                 }
     527                 :                         }
     528                 :                 } else {
     529               2 :                         result = 0;
     530                 :                 }
     531              45 :                 zval_ptr_dtor(&offset);
     532                 :         } else {
     533               0 :                 zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
     534               0 :                 return 0;
     535                 :         }
     536              45 :         return result;
     537                 : }
     538                 : 
     539                 : 
     540                 : static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC)
     541            1728 : {
     542                 :         zend_object *zobj;
     543                 :         zval tmp_member;
     544                 :         zval **retval;
     545                 :         zend_property_info *property_info;
     546                 : 
     547            1728 :         zobj = Z_OBJ_P(object);
     548                 : 
     549            1728 :         if (member->type != IS_STRING) {
     550               0 :                 tmp_member = *member;
     551               0 :                 zval_copy_ctor(&tmp_member);
     552               0 :                 convert_to_string(&tmp_member);
     553               0 :                 member = &tmp_member;
     554                 :         }
     555                 : 
     556                 : #if DEBUG_OBJECT_HANDLERS
     557                 :         fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
     558                 : #endif
     559                 : 
     560            1728 :         property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__get != NULL) TSRMLS_CC);
     561                 : 
     562            1727 :         if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
     563                 :                 zval *new_zval;
     564                 :                 zend_guard *guard;
     565                 : 
     566             234 :                 if (!zobj->ce->__get ||
     567                 :                         zend_get_property_guard(zobj, property_info, member, &guard) != SUCCESS ||
     568                 :                         (property_info && guard->in_get)) {
     569                 :                         /* we don't have access controls - will just add it */
     570              99 :                         new_zval = &EG(uninitialized_zval);
     571                 : 
     572                 : /*                      zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */
     573              99 :                         new_zval->refcount++;
     574              99 :                         zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
     575                 :                 } else {
     576                 :                         /* we do have getter - fail and let it try again with usual get/set */
     577              36 :                         retval = NULL;
     578                 :                 }
     579                 :         }
     580            1727 :         if (member == &tmp_member) {
     581               0 :                 zval_dtor(member);
     582                 :         }
     583            1727 :         return retval;
     584                 : }
     585                 : 
     586                 : 
     587                 : static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC)
     588             118 : {
     589                 :         zend_object *zobj;
     590             118 :         zval *tmp_member = NULL;
     591                 :         zend_property_info *property_info;
     592                 : 
     593             118 :         zobj = Z_OBJ_P(object);
     594                 : 
     595             118 :         if (member->type != IS_STRING) {
     596               0 :                 ALLOC_ZVAL(tmp_member);
     597               0 :                 *tmp_member = *member;
     598               0 :                 INIT_PZVAL(tmp_member);
     599               0 :                 zval_copy_ctor(tmp_member);
     600               0 :                 convert_to_string(tmp_member);
     601               0 :                 member = tmp_member;
     602                 :         }
     603                 : 
     604             118 :         property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__unset != NULL) TSRMLS_CC);
     605                 : 
     606             117 :         if (!property_info || zend_hash_del(zobj->properties, property_info->name, property_info->name_length+1) == FAILURE) {
     607                 :                 zend_guard *guard;
     608                 : 
     609              13 :                 if (zobj->ce->__unset &&
     610                 :                     zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
     611                 :                     !guard->in_unset) {
     612                 :                         /* have unseter - try with it! */
     613               5 :                         ZVAL_ADDREF(object);
     614               5 :                         guard->in_unset = 1; /* prevent circular unsetting */
     615               5 :                         zend_std_call_unsetter(object, member TSRMLS_CC);
     616               5 :                         guard->in_unset = 0;
     617               5 :                         zval_ptr_dtor(&object);
     618                 :                 }
     619                 :         }
     620                 : 
     621             117 :         if (tmp_member) {
     622               0 :                 zval_ptr_dtor(&tmp_member);
     623                 :         }
     624             117 : }
     625                 : 
     626                 : 
     627                 : static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC)
     628              23 : {
     629              23 :         zend_class_entry *ce = Z_OBJCE_P(object);
     630                 : 
     631              23 :         if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
     632              23 :                 SEPARATE_ARG_IF_REF(offset);
     633              23 :                 zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", NULL, offset);
     634              23 :                 zval_ptr_dtor(&offset);
     635                 :         } else {
     636               0 :                 zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
     637                 :         }
     638              23 : }
     639                 : 
     640                 : 
     641                 : ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS)
     642             379 : {
     643             379 :         zend_internal_function *func = (zend_internal_function *)EG(function_state_ptr)->function;
     644                 :         zval *method_name_ptr, *method_args_ptr;
     645             379 :         zval *method_result_ptr = NULL;
     646             379 :         zend_class_entry *ce = Z_OBJCE_P(this_ptr);
     647                 : 
     648             379 :         ALLOC_ZVAL(method_args_ptr);
     649             379 :         INIT_PZVAL(method_args_ptr);
     650             379 :         array_init(method_args_ptr);
     651                 : 
     652             379 :         if (zend_copy_parameters_array(ZEND_NUM_ARGS(), method_args_ptr TSRMLS_CC) == FAILURE) {
     653               0 :                 zval_dtor(method_args_ptr);
     654               0 :                 zend_error(E_ERROR, "Cannot get arguments for __call");
     655               0 :                 RETURN_FALSE;
     656                 :         }
     657                 : 
     658             379 :         ALLOC_ZVAL(method_name_ptr);
     659             379 :         INIT_PZVAL(method_name_ptr);
     660             379 :         ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
     661                 : 
     662                 :         /* __call handler is called with two arguments:
     663                 :            method name
     664                 :            array of method parameters
     665                 : 
     666                 :         */
     667             379 :         zend_call_method_with_2_params(&this_ptr, ce, &ce->__call, ZEND_CALL_FUNC_NAME, &method_result_ptr, method_name_ptr, method_args_ptr);
     668                 : 
     669             371 :         if (method_result_ptr) {
     670             365 :                 if (method_result_ptr->is_ref || method_result_ptr->refcount > 1) {
     671               2 :                         RETVAL_ZVAL(method_result_ptr, 1, 1);
     672                 :                 } else {
     673             361 :                         RETVAL_ZVAL(method_result_ptr, 0, 1);
     674                 :                 }
     675                 :         }
     676                 : 
     677                 :         /* now destruct all auxiliaries */
     678             371 :         zval_ptr_dtor(&method_args_ptr);
     679             371 :         zval_ptr_dtor(&method_name_ptr);
     680                 : 
     681                 :         /* destruct the function also, then - we have allocated it in get_method */
     682             371 :         efree(func);
     683                 : }
     684                 : 
     685                 : /* Ensures that we're allowed to call a private method.
     686                 :  * Returns the function address that should be called, or NULL
     687                 :  * if no such function exists.
     688                 :  */
     689                 : static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC)
     690              67 : {
     691              67 :         if (!ce) {
     692               4 :                 return 0;
     693                 :         }
     694                 : 
     695                 :         /* We may call a private function if:
     696                 :          * 1.  The class of our object is the same as the scope, and the private
     697                 :          *     function (EX(fbc)) has the same scope.
     698                 :          * 2.  One of our parent classes are the same as the scope, and it contains
     699                 :          *     a private function with the same name that has the same scope.
     700                 :          */
     701              63 :         if (fbc->common.scope == ce && EG(scope) == ce) {
     702                 :                 /* rule #1 checks out ok, allow the function call */
     703              34 :                 return fbc;
     704                 :         }
     705                 : 
     706                 : 
     707                 :         /* Check rule #2 */
     708              29 :         ce = ce->parent;
     709              68 :         while (ce) {
     710              14 :                 if (ce == EG(scope)) {
     711               4 :                         if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==SUCCESS
     712                 :                                 && fbc->op_array.fn_flags & ZEND_ACC_PRIVATE
     713                 :                                 && fbc->common.scope == EG(scope)) {
     714               4 :                                 return fbc;
     715                 :                         }
     716               0 :                         break;
     717                 :                 }
     718              10 :                 ce = ce->parent;
     719                 :         }
     720              25 :         return NULL;
     721                 : }
     722                 : 
     723                 : 
     724                 : ZEND_API int zend_check_private(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC)
     725              21 : {
     726              21 :         return zend_check_private_int(fbc, ce, function_name_strval, function_name_strlen TSRMLS_CC) != NULL;
     727                 : }
     728                 : 
     729                 : 
     730                 : /* Ensures that we're allowed to call a protected method.
     731                 :  */
     732                 : ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope)
     733            5094 : {
     734            5094 :         zend_class_entry *fbc_scope = ce;
     735                 : 
     736                 :         /* Is the context that's calling the function, the same as one of
     737                 :          * the function's parents?
     738                 :          */
     739           10556 :         while (fbc_scope) {
     740            5250 :                 if (fbc_scope==scope) {
     741            4882 :                         return 1;
     742                 :                 }
     743             368 :                 fbc_scope = fbc_scope->parent;
     744                 :         }
     745                 : 
     746                 :         /* Is the function's scope the same as our current object context,
     747                 :          * or any of the parents of our context?
     748                 :          */
     749             548 :         while (scope) {
     750             229 :                 if (scope==ce) {
     751             105 :                         return 1;
     752                 :                 }
     753             124 :                 scope = scope->parent;
     754                 :         }
     755             107 :         return 0;
     756                 : }
     757                 : 
     758                 : 
     759                 : static inline zend_class_entry * zend_get_function_root_class(zend_function *fbc)
     760              52 : {
     761              52 :         return fbc->common.prototype ? fbc->common.prototype->common.scope : fbc->common.scope;
     762                 : }
     763                 : 
     764                 : 
     765                 : static inline union _zend_function *zend_get_user_call_function(zend_class_entry *ce, const char *method_name, int method_len) /* {{{ */
     766             381 : {
     767             381 :         zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
     768             381 :         call_user_call->type = ZEND_INTERNAL_FUNCTION;
     769             381 :         call_user_call->module = ce->module;
     770             381 :         call_user_call->handler = zend_std_call_user_call;
     771             381 :         call_user_call->arg_info = NULL;
     772             381 :         call_user_call->num_args = 0;
     773             381 :         call_user_call->scope = ce;
     774             381 :         call_user_call->fn_flags = 0;
     775             381 :         call_user_call->function_name = estrndup(method_name, method_len);
     776             381 :         call_user_call->pass_rest_by_reference = 0;
     777             381 :         call_user_call->return_reference = ZEND_RETURN_VALUE;
     778                 : 
     779             381 :         return (union _zend_function *)call_user_call;
     780                 : }
     781                 : /* }}} */
     782                 : 
     783                 : static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC)
     784          206627 : {
     785                 :         zend_object *zobj;
     786                 :         zend_function *fbc;
     787                 :         char *lc_method_name;
     788          206627 :         zval *object = *object_ptr;
     789                 :         ALLOCA_FLAG(use_heap)
     790                 :         
     791          206627 :         lc_method_name = do_alloca_with_limit(method_len+1, use_heap);
     792                 :         /* Create a zend_copy_str_tolower(dest, src, src_length); */
     793          206627 :         zend_str_tolower_copy(lc_method_name, method_name, method_len);
     794                 :                 
     795          206627 :         zobj = Z_OBJ_P(object);
     796          206627 :         if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) {
     797             464 :                 free_alloca_with_limit(lc_method_name, use_heap);
     798             464 :                 if (zobj->ce->__call) {
     799             360 :                         return zend_get_user_call_function(zobj->ce, method_name, method_len);
     800                 :                 } else {
     801             104 :                         return NULL;
     802                 :                 }
     803                 :         }
     804                 : 
     805                 :         /* Check access level */
     806          206163 :         if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
     807                 :                 zend_function *updated_fbc;
     808                 : 
     809                 :                 /* Ensure that if we're calling a private function, we're allowed to do so.
     810                 :                  * If we're not and __call() handler exists, invoke it, otherwise error out.
     811                 :                  */
     812              30 :                 updated_fbc = zend_check_private_int(fbc, Z_OBJ_HANDLER_P(object, get_class_entry)(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC);
     813              30 :                 if (updated_fbc) {
     814              24 :                         fbc = updated_fbc;
     815                 :                 } else {
     816               6 :                         if (zobj->ce->__call) {
     817               2 :                                 fbc = zend_get_user_call_function(zobj->ce, method_name, method_len);
     818                 :                         } else {
     819               4 :                                 zend_error(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 : "");
     820                 :                         }
     821                 :                 }
     822                 :         } else {
     823                 :                 /* Ensure that we haven't overridden a private function and end up calling
     824                 :                  * the overriding public function...
     825                 :                  */
     826          206133 :                 if (EG(scope) &&
     827                 :                     is_derived_class(fbc->common.scope, EG(scope)) &&
     828                 :                     fbc->op_array.fn_flags & ZEND_ACC_CHANGED) {
     829                 :                         zend_function *priv_fbc;
     830                 : 
     831               8 :                         if (zend_hash_find(&EG(scope)->function_table, lc_method_name, method_len+1, (void **) &priv_fbc)==SUCCESS
     832                 :                                 && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
     833                 :                                 && priv_fbc->common.scope == EG(scope)) {
     834               7 :                                 fbc = priv_fbc;
     835                 :                         }
     836                 :                 }
     837          206133 :                 if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
     838                 :                         /* Ensure that if we're calling a protected function, we're allowed to do so.
     839                 :                          * If we're not and __call() handler exists, invoke it, otherwise error out.
     840                 :                          */
     841              36 :                         if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {
     842               9 :                                 if (zobj->ce->__call) {
     843               2 :                                         fbc = zend_get_user_call_function(zobj->ce, method_name, method_len);
     844                 :                                 } else {
     845               7 :                                         zend_error(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 : "");
     846                 :                                 }
     847                 :                         }
     848                 :                 }
     849                 :         }
     850                 : 
     851          206152 :         free_alloca_with_limit(lc_method_name, use_heap);
     852          206152 :         return fbc;
     853                 : }
     854                 : 
     855                 : 
     856                 : /* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */
     857                 : ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC)
     858            2438 : {
     859                 :         char *lc_function_name;
     860                 :         zend_function *fbc;     
     861                 :         
     862            2438 :         lc_function_name = zend_str_tolower_dup(function_name_strval, function_name_strlen);
     863                 : 
     864            2438 :         if (zend_hash_find(&ce->function_table, lc_function_name, function_name_strlen+1, (void **) &fbc)==FAILURE) {
     865              18 :                 efree(lc_function_name);
     866                 : 
     867              18 :                 if (ce->__call &&
     868                 :                     EG(This) &&
     869                 :                     Z_OBJ_HT_P(EG(This))->get_class_entry &&
     870                 :                     instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
     871              17 :                         return zend_get_user_call_function(ce, function_name_strval, function_name_strlen);
     872                 :                 } else {
     873               1 :                         char *class_name = ce->name;
     874                 : 
     875               1 :                         if (!class_name) {
     876               0 :                                 class_name = "";
     877                 :                         }
     878               1 :                         zend_error(E_ERROR, "Call to undefined method %s::%s()", class_name, function_name_strval);
     879                 :                 }
     880                 :         }
     881            2420 :         efree(lc_function_name);
     882                 : 
     883            2420 :         if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) {
     884                 :                 /* No further checks necessary, most common case */
     885              26 :         } else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
     886                 :                 zend_function *updated_fbc;
     887                 : 
     888                 :                 /* Ensure that if we're calling a private function, we're allowed to do so.
     889                 :                  */
     890              16 :                 updated_fbc = zend_check_private_int(fbc, EG(scope), function_name_strval, function_name_strlen TSRMLS_CC);
     891              16 :                 if (!updated_fbc) {
     892               6 :                         zend_error(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 : "");
     893                 :                 }
     894              10 :                 fbc = updated_fbc;
     895              10 :         } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
     896                 :                 /* Ensure that if we're calling a protected function, we're allowed to do so.
     897                 :                  */
     898              10 :                 if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {
     899               2 :                         zend_error(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 : "");
     900                 :                 }
     901                 :         }
     902                 : 
     903            2412 :         return fbc;
     904                 : }
     905                 : 
     906                 : 
     907                 : ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent TSRMLS_DC)
     908             575 : {
     909             575 :         zval **retval = NULL;
     910             575 :         zend_class_entry *tmp_ce = ce;
     911                 :         zend_property_info *property_info;
     912                 :         zend_property_info std_property_info;
     913                 : 
     914             575 :         if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
     915              20 :                 std_property_info.flags = ZEND_ACC_PUBLIC;
     916              20 :                 std_property_info.name = property_name;
     917              20 :                 std_property_info.name_length = property_name_len;
     918              20 :                 std_property_info.h = zend_get_hash_value(std_property_info.name, std_property_info.name_length+1);
     919              20 :                 std_property_info.ce = ce;
     920              20 :                 property_info = &std_property_info;
     921                 :         }
     922                 : 
     923                 : #if DEBUG_OBJECT_HANDLERS
     924                 :         zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
     925                 : #endif
     926                 : 
     927             575 :         if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) {
     928              14 :                 if (!silent) {
     929               2 :                         zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
     930                 :                 }
     931              12 :                 return NULL;
     932                 :         }
     933                 : 
     934             561 :         zend_update_class_constants(tmp_ce TSRMLS_CC);
     935                 : 
     936             561 :         zend_hash_quick_find(CE_STATIC_MEMBERS(tmp_ce), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
     937                 : 
     938             561 :         if (!retval) {
     939              10 :                 if (silent) {
     940               5 :                         return NULL;
     941                 :                 } else {
     942               5 :                         zend_error(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
     943                 :                 }
     944                 :         }
     945                 : 
     946             551 :         return retval;
     947                 : }
     948                 : 
     949                 : 
     950                 : ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC)
     951               0 : {
     952               0 :         zend_error(E_ERROR, "Attempt to unset static property %s::$%s", ce->name, property_name);
     953               0 :         return 0;
     954                 : }
     955                 : 
     956                 : 
     957                 : ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC)
     958          109644 : {
     959          109644 :         zend_object *zobj = Z_OBJ_P(object);
     960          109644 :         zend_function *constructor = zobj->ce->constructor;
     961                 : 
     962          109644 :         if (constructor) {
     963            4438 :                 if (constructor->op_array.fn_flags & ZEND_ACC_PUBLIC) {
     964                 :                         /* No further checks necessary */
     965              15 :                 } else if (constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
     966                 :                         /* Ensure that if we're calling a private function, we're allowed to do so.
     967                 :                          */
     968               9 :                         if (constructor->common.scope != EG(scope)) {
     969               3 :                                 if (EG(scope)) {
     970               1 :                                         zend_error(E_ERROR, "Call to private %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name);
     971                 :                                 } else {
     972               2 :                                         zend_error(E_ERROR, "Call to private %s::%s() from invalid context", constructor->common.scope->name, constructor->common.function_name);
     973                 :                                 }
     974                 :                         }
     975               6 :                 } else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
     976                 :                         /* Ensure that if we're calling a protected function, we're allowed to do so.
     977                 :                          */
     978               6 :                         if (!zend_check_protected(zend_get_function_root_class(constructor), EG(scope))) {
     979               2 :                                 if (EG(scope)) {
     980               1 :                                         zend_error(E_ERROR, "Call to protected %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name);
     981                 :                                 } else {
     982               1 :                                         zend_error(E_ERROR, "Call to protected %s::%s() from invalid context", constructor->common.scope->name, constructor->common.function_name);
     983                 :                                 }
     984                 :                         }
     985                 :                 }
     986                 :         }
     987                 : 
     988          109639 :         return constructor;
     989                 : }
     990                 : 
     991                 : 
     992                 : int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC);
     993                 : 
     994                 : 
     995                 : static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC)
     996             345 : {
     997                 :         zend_object *zobj1, *zobj2;
     998                 : 
     999             345 :         zobj1 = Z_OBJ_P(o1);
    1000             345 :         zobj2 = Z_OBJ_P(o2);
    1001                 : 
    1002             345 :         if (zobj1->ce != zobj2->ce) {
    1003              33 :                 return 1; /* different classes */
    1004                 :         }
    1005             312 :         return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC);
    1006                 : }
    1007                 : 
    1008                 : static int zend_std_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC)
    1009             242 : {
    1010                 :         zend_object *zobj;
    1011                 :         int result;
    1012                 :         zval **value;
    1013             242 :         zval *tmp_member = NULL;
    1014                 :         zend_property_info *property_info;
    1015                 : 
    1016             242 :         zobj = Z_OBJ_P(object);
    1017                 : 
    1018             242 :         if (member->type != IS_STRING) {
    1019               4 :                 ALLOC_ZVAL(tmp_member);
    1020               4 :                 *tmp_member = *member;
    1021               4 :                 INIT_PZVAL(tmp_member);
    1022               4 :                 zval_copy_ctor(tmp_member);
    1023               4 :                 convert_to_string(tmp_member);
    1024               4 :                 member = tmp_member;
    1025                 :         }
    1026                 : 
    1027                 : #if DEBUG_OBJECT_HANDLERS
    1028                 :         fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
    1029                 : #endif
    1030                 : 
    1031             242 :         property_info = zend_get_property_info(zobj->ce, member, 1 TSRMLS_CC);
    1032                 : 
    1033             364 :         if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) {
    1034                 :                 zend_guard *guard;
    1035                 : 
    1036             122 :                 result = 0;
    1037             122 :                 if ((has_set_exists != 2) &&
    1038                 :                     zobj->ce->__isset &&
    1039                 :                     zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
    1040                 :                     !guard->in_isset) {
    1041                 :                         zval *rv;
    1042                 : 
    1043                 :                         /* have issetter - try with it! */
    1044               3 :                         ZVAL_ADDREF(object);
    1045               3 :                         guard->in_isset = 1; /* prevent circular getting */
    1046               3 :                         rv = zend_std_call_issetter(object, member TSRMLS_CC);
    1047               3 :                         if (rv) {
    1048               3 :                                 result = zend_is_true(rv);
    1049               3 :                                 zval_ptr_dtor(&rv);
    1050               3 :                                 if (has_set_exists && result && !EG(exception) && zobj->ce->__get && !guard->in_get) {
    1051               0 :                                         guard->in_get = 1;
    1052               0 :                                         rv = zend_std_call_getter(object, member TSRMLS_CC);
    1053               0 :                                         guard->in_get = 0;
    1054               0 :                                         if (rv) {
    1055               0 :                                                 rv->refcount++;
    1056               0 :                                                 result = i_zend_is_true(rv);
    1057               0 :                                                 zval_ptr_dtor(&rv);
    1058                 :                                         }
    1059                 :                                 }
    1060                 :                         }
    1061               3 :                         guard->in_isset = 0;
    1062               3 :                         zval_ptr_dtor(&object);
    1063                 :                 }
    1064                 :         } else {
    1065             120 :                 switch (has_set_exists) {
    1066                 :                 case 0:
    1067              59 :                         result = (Z_TYPE_PP(value) != IS_NULL);
    1068              59 :                         break;
    1069                 :                 default:
    1070              20 :                         result = zend_is_true(*value);
    1071              20 :                         break;
    1072                 :                 case 2:
    1073              41 :                         result = 1;
    1074                 :                         break;
    1075                 :                 }
    1076                 :         }
    1077                 : 
    1078             242 :         if (tmp_member) {
    1079               4 :                 zval_ptr_dtor(&tmp_member);
    1080                 :         }
    1081             242 :         return result;
    1082                 : }
    1083                 : 
    1084                 : 
    1085                 : zend_class_entry *zend_std_object_get_class(zval *object TSRMLS_DC)
    1086          130614 : {
    1087                 :         zend_object *zobj;
    1088          130614 :         zobj = Z_OBJ_P(object);
    1089                 : 
    1090          130614 :         return zobj->ce;
    1091                 : }
    1092                 : 
    1093                 : int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
    1094            3835 : {
    1095                 :         zend_object *zobj;
    1096                 :         zend_class_entry *ce;
    1097            3835 :         zobj = Z_OBJ_P(object);
    1098                 : 
    1099            3835 :         if (parent) {
    1100               7 :                 if (!zobj->ce->parent) {
    1101               4 :                         return FAILURE;
    1102                 :                 }
    1103               3 :                 ce = zobj->ce->parent;
    1104                 :         } else {
    1105            3828 :                 ce = zobj->ce;
    1106                 :         }
    1107                 : 
    1108            3831 :         *class_name_len = ce->name_length;
    1109            3831 :         *class_name = estrndup(ce->name, ce->name_length);
    1110            3831 :         return SUCCESS;
    1111                 : }
    1112                 : 
    1113                 : ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC)
    1114          173016 : {
    1115                 :         zval *retval;
    1116                 :         zend_class_entry *ce;
    1117                 : 
    1118          173016 :         switch (type) {
    1119                 :                 case IS_STRING:
    1120          101640 :                         ce = Z_OBJCE_P(readobj);
    1121          101640 :                         if (ce->__tostring &&
    1122                 :                 (zend_call_method_with_0_params(&readobj, ce, &ce->__tostring, "__tostring", &retval) || EG(exception))) {
    1123          101052 :                 if (EG(exception)) {
    1124               3 :                         if (retval) {
    1125               1 :                                 zval_ptr_dtor(&retval);
    1126                 :                         }
    1127               3 :                                         zend_error(E_ERROR, "Method %s::__toString() must not throw an exception", ce->name);
    1128               0 :                         return FAILURE;
    1129                 :                 }
    1130          101049 :                                 if (Z_TYPE_P(retval) == IS_STRING) {
    1131          101045 :                                         INIT_PZVAL(writeobj);
    1132          101045 :                                         if (readobj == writeobj) {
    1133          100132 :                                                 zval_dtor(readobj);
    1134                 :                                         }
    1135          101045 :                                         ZVAL_ZVAL(writeobj, retval, 1, 1);
    1136          101045 :                                         if (Z_TYPE_P(writeobj) != type) {
    1137               0 :                                                 convert_to_explicit_type(writeobj, type);
    1138                 :                                         }
    1139          101045 :                                         return SUCCESS;
    1140                 :                                 } else {
    1141               4 :                                         zval_ptr_dtor(&retval);
    1142               4 :                                         INIT_PZVAL(writeobj);
    1143               4 :                                         if (readobj == writeobj) {
    1144               0 :                                                 zval_dtor(readobj);
    1145                 :                                         }
    1146               4 :                                         ZVAL_EMPTY_STRING(writeobj);
    1147               4 :                                         zend_error(E_RECOVERABLE_ERROR, "Method %s::__toString() must return a string value", ce->name);
    1148               4 :                                         return SUCCESS;
    1149                 :                                 }
    1150                 :                         }
    1151             588 :                         return FAILURE;
    1152                 :                 case IS_BOOL:
    1153           71058 :                         INIT_PZVAL(writeobj);
    1154           71058 :                         ZVAL_BOOL(writeobj, 1);
    1155           71058 :                         return SUCCESS;
    1156                 :                 case IS_LONG:
    1157             192 :                         ce = Z_OBJCE_P(readobj);
    1158             192 :                         zend_error(E_NOTICE, "Object of class %s could not be converted to int", ce->name);
    1159             192 :                         INIT_PZVAL(writeobj);
    1160             192 :                         if (readobj == writeobj) {
    1161               0 :                                 zval_dtor(readobj);
    1162                 :                         }
    1163             192 :                         ZVAL_LONG(writeobj, 1);
    1164             192 :                         return SUCCESS;
    1165                 :                 case IS_DOUBLE:
    1166              58 :                         ce = Z_OBJCE_P(readobj);
    1167              58 :                         zend_error(E_NOTICE, "Object of class %s could not be converted to double", ce->name);
    1168              58 :                         INIT_PZVAL(writeobj);
    1169              58 :                         if (readobj == writeobj) {
    1170               0 :                                 zval_dtor(readobj);
    1171                 :                         }
    1172              58 :                         ZVAL_DOUBLE(writeobj, 1);
    1173              58 :                         return SUCCESS;
    1174                 :                 default:
    1175              68 :                         INIT_PZVAL(writeobj);
    1176              68 :                         Z_TYPE_P(writeobj) = IS_NULL;
    1177                 :                         break;
    1178                 :         }
    1179              68 :         return FAILURE;
    1180                 : }
    1181                 : 
    1182                 : 
    1183                 : ZEND_API zend_object_handlers std_object_handlers = {
    1184                 :         zend_objects_store_add_ref,                             /* add_ref */
    1185                 :         zend_objects_store_del_ref,                             /* del_ref */
    1186                 :         zend_objects_clone_obj,                                 /* clone_obj */
    1187                 : 
    1188                 :         zend_std_read_property,                                 /* read_property */
    1189                 :         zend_std_write_property,                                /* write_property */
    1190                 :         zend_std_read_dimension,                                /* read_dimension */
    1191                 :         zend_std_write_dimension,                               /* write_dimension */
    1192                 :         zend_std_get_property_ptr_ptr,                  /* get_property_ptr_ptr */
    1193                 :         NULL,                                                                   /* get */
    1194                 :         NULL,                                                                   /* set */
    1195                 :         zend_std_has_property,                                  /* has_property */
    1196                 :         zend_std_unset_property,                                /* unset_property */
    1197                 :         zend_std_has_dimension,                                 /* has_dimension */
    1198                 :         zend_std_unset_dimension,                               /* unset_dimension */
    1199                 :         zend_std_get_properties,                                /* get_properties */
    1200                 :         zend_std_get_method,                                    /* get_method */
    1201                 :         NULL,                                                                   /* call_method */
    1202                 :         zend_std_get_constructor,                               /* get_constructor */
    1203                 :         zend_std_object_get_class,                              /* get_class_entry */
    1204                 :         zend_std_object_get_class_name,                 /* get_class_name */
    1205                 :         zend_std_compare_objects,                               /* compare_objects */
    1206                 :         zend_std_cast_object_tostring,                  /* cast_object */
    1207                 :         NULL,                                                                   /* count_elements */
    1208                 : };
    1209                 : 
    1210                 : /*
    1211                 :  * Local variables:
    1212                 :  * tab-width: 4
    1213                 :  * c-basic-offset: 4
    1214                 :  * indent-tabs-mode: t
    1215                 :  * End:
    1216                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:04 +0000 (5 days ago)

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