root/Zend/zend_object_handlers.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rebuild_object_properties
  2. zend_std_get_properties
  3. zend_std_get_gc
  4. zend_std_get_debug_info
  5. zend_std_call_getter
  6. zend_std_call_setter
  7. zend_std_call_unsetter
  8. zend_std_call_issetter
  9. zend_verify_property_access
  10. is_derived_class
  11. zend_get_property_offset
  12. zend_get_property_info
  13. zend_check_property_access
  14. zend_property_guard_dtor
  15. zend_get_property_guard
  16. zend_std_read_property
  17. zend_std_write_property
  18. zend_std_read_dimension
  19. zend_std_write_dimension
  20. zend_std_has_dimension
  21. zend_std_get_property_ptr_ptr
  22. zend_std_unset_property
  23. zend_std_unset_dimension
  24. zend_check_private_int
  25. zend_check_private
  26. zend_check_protected
  27. zend_get_call_trampoline_func
  28. zend_get_user_call_function
  29. zend_std_get_method
  30. zend_get_user_callstatic_function
  31. zend_std_get_static_method
  32. zend_std_get_static_property
  33. zend_std_unset_static_property
  34. zend_std_get_constructor
  35. zend_std_compare_objects
  36. zend_std_has_property
  37. zend_std_object_get_class_name
  38. zend_std_cast_object_tostring
  39. zend_std_get_closure

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

/* [<][>][^][v][top][bottom][index][help] */