root/Zend/zend_API.c

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

DEFINITIONS

This source file includes following definitions.
  1. zend_get_parameters
  2. zend_get_parameters_ex
  3. _zend_get_parameters_array_ex
  4. zend_copy_parameters_array
  5. zend_wrong_param_count
  6. zend_get_type_by_const
  7. zend_zval_type_name
  8. zend_wrong_paramers_count_error
  9. zend_wrong_paramer_type_error
  10. zend_wrong_paramer_class_error
  11. zend_wrong_callback_error
  12. zend_parse_arg_class
  13. zend_parse_arg_bool_weak
  14. zend_parse_arg_bool_slow
  15. zend_parse_arg_long_weak
  16. zend_parse_arg_long_slow
  17. zend_parse_arg_long_cap_weak
  18. zend_parse_arg_long_cap_slow
  19. zend_parse_arg_double_weak
  20. zend_parse_arg_double_slow
  21. zend_parse_arg_str_weak
  22. zend_parse_arg_str_slow
  23. zend_parse_arg_impl
  24. zend_parse_arg
  25. zend_parse_parameter
  26. zend_parse_parameters_debug_error
  27. zend_parse_va_args
  28. zend_parse_parameters_ex
  29. zend_parse_parameters
  30. zend_parse_parameters_throw
  31. zend_parse_method_parameters
  32. zend_parse_method_parameters_ex
  33. _array_init
  34. zend_merge_properties
  35. zend_update_class_constants
  36. object_properties_init
  37. object_properties_init_ex
  38. object_properties_load
  39. _object_and_properties_init
  40. _object_init_ex
  41. _object_init
  42. add_assoc_long_ex
  43. add_assoc_null_ex
  44. add_assoc_bool_ex
  45. add_assoc_resource_ex
  46. add_assoc_double_ex
  47. add_assoc_str_ex
  48. add_assoc_string_ex
  49. add_assoc_stringl_ex
  50. add_assoc_zval_ex
  51. add_index_long
  52. add_index_null
  53. add_index_bool
  54. add_index_resource
  55. add_index_double
  56. add_index_str
  57. add_index_string
  58. add_index_stringl
  59. add_index_zval
  60. add_next_index_long
  61. add_next_index_null
  62. add_next_index_bool
  63. add_next_index_resource
  64. add_next_index_double
  65. add_next_index_str
  66. add_next_index_string
  67. add_next_index_stringl
  68. add_next_index_zval
  69. add_get_assoc_string_ex
  70. add_get_assoc_stringl_ex
  71. add_get_index_long
  72. add_get_index_double
  73. add_get_index_str
  74. add_get_index_string
  75. add_get_index_stringl
  76. array_set_zval_key
  77. add_property_long_ex
  78. add_property_bool_ex
  79. add_property_null_ex
  80. add_property_resource_ex
  81. add_property_double_ex
  82. add_property_str_ex
  83. add_property_string_ex
  84. add_property_stringl_ex
  85. add_property_zval_ex
  86. zend_startup_module_ex
  87. zend_startup_module_zval
  88. zend_sort_modules
  89. zend_collect_module_handlers
  90. zend_startup_modules
  91. zend_destroy_modules
  92. zend_register_module_ex
  93. zend_register_internal_module
  94. zend_check_magic_method_implementation
  95. zend_register_functions
  96. zend_unregister_functions
  97. zend_startup_module
  98. zend_get_module_started
  99. clean_module_class
  100. clean_module_classes
  101. module_destructor
  102. zend_activate_modules
  103. module_registry_cleanup
  104. zend_deactivate_modules
  105. zend_cleanup_internal_classes
  106. module_registry_unload_temp
  107. module_registry_unload_temp_wrapper
  108. exec_done_cb
  109. zend_post_deactivate_modules
  110. zend_next_free_module
  111. do_register_internal_class
  112. zend_register_internal_class_ex
  113. zend_class_implements
  114. zend_register_internal_class
  115. zend_register_internal_interface
  116. zend_register_class_alias_ex
  117. zend_set_hash_symbol
  118. ZEND_FUNCTION
  119. zend_disable_function
  120. display_disabled_class
  121. zend_disable_class
  122. zend_is_callable_check_class
  123. zend_is_callable_check_func
  124. zend_is_callable_ex
  125. zend_is_callable
  126. zend_make_callable
  127. zend_fcall_info_init
  128. zend_fcall_info_args_clear
  129. zend_fcall_info_args_save
  130. zend_fcall_info_args_restore
  131. zend_fcall_info_args_ex
  132. zend_fcall_info_args
  133. zend_fcall_info_argp
  134. zend_fcall_info_argv
  135. zend_fcall_info_argn
  136. zend_fcall_info_call
  137. zend_get_module_version
  138. zend_declare_property_ex
  139. zend_declare_property
  140. zend_declare_property_null
  141. zend_declare_property_bool
  142. zend_declare_property_long
  143. zend_declare_property_double
  144. zend_declare_property_string
  145. zend_declare_property_stringl
  146. zend_declare_class_constant
  147. zend_declare_class_constant_null
  148. zend_declare_class_constant_long
  149. zend_declare_class_constant_bool
  150. zend_declare_class_constant_double
  151. zend_declare_class_constant_stringl
  152. zend_declare_class_constant_string
  153. zend_update_property_ex
  154. zend_update_property
  155. zend_update_property_null
  156. zend_update_property_bool
  157. zend_update_property_long
  158. zend_update_property_double
  159. zend_update_property_str
  160. zend_update_property_string
  161. zend_update_property_stringl
  162. zend_update_static_property
  163. zend_update_static_property_null
  164. zend_update_static_property_bool
  165. zend_update_static_property_long
  166. zend_update_static_property_double
  167. zend_update_static_property_string
  168. zend_update_static_property_stringl
  169. zend_read_property
  170. zend_read_static_property
  171. zend_save_error_handling
  172. zend_replace_error_handling
  173. same_zval
  174. zend_restore_error_handling
  175. zend_find_alias_name
  176. zend_resolve_method_name
  177. zend_get_object_type

   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    |          Andrei Zmievski <andrei@php.net>                            |
  18    |          Dmitry Stogov <dmitry@zend.com>                             |
  19    +----------------------------------------------------------------------+
  20 */
  21 
  22 /* $Id$ */
  23 
  24 #include "zend.h"
  25 #include "zend_execute.h"
  26 #include "zend_API.h"
  27 #include "zend_modules.h"
  28 #include "zend_extensions.h"
  29 #include "zend_constants.h"
  30 #include "zend_exceptions.h"
  31 #include "zend_closures.h"
  32 #include "zend_inheritance.h"
  33 
  34 #ifdef HAVE_STDARG_H
  35 #include <stdarg.h>
  36 #endif
  37 
  38 /* these variables are true statics/globals, and have to be mutex'ed on every access */
  39 ZEND_API HashTable module_registry;
  40 
  41 static zend_module_entry **module_request_startup_handlers;
  42 static zend_module_entry **module_request_shutdown_handlers;
  43 static zend_module_entry **module_post_deactivate_handlers;
  44 
  45 static zend_class_entry  **class_cleanup_handlers;
  46 
  47 /* this function doesn't check for too many parameters */
  48 ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
  49 {
  50         int arg_count;
  51         va_list ptr;
  52         zval **param, *param_ptr;
  53 
  54         param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
  55         arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
  56 
  57         if (param_count>arg_count) {
  58                 return FAILURE;
  59         }
  60 
  61         va_start(ptr, param_count);
  62 
  63         while (param_count-->0) {
  64                 param = va_arg(ptr, zval **);
  65                 if (!Z_ISREF_P(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
  66                         zval new_tmp;
  67 
  68                         ZVAL_DUP(&new_tmp, param_ptr);
  69                         Z_DELREF_P(param_ptr);
  70                         ZVAL_COPY_VALUE(param_ptr, &new_tmp);
  71                 }
  72                 *param = param_ptr;
  73                 param_ptr++;
  74         }
  75         va_end(ptr);
  76 
  77         return SUCCESS;
  78 }
  79 /* }}} */
  80 
  81 /* Zend-optimized Extended functions */
  82 /* this function doesn't check for too many parameters */
  83 ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
  84 {
  85         int arg_count;
  86         va_list ptr;
  87         zval **param, *param_ptr;
  88 
  89         param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
  90         arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
  91 
  92         if (param_count>arg_count) {
  93                 return FAILURE;
  94         }
  95 
  96         va_start(ptr, param_count);
  97         while (param_count-->0) {
  98                 param = va_arg(ptr, zval **);
  99                 *param = param_ptr;
 100                 param_ptr++;
 101         }
 102         va_end(ptr);
 103 
 104         return SUCCESS;
 105 }
 106 /* }}} */
 107 
 108 ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array) /* {{{ */
 109 {
 110         zval *param_ptr;
 111         int arg_count;
 112 
 113         param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
 114         arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
 115 
 116         if (param_count>arg_count) {
 117                 return FAILURE;
 118         }
 119 
 120         while (param_count-->0) {
 121                 ZVAL_COPY_VALUE(argument_array, param_ptr);
 122                 argument_array++;
 123                 param_ptr++;
 124         }
 125 
 126         return SUCCESS;
 127 }
 128 /* }}} */
 129 
 130 ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array) /* {{{ */
 131 {
 132         zval *param_ptr;
 133         int arg_count;
 134 
 135         param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
 136         arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
 137 
 138         if (param_count>arg_count) {
 139                 return FAILURE;
 140         }
 141 
 142         while (param_count-->0) {
 143                 if (Z_REFCOUNTED_P(param_ptr)) {
 144                         Z_ADDREF_P(param_ptr);
 145                 }
 146                 zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
 147                 param_ptr++;
 148         }
 149 
 150         return SUCCESS;
 151 }
 152 /* }}} */
 153 
 154 ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
 155 {
 156         const char *space;
 157         const char *class_name = get_active_class_name(&space);
 158 
 159         zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
 160 }
 161 /* }}} */
 162 
 163 /* Argument parsing API -- andrei */
 164 ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
 165 {
 166         switch(type) {
 167                 case IS_FALSE:
 168                 case IS_TRUE:
 169                 case _IS_BOOL:
 170                         return "boolean";
 171                 case IS_LONG:
 172                         return "integer";
 173                 case IS_DOUBLE:
 174                         return "float";
 175                 case IS_STRING:
 176                         return "string";
 177                 case IS_OBJECT:
 178                         return "object";
 179                 case IS_RESOURCE:
 180                         return "resource";
 181                 case IS_NULL:
 182                         return "null";
 183                 case IS_CALLABLE:
 184                         return "callable";
 185                 case IS_ARRAY:
 186                         return "array";
 187                 default:
 188                         return "unknown";
 189         }
 190 }
 191 /* }}} */
 192 
 193 ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
 194 {
 195         ZVAL_DEREF(arg);
 196         return zend_get_type_by_const(Z_TYPE_P(arg));
 197 }
 198 /* }}} */
 199 
 200 #ifdef FAST_ZPP
 201 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_paramers_count_error(int num_args, int min_num_args, int max_num_args) /* {{{ */
 202 {
 203         zend_function *active_function = EG(current_execute_data)->func;
 204         const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
 205 
 206         zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects %s %d parameter%s, %d given",
 207                 class_name, \
 208                 class_name[0] ? "::" : "", \
 209                 ZSTR_VAL(active_function->common.function_name),
 210                 min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
 211                 num_args < min_num_args ? min_num_args : max_num_args,
 212                 (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
 213                 num_args);
 214 }
 215 /* }}} */
 216 
 217 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_paramer_type_error(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
 218 {
 219         const char *space;
 220         const char *class_name = get_active_class_name(&space);
 221         static const char * const expected_error[] = {
 222                 Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
 223                 NULL
 224         };
 225 
 226         zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
 227                 class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
 228 }
 229 /* }}} */
 230 
 231 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_paramer_class_error(int num, char *name, zval *arg) /* {{{ */
 232 {
 233         const char *space;
 234         const char *class_name = get_active_class_name(&space);
 235 
 236         zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
 237                 class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
 238 }
 239 /* }}} */
 240 
 241 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int severity, int num, char *error) /* {{{ */
 242 {
 243         const char *space;
 244         const char *class_name = get_active_class_name(&space);
 245 
 246         if (severity == E_WARNING) {
 247                 zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid callback, %s",
 248                         class_name, space, get_active_function_name(), num, error);
 249         } else if (severity == E_ERROR) {
 250                 zend_throw_error(zend_ce_type_error, "%s%s%s() expects parameter %d to be a valid callback, %s",
 251                         class_name, space, get_active_function_name(), num, error);
 252         } else {
 253                 zend_error(severity, "%s%s%s() expects parameter %d to be a valid callback, %s",
 254                         class_name, space, get_active_function_name(), num, error);
 255         }
 256         efree(error);
 257 }
 258 /* }}} */
 259 
 260 ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, int check_null) /* {{{ */
 261 {
 262         zend_class_entry *ce_base = *pce;
 263 
 264         if (check_null && Z_TYPE_P(arg) == IS_NULL) {
 265                 *pce = NULL;
 266                 return 1;
 267         }
 268         convert_to_string_ex(arg);
 269         *pce = zend_lookup_class(Z_STR_P(arg));
 270         if (ce_base) {
 271                 if ((!*pce || !instanceof_function(*pce, ce_base))) {
 272                         const char *space;
 273                         const char *class_name = get_active_class_name(&space);
 274 
 275                         zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
 276                                 class_name, space, get_active_function_name(), num,
 277                                 ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
 278                         *pce = NULL;
 279                         return 0;
 280                 }
 281         }
 282         if (!*pce) {
 283                 const char *space;
 284                 const char *class_name = get_active_class_name(&space);
 285 
 286                 zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
 287                         class_name, space, get_active_function_name(), num,
 288                         Z_STRVAL_P(arg));
 289                 return 0;
 290         }
 291         return 1;
 292 }
 293 /* }}} */
 294 #endif
 295 
 296 ZEND_API int ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, zend_bool *dest) /* {{{ */
 297 {
 298         if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
 299                 *dest = zend_is_true(arg);
 300         } else {
 301                 return 0;
 302         }
 303         return 1;
 304 }
 305 /* }}} */
 306 
 307 ZEND_API int ZEND_FASTCALL zend_parse_arg_bool_slow(zval *arg, zend_bool *dest) /* {{{ */
 308 {
 309         if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
 310                 return 0;
 311         }
 312         return zend_parse_arg_bool_weak(arg, dest);
 313 }
 314 /* }}} */
 315 
 316 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest) /* {{{ */
 317 {
 318         if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
 319                 if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
 320                         return 0;
 321                 }
 322                 if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
 323                         return 0;
 324                 } else {
 325                         *dest = zend_dval_to_lval(Z_DVAL_P(arg));
 326                 }
 327         } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
 328                 double d;
 329                 int type;
 330 
 331                 if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
 332                         if (EXPECTED(type != 0)) {
 333                                 if (UNEXPECTED(zend_isnan(d))) {
 334                                         return 0;
 335                                 }
 336                                 if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
 337                                         return 0;
 338                                 } else {
 339                                         *dest = zend_dval_to_lval(d);
 340                                 }
 341                         } else {
 342                                 return 0;
 343                         }
 344                 }
 345         } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
 346                 *dest = 0;
 347         } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
 348                 *dest = 1;
 349         } else {
 350                 return 0;
 351         }
 352         return 1;
 353 }
 354 /* }}} */
 355 
 356 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest) /* {{{ */
 357 {
 358         if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
 359                 return 0;
 360         }
 361         return zend_parse_arg_long_weak(arg, dest);
 362 }
 363 /* }}} */
 364 
 365 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *dest) /* {{{ */
 366 {
 367         if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
 368                 if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
 369                         return 0;
 370                 }
 371                 if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
 372                         *dest = (Z_DVAL_P(arg) > 0) ? ZEND_LONG_MAX : ZEND_LONG_MIN;
 373                 } else {
 374                         *dest = zend_dval_to_lval(Z_DVAL_P(arg));
 375                 }
 376         } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
 377                 double d;
 378                 int type;
 379 
 380                 if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
 381                         if (EXPECTED(type != 0)) {
 382                                 if (UNEXPECTED(zend_isnan(d))) {
 383                                         return 0;
 384                                 }
 385                                 if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
 386                                         *dest = (d > 0) ? ZEND_LONG_MAX : ZEND_LONG_MIN;
 387                                 } else {
 388                                         *dest = zend_dval_to_lval(d);
 389                                 }
 390                         } else {
 391                                 return 0;
 392                         }
 393                 }
 394         } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
 395                 *dest = 0;
 396         } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
 397                 *dest = 1;
 398         } else {
 399                 return 0;
 400         }
 401         return 1;
 402 }
 403 /* }}} */
 404 
 405 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_slow(zval *arg, zend_long *dest) /* {{{ */
 406 {
 407         if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
 408                 return 0;
 409         }
 410         return zend_parse_arg_long_cap_weak(arg, dest);
 411 }
 412 /* }}} */
 413 
 414 ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest) /* {{{ */
 415 {
 416         if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
 417                 *dest = (double)Z_LVAL_P(arg);
 418         } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
 419                 zend_long l;
 420                 int type;
 421 
 422                 if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
 423                         if (EXPECTED(type != 0)) {
 424                                 *dest = (double)(l);
 425                         } else {
 426                                 return 0;
 427                         }
 428                 }
 429         } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
 430                 *dest = 0.0;
 431         } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
 432                 *dest = 1.0;
 433         } else {
 434                 return 0;
 435         }
 436         return 1;
 437 }
 438 /* }}} */
 439 
 440 ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest) /* {{{ */
 441 {
 442         if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
 443                 /* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */
 444                 *dest = (double)Z_LVAL_P(arg);
 445         } else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
 446                 return 0;
 447         }
 448         return zend_parse_arg_double_weak(arg, dest);
 449 }
 450 /* }}} */
 451 
 452 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest) /* {{{ */
 453 {
 454         if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
 455                 convert_to_string(arg);
 456                 *dest = Z_STR_P(arg);
 457         } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
 458                 if (Z_OBJ_HANDLER_P(arg, cast_object)) {
 459                         zval obj;
 460                         if (Z_OBJ_HANDLER_P(arg, cast_object)(arg, &obj, IS_STRING) == SUCCESS) {
 461                                 zval_ptr_dtor(arg);
 462                                 ZVAL_COPY_VALUE(arg, &obj);
 463                                 *dest = Z_STR_P(arg);
 464                                 return 1;
 465                         }
 466                 } else if (Z_OBJ_HANDLER_P(arg, get)) {
 467                         zval rv;
 468                         zval *z = Z_OBJ_HANDLER_P(arg, get)(arg, &rv);
 469 
 470                         Z_ADDREF_P(z);
 471                         if (Z_TYPE_P(z) != IS_OBJECT) {
 472                                 zval_dtor(arg);
 473                                 ZVAL_NULL(arg);
 474                                 if (!zend_make_printable_zval(z, arg)) {
 475                                         ZVAL_COPY_VALUE(arg, z);
 476                                 }
 477                                 *dest = Z_STR_P(arg);
 478                                 return 1;
 479                         }
 480                         zval_ptr_dtor(z);
 481                 }
 482                 return 0;
 483         } else {
 484                 return 0;
 485         }
 486         return 1;
 487 }
 488 /* }}} */
 489 
 490 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest) /* {{{ */
 491 {
 492         if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
 493                 return 0;
 494         }
 495         return zend_parse_arg_str_weak(arg, dest);
 496 }
 497 /* }}} */
 498 
 499 static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity) /* {{{ */
 500 {
 501         const char *spec_walk = *spec;
 502         char c = *spec_walk++;
 503         int check_null = 0;
 504         zval *real_arg = arg;
 505 
 506         /* scan through modifiers */
 507         ZVAL_DEREF(arg);
 508         while (1) {
 509                 if (*spec_walk == '/') {
 510                         SEPARATE_ZVAL_NOREF(arg);
 511                         real_arg = arg;
 512                 } else if (*spec_walk == '!') {
 513                         check_null = 1;
 514                 } else {
 515                         break;
 516                 }
 517                 spec_walk++;
 518         }
 519 
 520         switch (c) {
 521                 case 'l':
 522                 case 'L':
 523                         {
 524                                 zend_long *p = va_arg(*va, zend_long *);
 525                                 zend_bool *is_null = NULL;
 526 
 527                                 if (check_null) {
 528                                         is_null = va_arg(*va, zend_bool *);
 529                                 }
 530 
 531                                 if (!zend_parse_arg_long(arg, p, is_null, check_null, c == 'L')) {
 532                                         return "integer";
 533                                 }
 534                         }
 535                         break;
 536 
 537                 case 'd':
 538                         {
 539                                 double *p = va_arg(*va, double *);
 540                                 zend_bool *is_null = NULL;
 541 
 542                                 if (check_null) {
 543                                         is_null = va_arg(*va, zend_bool *);
 544                                 }
 545 
 546                                 if (!zend_parse_arg_double(arg, p, is_null, check_null)) {
 547                                         return "float";
 548                                 }
 549                         }
 550                         break;
 551 
 552                 case 's':
 553                         {
 554                                 char **p = va_arg(*va, char **);
 555                                 size_t *pl = va_arg(*va, size_t *);
 556                                 if (!zend_parse_arg_string(arg, p, pl, check_null)) {
 557                                         return "string";
 558                                 }
 559                         }
 560                         break;
 561 
 562                 case 'p':
 563                         {
 564                                 char **p = va_arg(*va, char **);
 565                                 size_t *pl = va_arg(*va, size_t *);
 566                                 if (!zend_parse_arg_path(arg, p, pl, check_null)) {
 567                                         return "a valid path";
 568                                 }
 569                         }
 570                         break;
 571 
 572                 case 'P':
 573                         {
 574                                 zend_string **str = va_arg(*va, zend_string **);
 575                                 if (!zend_parse_arg_path_str(arg, str, check_null)) {
 576                                         return "a valid path";
 577                                 }
 578                         }
 579                         break;
 580 
 581                 case 'S':
 582                         {
 583                                 zend_string **str = va_arg(*va, zend_string **);
 584                                 if (!zend_parse_arg_str(arg, str, check_null)) {
 585                                         return "string";
 586                                 }
 587                         }
 588                         break;
 589 
 590                 case 'b':
 591                         {
 592                                 zend_bool *p = va_arg(*va, zend_bool *);
 593                                 zend_bool *is_null = NULL;
 594 
 595                                 if (check_null) {
 596                                         is_null = va_arg(*va, zend_bool *);
 597                                 }
 598 
 599                                 if (!zend_parse_arg_bool(arg, p, is_null, check_null)) {
 600                                         return "boolean";
 601                                 }
 602                         }
 603                         break;
 604 
 605                 case 'r':
 606                         {
 607                                 zval **p = va_arg(*va, zval **);
 608 
 609                                 if (!zend_parse_arg_resource(arg, p, check_null)) {
 610                                         return "resource";
 611                                 }
 612                         }
 613                         break;
 614 
 615                 case 'A':
 616                 case 'a':
 617                         {
 618                                 zval **p = va_arg(*va, zval **);
 619 
 620                                 if (!zend_parse_arg_array(arg, p, check_null, c == 'A')) {
 621                                         return "array";
 622                                 }
 623                         }
 624                         break;
 625 
 626                 case 'H':
 627                 case 'h':
 628                         {
 629                                 HashTable **p = va_arg(*va, HashTable **);
 630 
 631                                 if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H')) {
 632                                         return "array";
 633                                 }
 634                         }
 635                         break;
 636 
 637                 case 'o':
 638                         {
 639                                 zval **p = va_arg(*va, zval **);
 640 
 641                                 if (!zend_parse_arg_object(arg, p, NULL, check_null)) {
 642                                         return "object";
 643                                 }
 644                         }
 645                         break;
 646 
 647                 case 'O':
 648                         {
 649                                 zval **p = va_arg(*va, zval **);
 650                                 zend_class_entry *ce = va_arg(*va, zend_class_entry *);
 651 
 652                                 if (!zend_parse_arg_object(arg, p, ce, check_null)) {
 653                                         if (ce) {
 654                                                 return ZSTR_VAL(ce->name);
 655                                         } else {
 656                                                 return "object";
 657                                         }
 658                                 }
 659                         }
 660                         break;
 661 
 662                 case 'C':
 663                         {
 664                                 zend_class_entry *lookup, **pce = va_arg(*va, zend_class_entry **);
 665                                 zend_class_entry *ce_base = *pce;
 666 
 667                                 if (check_null && Z_TYPE_P(arg) == IS_NULL) {
 668                                         *pce = NULL;
 669                                         break;
 670                                 }
 671                                 convert_to_string_ex(arg);
 672                                 if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
 673                                         *pce = NULL;
 674                                 } else {
 675                                         *pce = lookup;
 676                                 }
 677                                 if (ce_base) {
 678                                         if ((!*pce || !instanceof_function(*pce, ce_base))) {
 679                                                 zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given",
 680                                                         ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
 681                                                 *pce = NULL;
 682                                                 return "";
 683                                         }
 684                                 }
 685                                 if (!*pce) {
 686                                         zend_spprintf(error, 0, "to be a valid class name, '%s' given",
 687                                                 Z_STRVAL_P(arg));
 688                                         return "";
 689                                 }
 690                                 break;
 691 
 692                         }
 693                         break;
 694 
 695                 case 'f':
 696                         {
 697                                 zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
 698                                 zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
 699                                 char *is_callable_error = NULL;
 700 
 701                                 if (check_null && Z_TYPE_P(arg) == IS_NULL) {
 702                                         fci->size = 0;
 703                                         fcc->initialized = 0;
 704                                         break;
 705                                 }
 706 
 707                                 if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
 708                                         if (is_callable_error) {
 709                                                 *severity = E_DEPRECATED;
 710                                                 zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
 711                                                 efree(is_callable_error);
 712                                                 *spec = spec_walk;
 713                                                 return "";
 714                                         }
 715                                         break;
 716                                 } else {
 717                                         if (is_callable_error) {
 718                                                 *severity = E_ERROR;
 719                                                 zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
 720                                                 efree(is_callable_error);
 721                                                 return "";
 722                                         } else {
 723                                                 return "valid callback";
 724                                         }
 725                                 }
 726                         }
 727 
 728                 case 'z':
 729                         {
 730                                 zval **p = va_arg(*va, zval **);
 731 
 732                                 zend_parse_arg_zval_deref(real_arg, p, check_null);
 733                         }
 734                         break;
 735 
 736                 case 'Z':
 737                         /* 'Z' iz not supported anymore and should be replaced with 'z' */
 738                         ZEND_ASSERT(c != 'Z');
 739                 default:
 740                         return "unknown";
 741         }
 742 
 743         *spec = spec_walk;
 744 
 745         return NULL;
 746 }
 747 /* }}} */
 748 
 749 static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec, int flags) /* {{{ */
 750 {
 751         const char *expected_type = NULL;
 752         char *error = NULL;
 753         int severity = 0;
 754 
 755         expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity);
 756         if (expected_type) {
 757                 if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
 758                         const char *space;
 759                         const char *class_name = get_active_class_name(&space);
 760                         zend_bool throw_exception =
 761                                 ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
 762 
 763                         if (error) {
 764                                 zend_internal_type_error(throw_exception, "%s%s%s() expects parameter %d %s",
 765                                                 class_name, space, get_active_function_name(), arg_num, error);
 766                                 efree(error);
 767                         } else {
 768                                 zend_internal_type_error(throw_exception,
 769                                                 "%s%s%s() expects parameter %d to be %s, %s given",
 770                                                 class_name, space, get_active_function_name(), arg_num, expected_type,
 771                                                 zend_zval_type_name(arg));
 772                         }
 773                 }
 774                 if (severity != E_DEPRECATED) {
 775                         return FAILURE;
 776                 }
 777         }
 778 
 779         return SUCCESS;
 780 }
 781 /* }}} */
 782 
 783 ZEND_API int zend_parse_parameter(int flags, int arg_num, zval *arg, const char *spec, ...)
 784 {
 785         va_list va;
 786         int ret;
 787 
 788         va_start(va, spec);
 789         ret = zend_parse_arg(arg_num, arg, &va, &spec, flags);
 790         va_end(va);
 791 
 792         return ret;
 793 }
 794 
 795 static ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) {
 796         zend_function *active_function = EG(current_execute_data)->func;
 797         const char *class_name = active_function->common.scope
 798                 ? ZSTR_VAL(active_function->common.scope->name) : "";
 799         zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): %s",
 800                 class_name, class_name[0] ? "::" : "",
 801                 ZSTR_VAL(active_function->common.function_name), msg);
 802 }
 803 
 804 static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags) /* {{{ */
 805 {
 806         const  char *spec_walk;
 807         int c, i;
 808         int min_num_args = -1;
 809         int max_num_args = 0;
 810         int post_varargs = 0;
 811         zval *arg;
 812         int arg_count;
 813         zend_bool have_varargs = 0;
 814         zval **varargs = NULL;
 815         int *n_varargs = NULL;
 816 
 817         for (spec_walk = type_spec; *spec_walk; spec_walk++) {
 818                 c = *spec_walk;
 819                 switch (c) {
 820                         case 'l': case 'd':
 821                         case 's': case 'b':
 822                         case 'r': case 'a':
 823                         case 'o': case 'O':
 824                         case 'z': case 'Z':
 825                         case 'C': case 'h':
 826                         case 'f': case 'A':
 827                         case 'H': case 'p':
 828                         case 'S': case 'P':
 829                         case 'L':
 830                                 max_num_args++;
 831                                 break;
 832 
 833                         case '|':
 834                                 min_num_args = max_num_args;
 835                                 break;
 836 
 837                         case '/':
 838                         case '!':
 839                                 /* Pass */
 840                                 break;
 841 
 842                         case '*':
 843                         case '+':
 844                                 if (have_varargs) {
 845                                         zend_parse_parameters_debug_error(
 846                                                 "only one varargs specifier (* or +) is permitted");
 847                                         return FAILURE;
 848                                 }
 849                                 have_varargs = 1;
 850                                 /* we expect at least one parameter in varargs */
 851                                 if (c == '+') {
 852                                         max_num_args++;
 853                                 }
 854                                 /* mark the beginning of varargs */
 855                                 post_varargs = max_num_args;
 856                                 break;
 857 
 858                         default:
 859                                 zend_parse_parameters_debug_error("bad type specifier while parsing parameters");
 860                                 return FAILURE;
 861                 }
 862         }
 863 
 864         if (min_num_args < 0) {
 865                 min_num_args = max_num_args;
 866         }
 867 
 868         if (have_varargs) {
 869                 /* calculate how many required args are at the end of the specifier list */
 870                 post_varargs = max_num_args - post_varargs;
 871                 max_num_args = -1;
 872         }
 873 
 874         if (num_args < min_num_args || (num_args > max_num_args && max_num_args >= 0)) {
 875                 if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
 876                         zend_function *active_function = EG(current_execute_data)->func;
 877                         const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
 878                         zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
 879                         zend_internal_type_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given",
 880                                         class_name,
 881                                         class_name[0] ? "::" : "",
 882                                         ZSTR_VAL(active_function->common.function_name),
 883                                         min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
 884                                         num_args < min_num_args ? min_num_args : max_num_args,
 885                                         (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
 886                                         num_args);
 887                 }
 888                 return FAILURE;
 889         }
 890 
 891         arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
 892 
 893         if (num_args > arg_count) {
 894                 zend_parse_parameters_debug_error("could not obtain parameters for parsing");
 895                 return FAILURE;
 896         }
 897 
 898         i = 0;
 899         while (num_args-- > 0) {
 900                 if (*type_spec == '|') {
 901                         type_spec++;
 902                 }
 903 
 904                 if (*type_spec == '*' || *type_spec == '+') {
 905                         int num_varargs = num_args + 1 - post_varargs;
 906 
 907                         /* eat up the passed in storage even if it won't be filled in with varargs */
 908                         varargs = va_arg(*va, zval **);
 909                         n_varargs = va_arg(*va, int *);
 910                         type_spec++;
 911 
 912                         if (num_varargs > 0) {
 913                                 *n_varargs = num_varargs;
 914                                 *varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
 915                                 /* adjust how many args we have left and restart loop */
 916                                 num_args += 1 - num_varargs;
 917                                 i += num_varargs;
 918                                 continue;
 919                         } else {
 920                                 *varargs = NULL;
 921                                 *n_varargs = 0;
 922                         }
 923                 }
 924 
 925                 arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
 926 
 927                 if (zend_parse_arg(i+1, arg, va, &type_spec, flags) == FAILURE) {
 928                         /* clean up varargs array if it was used */
 929                         if (varargs && *varargs) {
 930                                 *varargs = NULL;
 931                         }
 932                         return FAILURE;
 933                 }
 934                 i++;
 935         }
 936 
 937         return SUCCESS;
 938 }
 939 /* }}} */
 940 
 941 ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...) /* {{{ */
 942 {
 943         va_list va;
 944         int retval;
 945 
 946         va_start(va, type_spec);
 947         retval = zend_parse_va_args(num_args, type_spec, &va, flags);
 948         va_end(va);
 949 
 950         return retval;
 951 }
 952 /* }}} */
 953 
 954 ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...) /* {{{ */
 955 {
 956         va_list va;
 957         int retval;
 958         int flags = 0;
 959 
 960         va_start(va, type_spec);
 961         retval = zend_parse_va_args(num_args, type_spec, &va, flags);
 962         va_end(va);
 963 
 964         return retval;
 965 }
 966 /* }}} */
 967 
 968 ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...) /* {{{ */
 969 {
 970         va_list va;
 971         int retval;
 972         int flags = ZEND_PARSE_PARAMS_THROW;
 973 
 974         va_start(va, type_spec);
 975         retval = zend_parse_va_args(num_args, type_spec, &va, flags);
 976         va_end(va);
 977 
 978         return retval;
 979 }
 980 /* }}} */
 981 
 982 ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
 983 {
 984         va_list va;
 985         int retval;
 986         int flags = 0;
 987         const char *p = type_spec;
 988         zval **object;
 989         zend_class_entry *ce;
 990 
 991         /* Just checking this_ptr is not enough, because fcall_common_helper does not set
 992          * Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
 993          * In that case EG(This) would still be the $this from the calling code and we'd take the
 994          * wrong branch here. */
 995         zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL;
 996 
 997         if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
 998                 va_start(va, type_spec);
 999                 retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1000                 va_end(va);
1001         } else {
1002                 p++;
1003 
1004                 va_start(va, type_spec);
1005 
1006                 object = va_arg(va, zval **);
1007                 ce = va_arg(va, zend_class_entry *);
1008                 *object = this_ptr;
1009 
1010                 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1011                         zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
1012                                 ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name(), ZSTR_VAL(ce->name), get_active_function_name());
1013                 }
1014 
1015                 retval = zend_parse_va_args(num_args, p, &va, flags);
1016                 va_end(va);
1017         }
1018         return retval;
1019 }
1020 /* }}} */
1021 
1022 ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1023 {
1024         va_list va;
1025         int retval;
1026         const char *p = type_spec;
1027         zval **object;
1028         zend_class_entry *ce;
1029 
1030         if (!this_ptr) {
1031                 va_start(va, type_spec);
1032                 retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1033                 va_end(va);
1034         } else {
1035                 p++;
1036                 va_start(va, type_spec);
1037 
1038                 object = va_arg(va, zval **);
1039                 ce = va_arg(va, zend_class_entry *);
1040                 *object = this_ptr;
1041 
1042                 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1043                         if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1044                                 zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
1045                                         ZSTR_VAL(ce->name), get_active_function_name(), ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name());
1046                         }
1047                         va_end(va);
1048                         return FAILURE;
1049                 }
1050 
1051                 retval = zend_parse_va_args(num_args, p, &va, flags);
1052                 va_end(va);
1053         }
1054         return retval;
1055 }
1056 /* }}} */
1057 
1058 /* Argument parsing API -- andrei */
1059 ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC) /* {{{ */
1060 {
1061         ZVAL_NEW_ARR(arg);
1062         _zend_hash_init(Z_ARRVAL_P(arg), size, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
1063         return SUCCESS;
1064 }
1065 /* }}} */
1066 
1067 /* This function should be called after the constructor has been called
1068  * because it may call __set from the uninitialized object otherwise. */
1069 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
1070 {
1071         const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
1072         zend_class_entry *old_scope = EG(scope);
1073         zend_string *key;
1074         zval *value;
1075 
1076         EG(scope) = Z_OBJCE_P(obj);
1077         ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) {
1078                 if (key) {
1079                         zval member;
1080 
1081                         ZVAL_STR(&member, key);
1082                         obj_ht->write_property(obj, &member, value, NULL);
1083                 }
1084         } ZEND_HASH_FOREACH_END();
1085         EG(scope) = old_scope;
1086 }
1087 /* }}} */
1088 
1089 ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
1090 {
1091         if (!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
1092                 class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
1093 
1094                 if (class_type->parent) {
1095                         if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
1096                                 return FAILURE;
1097                         }
1098                 }
1099 
1100                 if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
1101                         /* initialize static members of internal class */
1102                         int i;
1103                         zval *p;
1104 
1105 #if ZTS
1106                         CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count);
1107 #else
1108                         class_type->static_members_table = emalloc(sizeof(zval) * class_type->default_static_members_count);
1109 #endif
1110                         for (i = 0; i < class_type->default_static_members_count; i++) {
1111                                 p = &class_type->default_static_members_table[i];
1112                                 if (Z_ISREF_P(p) &&
1113                                         class_type->parent &&
1114                                         i < class_type->parent->default_static_members_count &&
1115                                         p == &class_type->parent->default_static_members_table[i] &&
1116                                         Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
1117                                 ) {
1118                                         zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
1119 
1120                                         ZVAL_NEW_REF(q, q);
1121                                         ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
1122                                         Z_ADDREF_P(q);
1123                                 } else {
1124                                         ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
1125                                 }
1126                         }
1127                 } else {
1128                         zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
1129                         zend_class_entry *old_scope = *scope;
1130                         zend_class_entry *ce;
1131                         zval *val;
1132                         zend_property_info *prop_info;
1133 
1134                         *scope = class_type;
1135                         ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
1136                                 ZVAL_DEREF(val);
1137                                 if (Z_CONSTANT_P(val)) {
1138                                         if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) {
1139                                                 return FAILURE;
1140                                         }
1141                                 }
1142                         } ZEND_HASH_FOREACH_END();
1143 
1144                         ce = class_type;
1145                         while (ce) {
1146                                 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
1147                                         if (prop_info->ce == ce) {
1148                                                 if (prop_info->flags & ZEND_ACC_STATIC) {
1149                                                         val = CE_STATIC_MEMBERS(class_type) + prop_info->offset;
1150                                                 } else {
1151                                                         val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0));
1152                                                 }
1153                                                 ZVAL_DEREF(val);
1154                                                 if (Z_CONSTANT_P(val)) {
1155                                                         *scope = ce;
1156                                                         if (UNEXPECTED(zval_update_constant_ex(val, 1, NULL) != SUCCESS)) {
1157                                                                 return FAILURE;
1158                                                         }
1159                                                 }
1160                                         }
1161                                 } ZEND_HASH_FOREACH_END();
1162                                 ce = ce->parent;
1163                         }
1164 
1165                         *scope = old_scope;
1166                 }
1167         }
1168         return SUCCESS;
1169 }
1170 /* }}} */
1171 
1172 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1173 {
1174         if (class_type->default_properties_count) {
1175                 zval *src = class_type->default_properties_table;
1176                 zval *dst = object->properties_table;
1177                 zval *end = src + class_type->default_properties_count;
1178 
1179                 do {
1180 #if ZTS
1181                         ZVAL_DUP(dst, src);
1182 #else
1183                         ZVAL_COPY(dst, src);
1184 #endif
1185                         src++;
1186                         dst++;
1187                 } while (src != end);
1188                 object->properties = NULL;
1189         }
1190 }
1191 /* }}} */
1192 
1193 ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */
1194 {
1195         object->properties = properties;
1196         if (object->ce->default_properties_count) {
1197             zval *prop;
1198         zend_string *key;
1199         zend_property_info *property_info;
1200 
1201         ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
1202                         property_info = zend_get_property_info(object->ce, key, 1);
1203                         if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1204                             property_info &&
1205                             (property_info->flags & ZEND_ACC_STATIC) == 0) {
1206                                 zval *slot = OBJ_PROP(object, property_info->offset);
1207                                 ZVAL_COPY_VALUE(slot, prop);
1208                                 ZVAL_INDIRECT(prop, slot);
1209                         }
1210                 } ZEND_HASH_FOREACH_END();
1211         }
1212 }
1213 /* }}} */
1214 
1215 ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */
1216 {
1217     zval *prop, tmp;
1218         zend_string *key;
1219         zend_long h;
1220         zend_property_info *property_info;
1221 
1222         ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
1223                 if (key) {
1224                         if (ZSTR_VAL(key)[0] == '\0') {
1225                                 const char *class_name, *prop_name;
1226                                 size_t prop_name_len;
1227                                 if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
1228                                         zend_string *pname = zend_string_init(prop_name, prop_name_len, 0);
1229                                         zend_class_entry *prev_scope = EG(scope);
1230                                         if (class_name && class_name[0] != '*') {
1231                                                 zend_string *cname = zend_string_init(class_name, strlen(class_name), 0);
1232                                                 EG(scope) = zend_lookup_class(cname);
1233                                                 zend_string_release(cname);
1234                                         }
1235                                         property_info = zend_get_property_info(object->ce, pname, 1);
1236                                         zend_string_release(pname);
1237                                         EG(scope) = prev_scope;
1238                                 } else {
1239                                         property_info = ZEND_WRONG_PROPERTY_INFO;
1240                                 }
1241                         } else {
1242                                 property_info = zend_get_property_info(object->ce, key, 1);
1243                         }
1244                         if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1245                                 property_info &&
1246                                 (property_info->flags & ZEND_ACC_STATIC) == 0) {
1247                                 zval *slot = OBJ_PROP(object, property_info->offset);
1248                                 zval_ptr_dtor(slot);
1249                                 ZVAL_COPY_VALUE(slot, prop);
1250                                 zval_add_ref(slot);
1251                                 if (object->properties) {
1252                                         ZVAL_INDIRECT(&tmp, slot);
1253                                         zend_hash_update(object->properties, key, &tmp);
1254                                 }
1255                         } else {
1256                                 if (!object->properties) {
1257                                         rebuild_object_properties(object);
1258                                 }
1259                                 prop = zend_hash_update(object->properties, key, prop);
1260                                 zval_add_ref(prop);
1261                         }
1262                 } else {
1263                         if (!object->properties) {
1264                                 rebuild_object_properties(object);
1265                         }
1266                         prop = zend_hash_index_update(object->properties, h, prop);
1267                         zval_add_ref(prop);
1268                 }
1269         } ZEND_HASH_FOREACH_END();
1270 }
1271 /* }}} */
1272 
1273 /* This function requires 'properties' to contain all props declared in the
1274  * class and all props being public. If only a subset is given or the class
1275  * has protected members then you need to merge the properties separately by
1276  * calling zend_merge_properties(). */
1277 ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC) /* {{{ */
1278 {
1279         if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1280                 if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1281                         zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
1282                 } else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1283                         zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
1284                 } else {
1285                         zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
1286                 }
1287                 ZVAL_NULL(arg);
1288                 Z_OBJ_P(arg) = NULL;
1289                 return FAILURE;
1290         }
1291 
1292         if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
1293                 if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
1294                         ZVAL_NULL(arg);
1295                         Z_OBJ_P(arg) = NULL;
1296                         return FAILURE;
1297                 }
1298         }
1299 
1300         if (class_type->create_object == NULL) {
1301                 ZVAL_OBJ(arg, zend_objects_new(class_type));
1302                 if (properties) {
1303                         object_properties_init_ex(Z_OBJ_P(arg), properties);
1304                 } else {
1305                         object_properties_init(Z_OBJ_P(arg), class_type);
1306                 }
1307         } else {
1308                 ZVAL_OBJ(arg, class_type->create_object(class_type));
1309         }
1310         return SUCCESS;
1311 }
1312 /* }}} */
1313 
1314 ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC) /* {{{ */
1315 {
1316         return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC);
1317 }
1318 /* }}} */
1319 
1320 ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC) /* {{{ */
1321 {
1322         return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC);
1323 }
1324 /* }}} */
1325 
1326 ZEND_API int add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1327 {
1328         zval *ret, tmp;
1329 
1330         ZVAL_LONG(&tmp, n);
1331         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1332         return ret ? SUCCESS : FAILURE;
1333 }
1334 /* }}} */
1335 
1336 ZEND_API int add_assoc_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1337 {
1338         zval *ret, tmp;
1339 
1340         ZVAL_NULL(&tmp);
1341         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1342         return ret ? SUCCESS : FAILURE;
1343 }
1344 /* }}} */
1345 
1346 ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, int b) /* {{{ */
1347 {
1348         zval *ret, tmp;
1349 
1350         ZVAL_BOOL(&tmp, b);
1351         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1352         return ret ? SUCCESS : FAILURE;
1353 }
1354 /* }}} */
1355 
1356 ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1357 {
1358         zval *ret, tmp;
1359 
1360         ZVAL_RES(&tmp, r);
1361         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1362         return ret ? SUCCESS : FAILURE;
1363 }
1364 /* }}} */
1365 
1366 ZEND_API int add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1367 {
1368         zval *ret, tmp;
1369 
1370         ZVAL_DOUBLE(&tmp, d);
1371         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1372         return ret ? SUCCESS : FAILURE;
1373 }
1374 /* }}} */
1375 
1376 ZEND_API int add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1377 {
1378         zval *ret, tmp;
1379 
1380         ZVAL_STR(&tmp, str);
1381         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1382         return ret ? SUCCESS : FAILURE;
1383 }
1384 /* }}} */
1385 
1386 ZEND_API int add_assoc_string_ex(zval *arg, const char *key, size_t key_len, char *str) /* {{{ */
1387 {
1388         zval *ret, tmp;
1389 
1390         ZVAL_STRING(&tmp, str);
1391         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1392         return ret ? SUCCESS : FAILURE;
1393 }
1394 /* }}} */
1395 
1396 ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, char *str, size_t length) /* {{{ */
1397 {
1398         zval *ret, tmp;
1399 
1400         ZVAL_STRINGL(&tmp, str, length);
1401         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1402         return ret ? SUCCESS : FAILURE;
1403 }
1404 /* }}} */
1405 
1406 ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1407 {
1408         zval *ret;
1409 
1410         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, value);
1411         return ret ? SUCCESS : FAILURE;
1412 }
1413 /* }}} */
1414 
1415 ZEND_API int add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */
1416 {
1417         zval tmp;
1418 
1419         ZVAL_LONG(&tmp, n);
1420         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1421 }
1422 /* }}} */
1423 
1424 ZEND_API int add_index_null(zval *arg, zend_ulong index) /* {{{ */
1425 {
1426         zval tmp;
1427 
1428         ZVAL_NULL(&tmp);
1429         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1430 }
1431 /* }}} */
1432 
1433 ZEND_API int add_index_bool(zval *arg, zend_ulong index, int b) /* {{{ */
1434 {
1435         zval tmp;
1436 
1437         ZVAL_BOOL(&tmp, b);
1438         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1439 }
1440 /* }}} */
1441 
1442 ZEND_API int add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */
1443 {
1444         zval tmp;
1445 
1446         ZVAL_RES(&tmp, r);
1447         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1448 }
1449 /* }}} */
1450 
1451 ZEND_API int add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1452 {
1453         zval tmp;
1454 
1455         ZVAL_DOUBLE(&tmp, d);
1456         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1457 }
1458 /* }}} */
1459 
1460 ZEND_API int add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1461 {
1462         zval tmp;
1463 
1464         ZVAL_STR(&tmp, str);
1465         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1466 }
1467 /* }}} */
1468 
1469 ZEND_API int add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1470 {
1471         zval tmp;
1472 
1473         ZVAL_STRING(&tmp, str);
1474         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1475 }
1476 /* }}} */
1477 
1478 ZEND_API int add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1479 {
1480         zval tmp;
1481 
1482         ZVAL_STRINGL(&tmp, str, length);
1483         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1484 }
1485 /* }}} */
1486 
1487 ZEND_API int add_index_zval(zval *arg, zend_ulong index, zval *value) /* {{{ */
1488 {
1489         return zend_hash_index_update(Z_ARRVAL_P(arg), index, value) ? SUCCESS : FAILURE;
1490 }
1491 /* }}} */
1492 
1493 ZEND_API int add_next_index_long(zval *arg, zend_long n) /* {{{ */
1494 {
1495         zval tmp;
1496 
1497         ZVAL_LONG(&tmp, n);
1498         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1499 }
1500 /* }}} */
1501 
1502 ZEND_API int add_next_index_null(zval *arg) /* {{{ */
1503 {
1504         zval tmp;
1505 
1506         ZVAL_NULL(&tmp);
1507         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1508 }
1509 /* }}} */
1510 
1511 ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
1512 {
1513         zval tmp;
1514 
1515         ZVAL_BOOL(&tmp, b);
1516         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1517 }
1518 /* }}} */
1519 
1520 ZEND_API int add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */
1521 {
1522         zval tmp;
1523 
1524         ZVAL_RES(&tmp, r);
1525         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1526 }
1527 /* }}} */
1528 
1529 ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
1530 {
1531         zval tmp;
1532 
1533         ZVAL_DOUBLE(&tmp, d);
1534         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1535 }
1536 /* }}} */
1537 
1538 ZEND_API int add_next_index_str(zval *arg, zend_string *str) /* {{{ */
1539 {
1540         zval tmp;
1541 
1542         ZVAL_STR(&tmp, str);
1543         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1544 }
1545 /* }}} */
1546 
1547 ZEND_API int add_next_index_string(zval *arg, const char *str) /* {{{ */
1548 {
1549         zval tmp;
1550 
1551         ZVAL_STRING(&tmp, str);
1552         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1553 }
1554 /* }}} */
1555 
1556 ZEND_API int add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
1557 {
1558         zval tmp;
1559 
1560         ZVAL_STRINGL(&tmp, str, length);
1561         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1562 }
1563 /* }}} */
1564 
1565 ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
1566 {
1567         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), value) ? SUCCESS : FAILURE;
1568 }
1569 /* }}} */
1570 
1571 ZEND_API zval *add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str) /* {{{ */
1572 {
1573         zval tmp, *ret;
1574 
1575         ZVAL_STRING(&tmp, str);
1576         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1577         return ret;
1578 }
1579 /* }}} */
1580 
1581 ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, size_t length) /* {{{ */
1582 {
1583         zval tmp, *ret;
1584 
1585         ZVAL_STRINGL(&tmp, str, length);
1586         ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1587         return ret;
1588 }
1589 /* }}} */
1590 
1591 ZEND_API zval *add_get_index_long(zval *arg, zend_ulong index, zend_long l) /* {{{ */
1592 {
1593         zval tmp;
1594 
1595         ZVAL_LONG(&tmp, l);
1596         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1597 }
1598 /* }}} */
1599 
1600 ZEND_API zval *add_get_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1601 {
1602         zval tmp;
1603 
1604         ZVAL_DOUBLE(&tmp, d);
1605         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1606 }
1607 /* }}} */
1608 
1609 ZEND_API zval *add_get_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1610 {
1611         zval tmp;
1612 
1613         ZVAL_STR(&tmp, str);
1614         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1615 }
1616 /* }}} */
1617 
1618 ZEND_API zval *add_get_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1619 {
1620         zval tmp;
1621 
1622         ZVAL_STRING(&tmp, str);
1623         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1624 }
1625 /* }}} */
1626 
1627 ZEND_API zval *add_get_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1628 {
1629         zval tmp;
1630 
1631         ZVAL_STRINGL(&tmp, str, length);
1632         return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1633 }
1634 /* }}} */
1635 
1636 ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
1637 {
1638         zval *result;
1639 
1640         switch (Z_TYPE_P(key)) {
1641                 case IS_STRING:
1642                         result = zend_symtable_update(ht, Z_STR_P(key), value);
1643                         break;
1644                 case IS_NULL:
1645                         result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value);
1646                         break;
1647                 case IS_RESOURCE:
1648                         zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
1649                         result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
1650                         break;
1651                 case IS_FALSE:
1652                         result = zend_hash_index_update(ht, 0, value);
1653                         break;
1654                 case IS_TRUE:
1655                         result = zend_hash_index_update(ht, 1, value);
1656                         break;
1657                 case IS_LONG:
1658                         result = zend_hash_index_update(ht, Z_LVAL_P(key), value);
1659                         break;
1660                 case IS_DOUBLE:
1661                         result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), value);
1662                         break;
1663                 default:
1664                         zend_error(E_WARNING, "Illegal offset type");
1665                         result = NULL;
1666         }
1667 
1668         if (result) {
1669                 if (Z_REFCOUNTED_P(result)) {
1670                         Z_ADDREF_P(result);
1671                 }
1672                 return SUCCESS;
1673         } else {
1674                 return FAILURE;
1675         }
1676 }
1677 /* }}} */
1678 
1679 ZEND_API int add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1680 {
1681         zval tmp;
1682         zval z_key;
1683 
1684         ZVAL_LONG(&tmp, n);
1685         ZVAL_STRINGL(&z_key, key, key_len);
1686         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1687         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1688         zval_ptr_dtor(&z_key);
1689         return SUCCESS;
1690 }
1691 /* }}} */
1692 
1693 ZEND_API int add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b) /* {{{ */
1694 {
1695         zval tmp;
1696         zval z_key;
1697 
1698         ZVAL_BOOL(&tmp, b);
1699         ZVAL_STRINGL(&z_key, key, key_len);
1700         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1701         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1702         zval_ptr_dtor(&z_key);
1703         return SUCCESS;
1704 }
1705 /* }}} */
1706 
1707 ZEND_API int add_property_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1708 {
1709         zval tmp;
1710         zval z_key;
1711 
1712         ZVAL_NULL(&tmp);
1713         ZVAL_STRINGL(&z_key, key, key_len);
1714         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1715         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1716         zval_ptr_dtor(&z_key);
1717         return SUCCESS;
1718 }
1719 /* }}} */
1720 
1721 ZEND_API int add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1722 {
1723         zval tmp;
1724         zval z_key;
1725 
1726         ZVAL_RES(&tmp, r);
1727         ZVAL_STRINGL(&z_key, key, key_len);
1728         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1729         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1730         zval_ptr_dtor(&z_key);
1731         return SUCCESS;
1732 }
1733 /* }}} */
1734 
1735 ZEND_API int add_property_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1736 {
1737         zval tmp;
1738         zval z_key;
1739 
1740         ZVAL_DOUBLE(&tmp, d);
1741         ZVAL_STRINGL(&z_key, key, key_len);
1742         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1743         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1744         zval_ptr_dtor(&z_key);
1745         return SUCCESS;
1746 }
1747 /* }}} */
1748 
1749 ZEND_API int add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1750 {
1751         zval tmp;
1752         zval z_key;
1753 
1754         ZVAL_STR(&tmp, str);
1755         ZVAL_STRINGL(&z_key, key, key_len);
1756         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1757         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1758         zval_ptr_dtor(&z_key);
1759         return SUCCESS;
1760 }
1761 /* }}} */
1762 
1763 ZEND_API int add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
1764 {
1765         zval tmp;
1766         zval z_key;
1767 
1768         ZVAL_STRING(&tmp, str);
1769         ZVAL_STRINGL(&z_key, key, key_len);
1770         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1771         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1772         zval_ptr_dtor(&z_key);
1773         return SUCCESS;
1774 }
1775 /* }}} */
1776 
1777 ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
1778 {
1779         zval tmp;
1780         zval z_key;
1781 
1782         ZVAL_STRINGL(&tmp, str, length);
1783         ZVAL_STRINGL(&z_key, key, key_len);
1784         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
1785         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1786         zval_ptr_dtor(&z_key);
1787         return SUCCESS;
1788 }
1789 /* }}} */
1790 
1791 ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1792 {
1793         zval z_key;
1794 
1795         ZVAL_STRINGL(&z_key, key, key_len);
1796         Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value, NULL);
1797         zval_ptr_dtor(&z_key);
1798         return SUCCESS;
1799 }
1800 /* }}} */
1801 
1802 ZEND_API int zend_startup_module_ex(zend_module_entry *module) /* {{{ */
1803 {
1804         size_t name_len;
1805         zend_string *lcname;
1806 
1807         if (module->module_started) {
1808                 return SUCCESS;
1809         }
1810         module->module_started = 1;
1811 
1812         /* Check module dependencies */
1813         if (module->deps) {
1814                 const zend_module_dep *dep = module->deps;
1815 
1816                 while (dep->name) {
1817                         if (dep->type == MODULE_DEP_REQUIRED) {
1818                                 zend_module_entry *req_mod;
1819 
1820                                 name_len = strlen(dep->name);
1821                                 lcname = zend_string_alloc(name_len, 0);
1822                                 zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
1823 
1824                                 if ((req_mod = zend_hash_find_ptr(&module_registry, lcname)) == NULL || !req_mod->module_started) {
1825                                         zend_string_free(lcname);
1826                                         /* TODO: Check version relationship */
1827                                         zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
1828                                         module->module_started = 0;
1829                                         return FAILURE;
1830                                 }
1831                                 zend_string_free(lcname);
1832                         }
1833                         ++dep;
1834                 }
1835         }
1836 
1837         /* Initialize module globals */
1838         if (module->globals_size) {
1839 #ifdef ZTS
1840                 ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
1841 #else
1842                 if (module->globals_ctor) {
1843                         module->globals_ctor(module->globals_ptr);
1844                 }
1845 #endif
1846         }
1847         if (module->module_startup_func) {
1848                 EG(current_module) = module;
1849                 if (module->module_startup_func(module->type, module->module_number)==FAILURE) {
1850                         zend_error_noreturn(E_CORE_ERROR,"Unable to start %s module", module->name);
1851                         EG(current_module) = NULL;
1852                         return FAILURE;
1853                 }
1854                 EG(current_module) = NULL;
1855         }
1856         return SUCCESS;
1857 }
1858 /* }}} */
1859 
1860 static int zend_startup_module_zval(zval *zv) /* {{{ */
1861 {
1862         zend_module_entry *module = Z_PTR_P(zv);
1863 
1864         return zend_startup_module_ex(module);
1865 }
1866 /* }}} */
1867 
1868 static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp) /* {{{ */
1869 {
1870         Bucket *b1 = base;
1871         Bucket *b2;
1872         Bucket *end = b1 + count;
1873         Bucket tmp;
1874         zend_module_entry *m, *r;
1875 
1876         while (b1 < end) {
1877 try_again:
1878                 m = (zend_module_entry*)Z_PTR(b1->val);
1879                 if (!m->module_started && m->deps) {
1880                         const zend_module_dep *dep = m->deps;
1881                         while (dep->name) {
1882                                 if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
1883                                         b2 = b1 + 1;
1884                                         while (b2 < end) {
1885                                                 r = (zend_module_entry*)Z_PTR(b2->val);
1886                                                 if (strcasecmp(dep->name, r->name) == 0) {
1887                                                         tmp = *b1;
1888                                                         *b1 = *b2;
1889                                                         *b2 = tmp;
1890                                                         goto try_again;
1891                                                 }
1892                                                 b2++;
1893                                         }
1894                                 }
1895                                 dep++;
1896                         }
1897                 }
1898                 b1++;
1899         }
1900 }
1901 /* }}} */
1902 
1903 ZEND_API void zend_collect_module_handlers(void) /* {{{ */
1904 {
1905         zend_module_entry *module;
1906         int startup_count = 0;
1907         int shutdown_count = 0;
1908         int post_deactivate_count = 0;
1909         zend_class_entry *ce;
1910         int class_count = 0;
1911 
1912         /* Collect extensions with request startup/shutdown handlers */
1913         ZEND_HASH_FOREACH_PTR(&module_registry, module) {
1914                 if (module->request_startup_func) {
1915                         startup_count++;
1916                 }
1917                 if (module->request_shutdown_func) {
1918                         shutdown_count++;
1919                 }
1920                 if (module->post_deactivate_func) {
1921                         post_deactivate_count++;
1922                 }
1923         } ZEND_HASH_FOREACH_END();
1924         module_request_startup_handlers = (zend_module_entry**)malloc(
1925             sizeof(zend_module_entry*) *
1926                 (startup_count + 1 +
1927                  shutdown_count + 1 +
1928                  post_deactivate_count + 1));
1929         module_request_startup_handlers[startup_count] = NULL;
1930         module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
1931         module_request_shutdown_handlers[shutdown_count] = NULL;
1932         module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
1933         module_post_deactivate_handlers[post_deactivate_count] = NULL;
1934         startup_count = 0;
1935 
1936         ZEND_HASH_FOREACH_PTR(&module_registry, module) {
1937                 if (module->request_startup_func) {
1938                         module_request_startup_handlers[startup_count++] = module;
1939                 }
1940                 if (module->request_shutdown_func) {
1941                         module_request_shutdown_handlers[--shutdown_count] = module;
1942                 }
1943                 if (module->post_deactivate_func) {
1944                         module_post_deactivate_handlers[--post_deactivate_count] = module;
1945                 }
1946         } ZEND_HASH_FOREACH_END();
1947 
1948         /* Collect internal classes with static members */
1949         ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1950                 if (ce->type == ZEND_INTERNAL_CLASS &&
1951                     ce->default_static_members_count > 0) {
1952                     class_count++;
1953                 }
1954         } ZEND_HASH_FOREACH_END();
1955 
1956         class_cleanup_handlers = (zend_class_entry**)malloc(
1957                 sizeof(zend_class_entry*) *
1958                 (class_count + 1));
1959         class_cleanup_handlers[class_count] = NULL;
1960 
1961         if (class_count) {
1962                 ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1963                         if (ce->type == ZEND_INTERNAL_CLASS &&
1964                             ce->default_static_members_count > 0) {
1965                             class_cleanup_handlers[--class_count] = ce;
1966                         }
1967                 } ZEND_HASH_FOREACH_END();
1968         }
1969 }
1970 /* }}} */
1971 
1972 ZEND_API int zend_startup_modules(void) /* {{{ */
1973 {
1974         zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
1975         zend_hash_apply(&module_registry, zend_startup_module_zval);
1976         return SUCCESS;
1977 }
1978 /* }}} */
1979 
1980 ZEND_API void zend_destroy_modules(void) /* {{{ */
1981 {
1982         free(class_cleanup_handlers);
1983         free(module_request_startup_handlers);
1984         zend_hash_graceful_reverse_destroy(&module_registry);
1985 }
1986 /* }}} */
1987 
1988 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /* {{{ */
1989 {
1990         size_t name_len;
1991         zend_string *lcname;
1992         zend_module_entry *module_ptr;
1993 
1994         if (!module) {
1995                 return NULL;
1996         }
1997 
1998 #if 0
1999         zend_printf("%s: Registering module %d\n", module->name, module->module_number);
2000 #endif
2001 
2002         /* Check module dependencies */
2003         if (module->deps) {
2004                 const zend_module_dep *dep = module->deps;
2005 
2006                 while (dep->name) {
2007                         if (dep->type == MODULE_DEP_CONFLICTS) {
2008                                 name_len = strlen(dep->name);
2009                                 lcname = zend_string_alloc(name_len, 0);
2010                                 zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2011 
2012                                 if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
2013                                         zend_string_free(lcname);
2014                                         /* TODO: Check version relationship */
2015                                         zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
2016                                         return NULL;
2017                                 }
2018                                 zend_string_free(lcname);
2019                         }
2020                         ++dep;
2021                 }
2022         }
2023 
2024         name_len = strlen(module->name);
2025         lcname = zend_string_alloc(name_len, 1);
2026         zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
2027 
2028         if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) {
2029                 zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
2030                 zend_string_release(lcname);
2031                 return NULL;
2032         }
2033         zend_string_release(lcname);
2034         module = module_ptr;
2035         EG(current_module) = module;
2036 
2037         if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
2038                 EG(current_module) = NULL;
2039                 zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
2040                 return NULL;
2041         }
2042 
2043         EG(current_module) = NULL;
2044         return module;
2045 }
2046 /* }}} */
2047 
2048 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module) /* {{{ */
2049 {
2050         module->module_number = zend_next_free_module();
2051         module->type = MODULE_PERSISTENT;
2052         return zend_register_module_ex(module);
2053 }
2054 /* }}} */
2055 
2056 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type) /* {{{ */
2057 {
2058         char lcname[16];
2059         size_t name_len;
2060 
2061         /* we don't care if the function name is longer, in fact lowercasing only
2062          * the beginning of the name speeds up the check process */
2063         name_len = ZSTR_LEN(fptr->common.function_name);
2064         zend_str_tolower_copy(lcname, ZSTR_VAL(fptr->common.function_name), MIN(name_len, sizeof(lcname)-1));
2065         lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
2066 
2067         if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1) && fptr->common.num_args != 0) {
2068                 zend_error(error_type, "Destructor %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_DESTRUCTOR_FUNC_NAME);
2069         } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - 1) && fptr->common.num_args != 0) {
2070                 zend_error(error_type, "Method %s::%s() cannot accept any arguments", ZSTR_VAL(ce->name), ZEND_CLONE_FUNC_NAME);
2071         } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) {
2072                 if (fptr->common.num_args != 1) {
2073                         zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_GET_FUNC_NAME);
2074                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2075                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_GET_FUNC_NAME);
2076                 }
2077         } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) {
2078                 if (fptr->common.num_args != 2) {
2079                         zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), ZEND_SET_FUNC_NAME);
2080                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2081                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_SET_FUNC_NAME);
2082                 }
2083         } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) {
2084                 if (fptr->common.num_args != 1) {
2085                         zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_UNSET_FUNC_NAME);
2086                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2087                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_UNSET_FUNC_NAME);
2088                 }
2089         } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) {
2090                 if (fptr->common.num_args != 1) {
2091                         zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_ISSET_FUNC_NAME);
2092                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2093                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_ISSET_FUNC_NAME);
2094                 }
2095         } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) {
2096                 if (fptr->common.num_args != 2) {
2097                         zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), ZEND_CALL_FUNC_NAME);
2098                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2099                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_CALL_FUNC_NAME);
2100                 }
2101         } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
2102                 !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)
2103         ) {
2104                 if (fptr->common.num_args != 2) {
2105                         zend_error(error_type, "Method %s::__callStatic() must take exactly 2 arguments", ZSTR_VAL(ce->name));
2106                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2107                         zend_error(error_type, "Method %s::__callStatic() cannot take arguments by reference", ZSTR_VAL(ce->name));
2108                 }
2109         } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
2110                 !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0
2111         ) {
2112                 zend_error(error_type, "Method %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_TOSTRING_FUNC_NAME);
2113         } else if (name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1 &&
2114                 !memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && fptr->common.num_args != 0) {
2115                 zend_error(error_type, "Method %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_DEBUGINFO_FUNC_NAME);
2116         }
2117 }
2118 /* }}} */
2119 
2120 /* registers all functions in *library_functions in the function hash */
2121 ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type) /* {{{ */
2122 {
2123         const zend_function_entry *ptr = functions;
2124         zend_function function, *reg_function;
2125         zend_internal_function *internal_function = (zend_internal_function *)&function;
2126         int count=0, unload=0;
2127         HashTable *target_function_table = function_table;
2128         int error_type;
2129         zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL;
2130         zend_string *lowercase_name;
2131         size_t fname_len;
2132         const char *lc_class_name = NULL;
2133         size_t class_name_len = 0;
2134 
2135         if (type==MODULE_PERSISTENT) {
2136                 error_type = E_CORE_WARNING;
2137         } else {
2138                 error_type = E_WARNING;
2139         }
2140 
2141         if (!target_function_table) {
2142                 target_function_table = CG(function_table);
2143         }
2144         internal_function->type = ZEND_INTERNAL_FUNCTION;
2145         internal_function->module = EG(current_module);
2146         memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
2147 
2148         if (scope) {
2149                 class_name_len = ZSTR_LEN(scope->name);
2150                 if ((lc_class_name = zend_memrchr(ZSTR_VAL(scope->name), '\\', class_name_len))) {
2151                         ++lc_class_name;
2152                         class_name_len -= (lc_class_name - ZSTR_VAL(scope->name));
2153                         lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
2154                 } else {
2155                         lc_class_name = zend_str_tolower_dup(ZSTR_VAL(scope->name), class_name_len);
2156                 }
2157         }
2158 
2159         while (ptr->fname) {
2160                 fname_len = strlen(ptr->fname);
2161                 internal_function->handler = ptr->handler;
2162                 internal_function->function_name = zend_new_interned_string(zend_string_init(ptr->fname, fname_len, 1));
2163                 internal_function->scope = scope;
2164                 internal_function->prototype = NULL;
2165                 if (ptr->flags) {
2166                         if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2167                                 if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
2168                                         zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2169                                 }
2170                                 internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2171                         } else {
2172                                 internal_function->fn_flags = ptr->flags;
2173                         }
2174                 } else {
2175                         internal_function->fn_flags = ZEND_ACC_PUBLIC;
2176                 }
2177                 if (ptr->arg_info) {
2178                         zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
2179 
2180                         internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1;
2181                         internal_function->num_args = ptr->num_args;
2182                         /* Currently you cannot denote that the function can accept less arguments than num_args */
2183                         if (info->required_num_args == (zend_uintptr_t)-1) {
2184                                 internal_function->required_num_args = ptr->num_args;
2185                         } else {
2186                                 internal_function->required_num_args = info->required_num_args;
2187                         }
2188                         if (info->return_reference) {
2189                                 internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
2190                         }
2191                         if (ptr->arg_info[ptr->num_args].is_variadic) {
2192                                 internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2193                                 /* Don't count the variadic argument */
2194                                 internal_function->num_args--;
2195                         }
2196                         if (info->type_hint) {
2197                                 if (info->class_name) {
2198                                         ZEND_ASSERT(info->type_hint == IS_OBJECT);
2199                                         if (!scope && (!strcasecmp(info->class_name, "self") || !strcasecmp(info->class_name, "parent"))) {
2200                                                 zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", info->class_name);
2201                                         }
2202                                 }
2203 
2204                                 internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2205                         }
2206                 } else {
2207                         internal_function->arg_info = NULL;
2208                         internal_function->num_args = 0;
2209                         internal_function->required_num_args = 0;
2210                 }
2211                 zend_set_function_arg_flags((zend_function*)internal_function);
2212                 if (ptr->flags & ZEND_ACC_ABSTRACT) {
2213                         if (scope) {
2214                                 /* This is a class that must be abstract itself. Here we set the check info. */
2215                                 scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2216                                 if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
2217                                         /* Since the class is not an interface it needs to be declared as a abstract class. */
2218                                         /* Since here we are handling internal functions only we can add the keyword flag. */
2219                                         /* This time we set the flag for the keyword 'abstract'. */
2220                                         scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2221                                 }
2222                         }
2223                         if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
2224                                 zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2225                         }
2226                 } else {
2227                         if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
2228                                 efree((char*)lc_class_name);
2229                                 zend_error(error_type, "Interface %s cannot contain non abstract method %s()", ZSTR_VAL(scope->name), ptr->fname);
2230                                 return FAILURE;
2231                         }
2232                         if (!internal_function->handler) {
2233                                 if (scope) {
2234                                         efree((char*)lc_class_name);
2235                                 }
2236                                 zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2237                                 zend_unregister_functions(functions, count, target_function_table);
2238                                 return FAILURE;
2239                         }
2240                 }
2241                 lowercase_name = zend_string_alloc(fname_len, 1);
2242                 zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2243                 lowercase_name = zend_new_interned_string(lowercase_name);
2244                 reg_function = malloc(sizeof(zend_internal_function));
2245                 memcpy(reg_function, &function, sizeof(zend_internal_function));
2246                 if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
2247                         unload=1;
2248                         free(reg_function);
2249                         zend_string_release(lowercase_name);
2250                         break;
2251                 }
2252 
2253                 /* If types of arguments have to be checked */
2254                 if (reg_function->common.arg_info && reg_function->common.num_args) {
2255                         uint32_t i;
2256                         for (i = 0; i < reg_function->common.num_args; i++) {
2257                                 if (reg_function->common.arg_info[i].class_name ||
2258                                     reg_function->common.arg_info[i].type_hint) {
2259                                     reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
2260                                         break;
2261                                 }
2262                         }
2263                 }
2264 
2265                 if (scope) {
2266                         /* Look for ctor, dtor, clone
2267                          * If it's an old-style constructor, store it only if we don't have
2268                          * a constructor already.
2269                          */
2270                         if ((fname_len == class_name_len) && !ctor && !memcmp(ZSTR_VAL(lowercase_name), lc_class_name, class_name_len+1)) {
2271                                 ctor = reg_function;
2272                         } else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2273                                 ctor = reg_function;
2274                         } else if (zend_string_equals_literal(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME)) {
2275                                 dtor = reg_function;
2276                                 if (internal_function->num_args) {
2277                                         zend_error(error_type, "Destructor %s::%s() cannot take arguments", ZSTR_VAL(scope->name), ptr->fname);
2278                                 }
2279                         } else if (zend_string_equals_literal(lowercase_name, ZEND_CLONE_FUNC_NAME)) {
2280                                 clone = reg_function;
2281                         } else if (zend_string_equals_literal(lowercase_name, ZEND_CALL_FUNC_NAME)) {
2282                                 __call = reg_function;
2283                         } else if (zend_string_equals_literal(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME)) {
2284                                 __callstatic = reg_function;
2285                         } else if (zend_string_equals_literal(lowercase_name, ZEND_TOSTRING_FUNC_NAME)) {
2286                                 __tostring = reg_function;
2287                         } else if (zend_string_equals_literal(lowercase_name, ZEND_GET_FUNC_NAME)) {
2288                                 __get = reg_function;
2289                                 scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2290                         } else if (zend_string_equals_literal(lowercase_name, ZEND_SET_FUNC_NAME)) {
2291                                 __set = reg_function;
2292                                 scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2293                         } else if (zend_string_equals_literal(lowercase_name, ZEND_UNSET_FUNC_NAME)) {
2294                                 __unset = reg_function;
2295                                 scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2296                         } else if (zend_string_equals_literal(lowercase_name, ZEND_ISSET_FUNC_NAME)) {
2297                                 __isset = reg_function;
2298                                 scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2299                         } else if (zend_string_equals_literal(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME)) {
2300                                 __debugInfo = reg_function;
2301                         } else {
2302                                 reg_function = NULL;
2303                         }
2304                         if (reg_function) {
2305                                 zend_check_magic_method_implementation(scope, reg_function, error_type);
2306                         }
2307                 }
2308                 ptr++;
2309                 count++;
2310                 zend_string_release(lowercase_name);
2311         }
2312         if (unload) { /* before unloading, display all remaining bad function in the module */
2313                 if (scope) {
2314                         efree((char*)lc_class_name);
2315                 }
2316                 while (ptr->fname) {
2317                         fname_len = strlen(ptr->fname);
2318                         lowercase_name = zend_string_alloc(fname_len, 0);
2319                         zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2320                         if (zend_hash_exists(target_function_table, lowercase_name)) {
2321                                 zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2322                         }
2323                         zend_string_free(lowercase_name);
2324                         ptr++;
2325                 }
2326                 zend_unregister_functions(functions, count, target_function_table);
2327                 return FAILURE;
2328         }
2329         if (scope) {
2330                 scope->constructor = ctor;
2331                 scope->destructor = dtor;
2332                 scope->clone = clone;
2333                 scope->__call = __call;
2334                 scope->__callstatic = __callstatic;
2335                 scope->__tostring = __tostring;
2336                 scope->__get = __get;
2337                 scope->__set = __set;
2338                 scope->__unset = __unset;
2339                 scope->__isset = __isset;
2340                 scope->__debugInfo = __debugInfo;
2341                 if (ctor) {
2342                         ctor->common.fn_flags |= ZEND_ACC_CTOR;
2343                         if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
2344                                 zend_error(error_type, "Constructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name));
2345                         }
2346                         ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2347                 }
2348                 if (dtor) {
2349                         dtor->common.fn_flags |= ZEND_ACC_DTOR;
2350                         if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
2351                                 zend_error(error_type, "Destructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name));
2352                         }
2353                         dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2354                 }
2355                 if (clone) {
2356                         clone->common.fn_flags |= ZEND_ACC_CLONE;
2357                         if (clone->common.fn_flags & ZEND_ACC_STATIC) {
2358                                 zend_error(error_type, "Constructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(clone->common.function_name));
2359                         }
2360                         clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2361                 }
2362                 if (__call) {
2363                         if (__call->common.fn_flags & ZEND_ACC_STATIC) {
2364                                 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__call->common.function_name));
2365                         }
2366                         __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2367                 }
2368                 if (__callstatic) {
2369                         if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
2370                                 zend_error(error_type, "Method %s::%s() must be static", ZSTR_VAL(scope->name), ZSTR_VAL(__callstatic->common.function_name));
2371                         }
2372                         __callstatic->common.fn_flags |= ZEND_ACC_STATIC;
2373                 }
2374                 if (__tostring) {
2375                         if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
2376                                 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__tostring->common.function_name));
2377                         }
2378                         __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2379                 }
2380                 if (__get) {
2381                         if (__get->common.fn_flags & ZEND_ACC_STATIC) {
2382                                 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__get->common.function_name));
2383                         }
2384                         __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2385                 }
2386                 if (__set) {
2387                         if (__set->common.fn_flags & ZEND_ACC_STATIC) {
2388                                 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__set->common.function_name));
2389                         }
2390                         __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2391                 }
2392                 if (__unset) {
2393                         if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
2394                                 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__unset->common.function_name));
2395                         }
2396                         __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2397                 }
2398                 if (__isset) {
2399                         if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
2400                                 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__isset->common.function_name));
2401                         }
2402                         __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2403                 }
2404                 if (__debugInfo) {
2405                         if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) {
2406                                 zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__debugInfo->common.function_name));
2407                         }
2408                 }
2409 
2410                 if (ctor && ctor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && ctor->common.fn_flags & ZEND_ACC_CTOR) {
2411                         zend_error_noreturn(E_CORE_ERROR, "Constructor %s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name));
2412                 }
2413 
2414                 if (dtor && dtor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && dtor->common.fn_flags & ZEND_ACC_DTOR) {
2415                         zend_error_noreturn(E_CORE_ERROR, "Destructor %s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name));
2416                 }
2417 
2418                 if (clone && clone->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && dtor->common.fn_flags & ZEND_ACC_DTOR) {
2419                         zend_error_noreturn(E_CORE_ERROR, "%s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(clone->common.function_name));
2420                 }
2421                 efree((char*)lc_class_name);
2422         }
2423         return SUCCESS;
2424 }
2425 /* }}} */
2426 
2427 /* count=-1 means erase all functions, otherwise,
2428  * erase the first count functions
2429  */
2430 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table) /* {{{ */
2431 {
2432         const zend_function_entry *ptr = functions;
2433         int i=0;
2434         HashTable *target_function_table = function_table;
2435         zend_string *lowercase_name;
2436         size_t fname_len;
2437 
2438         if (!target_function_table) {
2439                 target_function_table = CG(function_table);
2440         }
2441         while (ptr->fname) {
2442                 if (count!=-1 && i>=count) {
2443                         break;
2444                 }
2445                 fname_len = strlen(ptr->fname);
2446                 lowercase_name = zend_string_alloc(fname_len, 0);
2447                 zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2448                 zend_hash_del(target_function_table, lowercase_name);
2449                 zend_string_free(lowercase_name);
2450                 ptr++;
2451                 i++;
2452         }
2453 }
2454 /* }}} */
2455 
2456 ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */
2457 {
2458         if ((module = zend_register_internal_module(module)) != NULL && zend_startup_module_ex(module) == SUCCESS) {
2459                 return SUCCESS;
2460         }
2461         return FAILURE;
2462 }
2463 /* }}} */
2464 
2465 ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
2466 {
2467         zend_module_entry *module;
2468 
2469         module = zend_hash_str_find_ptr(&module_registry, module_name, strlen(module_name));
2470         return (module && module->module_started) ? SUCCESS : FAILURE;
2471 }
2472 /* }}} */
2473 
2474 static int clean_module_class(zval *el, void *arg) /* {{{ */
2475 {
2476         zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
2477         int module_number = *(int *)arg;
2478         if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
2479                 return ZEND_HASH_APPLY_REMOVE;
2480         } else {
2481                 return ZEND_HASH_APPLY_KEEP;
2482         }
2483 }
2484 /* }}} */
2485 
2486 static void clean_module_classes(int module_number) /* {{{ */
2487 {
2488         zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number);
2489 }
2490 /* }}} */
2491 
2492 void module_destructor(zend_module_entry *module) /* {{{ */
2493 {
2494 
2495         if (module->type == MODULE_TEMPORARY) {
2496                 zend_clean_module_rsrc_dtors(module->module_number);
2497                 clean_module_constants(module->module_number);
2498                 clean_module_classes(module->module_number);
2499         }
2500 
2501         if (module->module_started && module->module_shutdown_func) {
2502 #if 0
2503                 zend_printf("%s: Module shutdown\n", module->name);
2504 #endif
2505                 module->module_shutdown_func(module->type, module->module_number);
2506         }
2507 
2508         /* Deinitilaise module globals */
2509         if (module->globals_size) {
2510 #ifdef ZTS
2511                 if (*module->globals_id_ptr) {
2512                         ts_free_id(*module->globals_id_ptr);
2513                 }
2514 #else
2515                 if (module->globals_dtor) {
2516                         module->globals_dtor(module->globals_ptr);
2517                 }
2518 #endif
2519         }
2520 
2521         module->module_started=0;
2522         if (module->functions) {
2523                 zend_unregister_functions(module->functions, -1, NULL);
2524         }
2525 
2526 #if HAVE_LIBDL
2527 #if !(defined(NETWARE) && defined(APACHE_1_BUILD))
2528         if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2529                 DL_UNLOAD(module->handle);
2530         }
2531 #endif
2532 #endif
2533 }
2534 /* }}} */
2535 
2536 ZEND_API void zend_activate_modules(void) /* {{{ */
2537 {
2538         zend_module_entry **p = module_request_startup_handlers;
2539 
2540         while (*p) {
2541                 zend_module_entry *module = *p;
2542 
2543                 if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
2544                         zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
2545                         exit(1);
2546                 }
2547                 p++;
2548         }
2549 }
2550 /* }}} */
2551 
2552 /* call request shutdown for all modules */
2553 static int module_registry_cleanup(zval *zv) /* {{{ */
2554 {
2555         zend_module_entry *module = Z_PTR_P(zv);
2556 
2557         if (module->request_shutdown_func) {
2558 #if 0
2559                 zend_printf("%s: Request shutdown\n", module->name);
2560 #endif
2561                 module->request_shutdown_func(module->type, module->module_number);
2562         }
2563         return 0;
2564 }
2565 /* }}} */
2566 
2567 ZEND_API void zend_deactivate_modules(void) /* {{{ */
2568 {
2569         EG(current_execute_data) = NULL; /* we're no longer executing anything */
2570 
2571         zend_try {
2572                 if (EG(full_tables_cleanup)) {
2573                         zend_hash_reverse_apply(&module_registry, module_registry_cleanup);
2574                 } else {
2575                         zend_module_entry **p = module_request_shutdown_handlers;
2576 
2577                         while (*p) {
2578                                 zend_module_entry *module = *p;
2579 
2580                                 module->request_shutdown_func(module->type, module->module_number);
2581                                 p++;
2582                         }
2583                 }
2584         } zend_end_try();
2585 }
2586 /* }}} */
2587 
2588 ZEND_API void zend_cleanup_internal_classes(void) /* {{{ */
2589 {
2590         zend_class_entry **p = class_cleanup_handlers;
2591 
2592         while (*p) {
2593                 zend_cleanup_internal_class_data(*p);
2594                 p++;
2595         }
2596 }
2597 /* }}} */
2598 
2599 int module_registry_unload_temp(const zend_module_entry *module) /* {{{ */
2600 {
2601         return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
2602 }
2603 /* }}} */
2604 
2605 static int module_registry_unload_temp_wrapper(zval *el) /* {{{ */
2606 {
2607         zend_module_entry *module = (zend_module_entry *)Z_PTR_P(el);
2608         return module_registry_unload_temp((const zend_module_entry *)module);
2609 }
2610 /* }}} */
2611 
2612 static int exec_done_cb(zval *el) /* {{{ */
2613 {
2614         zend_module_entry *module = (zend_module_entry *)Z_PTR_P(el);
2615         if (module->post_deactivate_func) {
2616                 module->post_deactivate_func();
2617         }
2618         return 0;
2619 }
2620 /* }}} */
2621 
2622 ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
2623 {
2624         if (EG(full_tables_cleanup)) {
2625                 zend_hash_apply(&module_registry, exec_done_cb);
2626                 zend_hash_reverse_apply(&module_registry, module_registry_unload_temp_wrapper);
2627         } else {
2628                 zend_module_entry **p = module_post_deactivate_handlers;
2629 
2630                 while (*p) {
2631                         zend_module_entry *module = *p;
2632 
2633                         module->post_deactivate_func();
2634                         p++;
2635                 }
2636         }
2637 }
2638 /* }}} */
2639 
2640 /* return the next free module number */
2641 ZEND_API int zend_next_free_module(void) /* {{{ */
2642 {
2643         return zend_hash_num_elements(&module_registry) + 1;
2644 }
2645 /* }}} */
2646 
2647 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
2648 {
2649         zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
2650         zend_string *lowercase_name = zend_string_alloc(ZSTR_LEN(orig_class_entry->name), 1);
2651         *class_entry = *orig_class_entry;
2652 
2653         class_entry->type = ZEND_INTERNAL_CLASS;
2654         zend_initialize_class_data(class_entry, 0);
2655         class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED;
2656         class_entry->info.internal.module = EG(current_module);
2657 
2658         if (class_entry->info.internal.builtin_functions) {
2659                 zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, MODULE_PERSISTENT);
2660         }
2661 
2662         zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ZSTR_VAL(orig_class_entry->name), ZSTR_LEN(class_entry->name));
2663         lowercase_name = zend_new_interned_string(lowercase_name);
2664         zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
2665         zend_string_release(lowercase_name);
2666         return class_entry;
2667 }
2668 /* }}} */
2669 
2670 /* If parent_ce is not NULL then it inherits from parent_ce
2671  * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
2672  * If both parent_ce and parent_name are NULL it does a regular class registration
2673  * If parent_name is specified but not found NULL is returned
2674  */
2675 ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */
2676 {
2677         zend_class_entry *register_class;
2678 
2679         register_class = zend_register_internal_class(class_entry);
2680 
2681         if (parent_ce) {
2682                 zend_do_inheritance(register_class, parent_ce);
2683         }
2684         return register_class;
2685 }
2686 /* }}} */
2687 
2688 ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...) /* {{{ */
2689 {
2690         zend_class_entry *interface_entry;
2691         va_list interface_list;
2692         va_start(interface_list, num_interfaces);
2693 
2694         while (num_interfaces--) {
2695                 interface_entry = va_arg(interface_list, zend_class_entry *);
2696                 zend_do_implement_interface(class_entry, interface_entry);
2697         }
2698 
2699         va_end(interface_list);
2700 }
2701 /* }}} */
2702 
2703 /* A class that contains at least one abstract method automatically becomes an abstract class.
2704  */
2705 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */
2706 {
2707         return do_register_internal_class(orig_class_entry, 0);
2708 }
2709 /* }}} */
2710 
2711 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry) /* {{{ */
2712 {
2713         return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE);
2714 }
2715 /* }}} */
2716 
2717 ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce) /* {{{ */
2718 {
2719         zend_string *lcname;
2720 
2721         if (name[0] == '\\') {
2722                 lcname = zend_string_alloc(name_len-1, 1);
2723                 zend_str_tolower_copy(ZSTR_VAL(lcname), name+1, name_len-1);
2724         } else {
2725                 lcname = zend_string_alloc(name_len, 1);
2726                 zend_str_tolower_copy(ZSTR_VAL(lcname), name, name_len);
2727         }
2728 
2729         zend_assert_valid_class_name(lcname);
2730 
2731         ce = zend_hash_add_ptr(CG(class_table), lcname, ce);
2732         zend_string_release(lcname);
2733         if (ce) {
2734                 ce->refcount++;
2735                 return SUCCESS;
2736         }
2737         return FAILURE;
2738 }
2739 /* }}} */
2740 
2741 ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */
2742 {
2743         HashTable *symbol_table;
2744         va_list symbol_table_list;
2745 
2746         if (num_symbol_tables <= 0) return FAILURE;
2747 
2748         if (is_ref) {
2749                 ZVAL_MAKE_REF(symbol);
2750         }
2751 
2752         va_start(symbol_table_list, num_symbol_tables);
2753         while (num_symbol_tables-- > 0) {
2754                 symbol_table = va_arg(symbol_table_list, HashTable *);
2755                 zend_hash_str_update(symbol_table, name, name_length, symbol);
2756                 if (Z_REFCOUNTED_P(symbol)) {
2757                         Z_ADDREF_P(symbol);
2758                 }
2759         }
2760         va_end(symbol_table_list);
2761         return SUCCESS;
2762 }
2763 /* }}} */
2764 
2765 /* Disabled functions support */
2766 
2767 /* {{{ proto void display_disabled_function(void)
2768 Dummy function which displays an error when a disabled function is called. */
2769 ZEND_API ZEND_FUNCTION(display_disabled_function)
2770 {
2771         zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name());
2772 }
2773 /* }}} */
2774 
2775 ZEND_API int zend_disable_function(char *function_name, size_t function_name_length) /* {{{ */
2776 {
2777         zend_internal_function *func;
2778         if ((func = zend_hash_str_find_ptr(CG(function_table), function_name, function_name_length))) {
2779             func->fn_flags &= ~(ZEND_ACC_VARIADIC | ZEND_ACC_HAS_TYPE_HINTS);
2780                 func->num_args = 0;
2781                 func->arg_info = NULL;
2782                 func->handler = ZEND_FN(display_disabled_function);
2783                 return SUCCESS;
2784         }
2785         return FAILURE;
2786 }
2787 /* }}} */
2788 
2789 #ifdef ZEND_WIN32
2790 #pragma optimize("", off)
2791 #endif
2792 static zend_object *display_disabled_class(zend_class_entry *class_type) /* {{{ */
2793 {
2794         zend_object *intern;
2795 
2796         intern = zend_objects_new(class_type);
2797         zend_error(E_WARNING, "%s() has been disabled for security reasons", ZSTR_VAL(class_type->name));
2798         return intern;
2799 }
2800 #ifdef ZEND_WIN32
2801 #pragma optimize("", on)
2802 #endif
2803 /* }}} */
2804 
2805 static const zend_function_entry disabled_class_new[] = {
2806         ZEND_FE_END
2807 };
2808 
2809 ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {{{ */
2810 {
2811         zend_class_entry *disabled_class;
2812         zend_string *key;
2813 
2814         key = zend_string_alloc(class_name_length, 0);
2815         zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
2816         disabled_class = zend_hash_find_ptr(CG(class_table), key);
2817         if (!disabled_class) {
2818                 return FAILURE;
2819         }
2820         INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new, NULL, NULL, NULL, NULL, NULL);
2821         disabled_class->create_object = display_disabled_class;
2822         zend_hash_clean(&disabled_class->function_table);
2823         return SUCCESS;
2824 }
2825 /* }}} */
2826 
2827 static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */
2828 {
2829         int ret = 0;
2830         zend_class_entry *ce;
2831         size_t name_len = ZSTR_LEN(name);
2832         zend_string *lcname;
2833         ALLOCA_FLAG(use_heap);
2834 
2835         ZSTR_ALLOCA_ALLOC(lcname, name_len, use_heap);
2836         zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name), name_len);
2837 
2838         *strict_class = 0;
2839         if (zend_string_equals_literal(lcname, "self")) {
2840                 if (!EG(scope)) {
2841                         if (error) *error = estrdup("cannot access self:: when no class scope is active");
2842                 } else {
2843                         fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
2844                         fcc->calling_scope = EG(scope);
2845                         if (!fcc->object) {
2846                                 fcc->object = zend_get_this_object(EG(current_execute_data));
2847                         }
2848                         ret = 1;
2849                 }
2850         } else if (zend_string_equals_literal(lcname, "parent")) {
2851                 if (!EG(scope)) {
2852                         if (error) *error = estrdup("cannot access parent:: when no class scope is active");
2853                 } else if (!EG(scope)->parent) {
2854                         if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
2855                 } else {
2856                         fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
2857                         fcc->calling_scope = EG(scope)->parent;
2858                         if (!fcc->object) {
2859                                 fcc->object = zend_get_this_object(EG(current_execute_data));
2860                         }
2861                         *strict_class = 1;
2862                         ret = 1;
2863                 }
2864         } else if (zend_string_equals_literal(lcname, "static")) {
2865                 zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
2866 
2867                 if (!called_scope) {
2868                         if (error) *error = estrdup("cannot access static:: when no class scope is active");
2869                 } else {
2870                         fcc->called_scope = called_scope;
2871                         fcc->calling_scope = called_scope;
2872                         if (!fcc->object) {
2873                                 fcc->object = zend_get_this_object(EG(current_execute_data));
2874                         }
2875                         *strict_class = 1;
2876                         ret = 1;
2877                 }
2878         } else if ((ce = zend_lookup_class_ex(name, NULL, 1)) != NULL) {
2879                 zend_class_entry *scope;
2880                 zend_execute_data *ex = EG(current_execute_data);
2881 
2882                 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
2883                         ex = ex->prev_execute_data;
2884                 }
2885                 scope = ex ? ex->func->common.scope : NULL;
2886                 fcc->calling_scope = ce;
2887                 if (scope && !fcc->object) {
2888                         zend_object *object = zend_get_this_object(EG(current_execute_data));
2889 
2890                         if (object &&
2891                             instanceof_function(object->ce, scope) &&
2892                             instanceof_function(scope, fcc->calling_scope)) {
2893                                 fcc->object = object;
2894                                 fcc->called_scope = object->ce;
2895                         } else {
2896                                 fcc->called_scope = fcc->calling_scope;
2897                         }
2898                 } else {
2899                         fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
2900                 }
2901                 *strict_class = 1;
2902                 ret = 1;
2903         } else {
2904                 if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, ZSTR_VAL(name));
2905         }
2906         ZSTR_ALLOCA_FREE(lcname, use_heap);
2907         return ret;
2908 }
2909 /* }}} */
2910 
2911 static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error) /* {{{ */
2912 {
2913         zend_class_entry *ce_org = fcc->calling_scope;
2914         int retval = 0;
2915         zend_string *mname, *cname;
2916         zend_string *lmname;
2917         const char *colon;
2918         size_t clen, mlen;
2919         zend_class_entry *last_scope;
2920         HashTable *ftable;
2921         int call_via_handler = 0;
2922         ALLOCA_FLAG(use_heap)
2923 
2924         if (error) {
2925                 *error = NULL;
2926         }
2927 
2928         fcc->calling_scope = NULL;
2929         fcc->function_handler = NULL;
2930 
2931         if (!ce_org) {
2932                 zend_string *lmname;
2933 
2934                 /* Skip leading \ */
2935                 if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
2936                         ZSTR_ALLOCA_INIT(lmname, Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1, use_heap);
2937                 } else {
2938                         lmname = Z_STR_P(callable);
2939                 }
2940                 /* Check if function with given name exists.
2941                  * This may be a compound name that includes namespace name */
2942                 if (EXPECTED((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL)) {
2943                         if (lmname != Z_STR_P(callable)) {
2944                                 ZSTR_ALLOCA_FREE(lmname, use_heap);
2945                         }
2946                         fcc->initialized = 1;
2947                         return 1;
2948                 } else {
2949                         if (lmname == Z_STR_P(callable)) {
2950                                 ZSTR_ALLOCA_INIT(lmname, Z_STRVAL_P(callable), Z_STRLEN_P(callable), use_heap);
2951                         } else {
2952                                 zend_string_forget_hash_val(lmname);
2953                         }
2954                         zend_str_tolower(ZSTR_VAL(lmname), ZSTR_LEN(lmname));
2955                         if ((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL) {
2956                                 ZSTR_ALLOCA_FREE(lmname, use_heap);
2957                                 fcc->initialized = 1;
2958                                 return 1;
2959                         }
2960                 }
2961                 if (lmname != Z_STR_P(callable)) {
2962                         ZSTR_ALLOCA_FREE(lmname, use_heap);
2963                 }
2964         }
2965 
2966         /* Split name into class/namespace and method/function names */
2967         if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
2968                 colon > Z_STRVAL_P(callable) &&
2969                 *(colon-1) == ':'
2970         ) {
2971                 colon--;
2972                 clen = colon - Z_STRVAL_P(callable);
2973                 mlen = Z_STRLEN_P(callable) - clen - 2;
2974 
2975                 if (colon == Z_STRVAL_P(callable)) {
2976                         if (error) zend_spprintf(error, 0, "invalid function name");
2977                         return 0;
2978                 }
2979 
2980                 /* This is a compound name.
2981                  * Try to fetch class and then find static method. */
2982                 last_scope = EG(scope);
2983                 if (ce_org) {
2984                         EG(scope) = ce_org;
2985                 }
2986 
2987                 cname = zend_string_init(Z_STRVAL_P(callable), clen, 0);
2988                 if (!zend_is_callable_check_class(cname, fcc, &strict_class, error)) {
2989                         zend_string_release(cname);
2990                         EG(scope) = last_scope;
2991                         return 0;
2992                 }
2993                 zend_string_release(cname);
2994                 EG(scope) = last_scope;
2995 
2996                 ftable = &fcc->calling_scope->function_table;
2997                 if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) {
2998                         if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ZSTR_VAL(ce_org->name), ZSTR_VAL(fcc->calling_scope->name));
2999                         return 0;
3000                 }
3001                 mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
3002         } else if (ce_org) {
3003                 /* Try to fetch find static method of given class. */
3004                 mlen = Z_STRLEN_P(callable);
3005                 mname = Z_STR_P(callable);
3006                 zend_string_addref(mname);
3007                 ftable = &ce_org->function_table;
3008                 fcc->calling_scope = ce_org;
3009         } else {
3010                 /* We already checked for plain function before. */
3011                 if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3012                         zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
3013                 }
3014                 return 0;
3015         }
3016 
3017         lmname = zend_string_tolower(mname);
3018         if (strict_class &&
3019             fcc->calling_scope &&
3020                 zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
3021                 fcc->function_handler = fcc->calling_scope->constructor;
3022                 if (fcc->function_handler) {
3023                         retval = 1;
3024                 }
3025         } else if ((fcc->function_handler = zend_hash_find_ptr(ftable, lmname)) != NULL) {
3026                 retval = 1;
3027                 if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
3028                     !strict_class && EG(scope) &&
3029                     instanceof_function(fcc->function_handler->common.scope, EG(scope))) {
3030                         zend_function *priv_fbc;
3031 
3032                         if ((priv_fbc = zend_hash_find_ptr(&EG(scope)->function_table, lmname)) != NULL
3033                                 && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
3034                                 && priv_fbc->common.scope == EG(scope)) {
3035                                 fcc->function_handler = priv_fbc;
3036                         }
3037                 }
3038                 if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
3039                     (fcc->calling_scope &&
3040                      ((fcc->object && fcc->calling_scope->__call) ||
3041                       (!fcc->object && fcc->calling_scope->__callstatic)))) {
3042                         if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
3043                                 if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname)) {
3044                                         retval = 0;
3045                                         fcc->function_handler = NULL;
3046                                         goto get_function_via_handler;
3047                                 }
3048                         } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
3049                                 if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
3050                                         retval = 0;
3051                                         fcc->function_handler = NULL;
3052                                         goto get_function_via_handler;
3053                                 }
3054                         }
3055                 }
3056         } else {
3057 get_function_via_handler:
3058                 if (fcc->object && fcc->calling_scope == ce_org) {
3059                         if (strict_class && ce_org->__call) {
3060                                 fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
3061                                 call_via_handler = 1;
3062                                 retval = 1;
3063                         } else if (fcc->object->handlers->get_method) {
3064                                 fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
3065                                 if (fcc->function_handler) {
3066                                         if (strict_class &&
3067                                             (!fcc->function_handler->common.scope ||
3068                                              !instanceof_function(ce_org, fcc->function_handler->common.scope))) {
3069                                                 if (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
3070                                                         if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3071                                                                 zend_string_release(fcc->function_handler->common.function_name);
3072                                                         }
3073                                                         zend_free_trampoline(fcc->function_handler);
3074                                                 }
3075                                         } else {
3076                                                 retval = 1;
3077                                                 call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3078                                         }
3079                                 }
3080                         }
3081                 } else if (fcc->calling_scope) {
3082                         if (fcc->calling_scope->get_static_method) {
3083                                 fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname);
3084                         } else {
3085                                 fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, NULL);
3086                         }
3087                         if (fcc->function_handler) {
3088                                 retval = 1;
3089                                 call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3090                                 if (call_via_handler && !fcc->object) {
3091                                         zend_object *object = zend_get_this_object(EG(current_execute_data));
3092                                         if (object &&
3093                                             instanceof_function(object->ce, fcc->calling_scope)) {
3094                                                 fcc->object = object;
3095                                         }
3096                                 }
3097                         }
3098                 }
3099         }
3100 
3101         if (retval) {
3102                 if (fcc->calling_scope && !call_via_handler) {
3103                         if (!fcc->object && (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT)) {
3104                                 if (error) {
3105                                         zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3106                                         retval = 0;
3107                                 } else {
3108                                         zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3109                                         return 0;
3110                                 }
3111                         } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3112                                 int severity;
3113                                 char *verb;
3114                                 if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
3115                                         severity = E_DEPRECATED;
3116                                         verb = "should not";
3117                                 } else {
3118                                         /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
3119                                         severity = E_ERROR;
3120                                         verb = "cannot";
3121                                 }
3122                                 if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
3123                                         retval = 0;
3124                                 }
3125                                 if (error) {
3126                                         zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
3127                                         if (severity != E_DEPRECATED) {
3128                                                 retval = 0;
3129                                         }
3130                                 } else if (retval) {
3131                                         if (severity == E_ERROR) {
3132                                                 zend_throw_error(NULL, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
3133                                         } else {
3134                                                 zend_error(severity, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
3135                                         }
3136                                 }
3137                         }
3138                         if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
3139                                 if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
3140                                         if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname)) {
3141                                                 if (error) {
3142                                                         if (*error) {
3143                                                                 efree(*error);
3144                                                         }
3145                                                         zend_spprintf(error, 0, "cannot access private method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3146                                                 }
3147                                                 retval = 0;
3148                                         }
3149                                 } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
3150                                         if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
3151                                                 if (error) {
3152                                                         if (*error) {
3153                                                                 efree(*error);
3154                                                         }
3155                                                         zend_spprintf(error, 0, "cannot access protected method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3156                                                 }
3157                                                 retval = 0;
3158                                         }
3159                                 }
3160                         }
3161                 }
3162         } else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3163                 if (fcc->calling_scope) {
3164                         if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(mname));
3165                 } else {
3166                         if (error) zend_spprintf(error, 0, "function '%s' does not exist", ZSTR_VAL(mname));
3167                 }
3168         }
3169         zend_string_release(lmname);
3170         zend_string_release(mname);
3171 
3172         if (fcc->object) {
3173                 fcc->called_scope = fcc->object->ce;
3174         }
3175         if (retval) {
3176                 fcc->initialized = 1;
3177         }
3178         return retval;
3179 }
3180 /* }}} */
3181 
3182 ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */
3183 {
3184         zend_bool ret;
3185         zend_fcall_info_cache fcc_local;
3186 
3187         if (callable_name) {
3188                 *callable_name = NULL;
3189         }
3190         if (fcc == NULL) {
3191                 fcc = &fcc_local;
3192         }
3193         if (error) {
3194                 *error = NULL;
3195         }
3196 
3197         fcc->initialized = 0;
3198         fcc->calling_scope = NULL;
3199         fcc->called_scope = NULL;
3200         fcc->function_handler = NULL;
3201         fcc->object = NULL;
3202 
3203         if (object &&
3204             (!EG(objects_store).object_buckets ||
3205              !IS_OBJ_VALID(EG(objects_store).object_buckets[object->handle]))) {
3206                 return 0;
3207         }
3208 
3209 again:
3210         switch (Z_TYPE_P(callable)) {
3211                 case IS_STRING:
3212                         if (object) {
3213                                 fcc->object = object;
3214                                 fcc->calling_scope = object->ce;
3215                                 if (callable_name) {
3216                                         char *ptr;
3217 
3218                                         *callable_name = zend_string_alloc(ZSTR_LEN(fcc->calling_scope->name) + Z_STRLEN_P(callable) + sizeof("::") - 1, 0);
3219                                         ptr = ZSTR_VAL(*callable_name);
3220                                         memcpy(ptr, ZSTR_VAL(fcc->calling_scope->name), ZSTR_LEN(fcc->calling_scope->name));
3221                                         ptr += ZSTR_LEN(fcc->calling_scope->name);
3222                                         memcpy(ptr, "::", sizeof("::") - 1);
3223                                         ptr += sizeof("::") - 1;
3224                                         memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1);
3225                                 }
3226                         } else if (callable_name) {
3227                                 *callable_name = zend_string_copy(Z_STR_P(callable));
3228                         }
3229                         if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3230                                 fcc->called_scope = fcc->calling_scope;
3231                                 return 1;
3232                         }
3233 
3234                         ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error);
3235                         if (fcc == &fcc_local &&
3236                             fcc->function_handler &&
3237                                 ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
3238                              fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3239                              fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3240                                 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3241                                         zend_string_release(fcc->function_handler->common.function_name);
3242                                 }
3243                                 zend_free_trampoline(fcc->function_handler);
3244                         }
3245                         return ret;
3246 
3247                 case IS_ARRAY:
3248                         {
3249                                 zval *method = NULL;
3250                                 zval *obj = NULL;
3251                                 int strict_class = 0;
3252 
3253                                 if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3254                                         obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
3255                                         method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
3256                                 }
3257 
3258                                 do {
3259                                         if (obj == NULL || method == NULL) {
3260                                                 break;
3261                                         }
3262 
3263                                         ZVAL_DEREF(method);
3264                                         if (Z_TYPE_P(method) != IS_STRING) {
3265                                                 break;
3266                                         }
3267 
3268                                         ZVAL_DEREF(obj);
3269                                         if (Z_TYPE_P(obj) == IS_STRING) {
3270                                                 if (callable_name) {
3271                                                         char *ptr;
3272 
3273 
3274                                                         *callable_name = zend_string_alloc(Z_STRLEN_P(obj) + Z_STRLEN_P(method) + sizeof("::") - 1, 0);
3275                                                         ptr = ZSTR_VAL(*callable_name);
3276                                                         memcpy(ptr, Z_STRVAL_P(obj), Z_STRLEN_P(obj));
3277                                                         ptr += Z_STRLEN_P(obj);
3278                                                         memcpy(ptr, "::", sizeof("::") - 1);
3279                                                         ptr += sizeof("::") - 1;
3280                                                         memcpy(ptr, Z_STRVAL_P(method), Z_STRLEN_P(method) + 1);
3281                                                 }
3282 
3283                                                 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3284                                                         return 1;
3285                                                 }
3286 
3287                                                 if (!zend_is_callable_check_class(Z_STR_P(obj), fcc, &strict_class, error)) {
3288                                                         return 0;
3289                                                 }
3290 
3291                                         } else if (Z_TYPE_P(obj) == IS_OBJECT) {
3292                                                 if (!EG(objects_store).object_buckets ||
3293                                                     !IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(obj)])) {
3294                                                         return 0;
3295                                                 }
3296 
3297                                                 fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
3298 
3299                                                 fcc->object = Z_OBJ_P(obj);
3300 
3301                                                 if (callable_name) {
3302                                                         char *ptr;
3303 
3304                                                         *callable_name = zend_string_alloc(ZSTR_LEN(fcc->calling_scope->name) + Z_STRLEN_P(method) + sizeof("::") - 1, 0);
3305                                                         ptr = ZSTR_VAL(*callable_name);
3306                                                         memcpy(ptr, ZSTR_VAL(fcc->calling_scope->name), ZSTR_LEN(fcc->calling_scope->name));
3307                                                         ptr += ZSTR_LEN(fcc->calling_scope->name);
3308                                                         memcpy(ptr, "::", sizeof("::") - 1);
3309                                                         ptr += sizeof("::") - 1;
3310                                                         memcpy(ptr, Z_STRVAL_P(method), Z_STRLEN_P(method) + 1);
3311                                                 }
3312 
3313                                                 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3314                                                         fcc->called_scope = fcc->calling_scope;
3315                                                         return 1;
3316                                                 }
3317                                         } else {
3318                                                 break;
3319                                         }
3320 
3321                                         ret = zend_is_callable_check_func(check_flags, method, fcc, strict_class, error);
3322                                         if (fcc == &fcc_local &&
3323                                             fcc->function_handler &&
3324                                                 ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
3325                                              fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3326                                              fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3327                                                 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3328                                                         zend_string_release(fcc->function_handler->common.function_name);
3329                                                 }
3330                                                 zend_free_trampoline(fcc->function_handler);
3331                                         }
3332                                         return ret;
3333 
3334                                 } while (0);
3335                                 if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3336                                         if (!obj || (!Z_ISREF_P(obj)?
3337                                                                 (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) :
3338                                                                 (Z_TYPE_P(Z_REFVAL_P(obj)) != IS_STRING && Z_TYPE_P(Z_REFVAL_P(obj)) != IS_OBJECT))) {
3339                                                 if (error) zend_spprintf(error, 0, "first array member is not a valid class name or object");
3340                                         } else {
3341                                                 if (error) zend_spprintf(error, 0, "second array member is not a valid method");
3342                                         }
3343                                 } else {
3344                                         if (error) zend_spprintf(error, 0, "array must have exactly two members");
3345                                 }
3346                                 if (callable_name) {
3347                                         *callable_name = zend_string_init("Array", sizeof("Array")-1, 0);
3348                                 }
3349                         }
3350                         return 0;
3351                 case IS_OBJECT:
3352                         if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) {
3353                                 fcc->called_scope = fcc->calling_scope;
3354                                 if (callable_name) {
3355                                         zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
3356 
3357                                         *callable_name = zend_string_alloc(ZSTR_LEN(ce->name) + sizeof("::__invoke") - 1, 0);
3358                                         memcpy(ZSTR_VAL(*callable_name), ZSTR_VAL(ce->name), ZSTR_LEN(ce->name));
3359                                         memcpy(ZSTR_VAL(*callable_name) + ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke"));
3360                                 }
3361                                 return 1;
3362                         }
3363                         if (callable_name) {
3364                                 *callable_name = zval_get_string(callable);
3365                         }
3366                         if (error) zend_spprintf(error, 0, "no array or string given");
3367                         return 0;
3368                 case IS_REFERENCE:
3369                         callable = Z_REFVAL_P(callable);
3370                         goto again;
3371                 default:
3372                         if (callable_name) {
3373                                 *callable_name = zval_get_string(callable);
3374                         }
3375                         if (error) zend_spprintf(error, 0, "no array or string given");
3376                         return 0;
3377         }
3378 }
3379 /* }}} */
3380 
3381 ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, zend_string **callable_name) /* {{{ */
3382 {
3383         return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL);
3384 }
3385 /* }}} */
3386 
3387 ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_name) /* {{{ */
3388 {
3389         zend_fcall_info_cache fcc;
3390 
3391         if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, &fcc, NULL)) {
3392                 if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
3393                         zval_dtor(callable);
3394                         array_init(callable);
3395                         add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
3396                         add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
3397                 }
3398                 if (fcc.function_handler &&
3399                         ((fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
3400                      fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3401                      fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3402                         if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3403                                 zend_string_release(fcc.function_handler->common.function_name);
3404                         }
3405                         zend_free_trampoline(fcc.function_handler);
3406                 }
3407                 return 1;
3408         }
3409         return 0;
3410 }
3411 /* }}} */
3412 
3413 ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error) /* {{{ */
3414 {
3415         if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error)) {
3416                 return FAILURE;
3417         }
3418 
3419         fci->size = sizeof(*fci);
3420         fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table);
3421         fci->object = fcc->object;
3422         ZVAL_COPY_VALUE(&fci->function_name, callable);
3423         fci->retval = NULL;
3424         fci->param_count = 0;
3425         fci->params = NULL;
3426         fci->no_separation = 1;
3427         fci->symbol_table = NULL;
3428 
3429         return SUCCESS;
3430 }
3431 /* }}} */
3432 
3433 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
3434 {
3435         if (fci->params) {
3436                 zval *p = fci->params;
3437                 zval *end = p + fci->param_count;
3438 
3439                 while (p != end) {
3440                         i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
3441                         p++;
3442                 }
3443                 if (free_mem) {
3444                         efree(fci->params);
3445                         fci->params = NULL;
3446                 }
3447         }
3448         fci->param_count = 0;
3449 }
3450 /* }}} */
3451 
3452 ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval **params) /* {{{ */
3453 {
3454         *param_count = fci->param_count;
3455         *params = fci->params;
3456         fci->param_count = 0;
3457         fci->params = NULL;
3458 }
3459 /* }}} */
3460 
3461 ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval *params) /* {{{ */
3462 {
3463         zend_fcall_info_args_clear(fci, 1);
3464         fci->param_count = param_count;
3465         fci->params = params;
3466 }
3467 /* }}} */
3468 
3469 ZEND_API int zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args) /* {{{ */
3470 {
3471         zval *arg, *params;
3472         uint32_t n = 1;
3473 
3474         zend_fcall_info_args_clear(fci, !args);
3475 
3476         if (!args) {
3477                 return SUCCESS;
3478         }
3479 
3480         if (Z_TYPE_P(args) != IS_ARRAY) {
3481                 return FAILURE;
3482         }
3483 
3484         fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
3485         fci->params = params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3486 
3487         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
3488                 if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
3489                         ZVAL_NEW_REF(params, arg);
3490                         if (Z_REFCOUNTED_P(arg)) {
3491                                 Z_ADDREF_P(arg);
3492                         }
3493                 } else {
3494                         ZVAL_COPY(params, arg);
3495                 }
3496                 params++;
3497                 n++;
3498         } ZEND_HASH_FOREACH_END();
3499 
3500         return SUCCESS;
3501 }
3502 /* }}} */
3503 
3504 ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args) /* {{{ */
3505 {
3506         return zend_fcall_info_args_ex(fci, NULL, args);
3507 }
3508 /* }}} */
3509 
3510 ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci, int argc, zval *argv) /* {{{ */
3511 {
3512         int i;
3513 
3514         if (argc < 0) {
3515                 return FAILURE;
3516         }
3517 
3518         zend_fcall_info_args_clear(fci, !argc);
3519 
3520         if (argc) {
3521                 fci->param_count = argc;
3522                 fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3523 
3524                 for (i = 0; i < argc; ++i) {
3525                         ZVAL_COPY(&fci->params[i], &argv[i]);
3526                 }
3527         }
3528 
3529         return SUCCESS;
3530 }
3531 /* }}} */
3532 
3533 ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci, int argc, va_list *argv) /* {{{ */
3534 {
3535         int i;
3536         zval *arg;
3537 
3538         if (argc < 0) {
3539                 return FAILURE;
3540         }
3541 
3542         zend_fcall_info_args_clear(fci, !argc);
3543 
3544         if (argc) {
3545                 fci->param_count = argc;
3546                 fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3547 
3548                 for (i = 0; i < argc; ++i) {
3549                         arg = va_arg(*argv, zval *);
3550                         ZVAL_COPY(&fci->params[i], arg);
3551                 }
3552         }
3553 
3554         return SUCCESS;
3555 }
3556 /* }}} */
3557 
3558 ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci, int argc, ...) /* {{{ */
3559 {
3560         int ret;
3561         va_list argv;
3562 
3563         va_start(argv, argc);
3564         ret = zend_fcall_info_argv(fci, argc, &argv);
3565         va_end(argv);
3566 
3567         return ret;
3568 }
3569 /* }}} */
3570 
3571 ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval_ptr, zval *args) /* {{{ */
3572 {
3573         zval retval, *org_params = NULL;
3574         int result, org_count = 0;
3575 
3576         fci->retval = retval_ptr ? retval_ptr : &retval;
3577         if (args) {
3578                 zend_fcall_info_args_save(fci, &org_count, &org_params);
3579                 zend_fcall_info_args(fci, args);
3580         }
3581         result = zend_call_function(fci, fcc);
3582 
3583         if (!retval_ptr && Z_TYPE(retval) != IS_UNDEF) {
3584                 zval_ptr_dtor(&retval);
3585         }
3586         if (args) {
3587                 zend_fcall_info_args_restore(fci, org_count, org_params);
3588         }
3589         return result;
3590 }
3591 /* }}} */
3592 
3593 ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
3594 {
3595         zend_string *lname;
3596         size_t name_len = strlen(module_name);
3597         zend_module_entry *module;
3598 
3599         lname = zend_string_alloc(name_len, 0);
3600         zend_str_tolower_copy(ZSTR_VAL(lname), module_name, name_len);
3601         module = zend_hash_find_ptr(&module_registry, lname);
3602         zend_string_free(lname);
3603         return module ? module->version : NULL;
3604 }
3605 /* }}} */
3606 
3607 ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
3608 {
3609         zend_property_info *property_info, *property_info_ptr;
3610 
3611         if (ce->type == ZEND_INTERNAL_CLASS) {
3612                 property_info = pemalloc(sizeof(zend_property_info), 1);
3613                 if ((access_type & ZEND_ACC_STATIC) || Z_CONSTANT_P(property)) {
3614                         ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
3615                 }
3616         } else {
3617                 property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
3618                 if (Z_CONSTANT_P(property)) {
3619                         ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
3620                 }
3621         }
3622 
3623         if (!(access_type & ZEND_ACC_PPP_MASK)) {
3624                 access_type |= ZEND_ACC_PUBLIC;
3625         }
3626         if (access_type & ZEND_ACC_STATIC) {
3627                 if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
3628                     (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
3629                         property_info->offset = property_info_ptr->offset;
3630                         zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]);
3631                         zend_hash_del(&ce->properties_info, name);
3632                 } else {
3633                         property_info->offset = ce->default_static_members_count++;
3634                         ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
3635                 }
3636                 ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
3637                 if (ce->type == ZEND_USER_CLASS) {
3638                         ce->static_members_table = ce->default_static_members_table;
3639                 }
3640         } else {
3641                 if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
3642                     (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
3643                         property_info->offset = property_info_ptr->offset;
3644                         zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
3645                         zend_hash_del(&ce->properties_info, name);
3646                 } else {
3647                         property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
3648                         ce->default_properties_count++;
3649                         ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
3650                 }
3651                 ZVAL_COPY_VALUE(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)], property);
3652         }
3653         if (ce->type & ZEND_INTERNAL_CLASS) {
3654                 switch(Z_TYPE_P(property)) {
3655                         case IS_ARRAY:
3656                         case IS_OBJECT:
3657                         case IS_RESOURCE:
3658                                 zend_error_noreturn(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
3659                                 break;
3660                         default:
3661                                 break;
3662                 }
3663         }
3664         if (access_type & ZEND_ACC_PUBLIC) {
3665                 property_info->name = zend_string_copy(name);
3666         } else if (access_type & ZEND_ACC_PRIVATE) {
3667                 property_info->name = zend_mangle_property_name(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(name), ZSTR_LEN(name), ce->type & ZEND_INTERNAL_CLASS);
3668         } else {
3669                 ZEND_ASSERT(access_type & ZEND_ACC_PROTECTED);
3670                 property_info->name = zend_mangle_property_name("*", 1, ZSTR_VAL(name), ZSTR_LEN(name), ce->type & ZEND_INTERNAL_CLASS);
3671         }
3672 
3673         property_info->name = zend_new_interned_string(property_info->name);
3674         property_info->flags = access_type;
3675         property_info->doc_comment = doc_comment;
3676         property_info->ce = ce;
3677         zend_hash_update_ptr(&ce->properties_info, name, property_info);
3678 
3679         return SUCCESS;
3680 }
3681 /* }}} */
3682 
3683 ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type) /* {{{ */
3684 {
3685         zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3686         int ret = zend_declare_property_ex(ce, key, property, access_type, NULL);
3687         zend_string_release(key);
3688         return ret;
3689 }
3690 /* }}} */
3691 
3692 ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type) /* {{{ */
3693 {
3694         zval property;
3695 
3696         ZVAL_NULL(&property);
3697         return zend_declare_property(ce, name, name_length, &property, access_type);
3698 }
3699 /* }}} */
3700 
3701 ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
3702 {
3703         zval property;
3704 
3705         ZVAL_BOOL(&property, value);
3706         return zend_declare_property(ce, name, name_length, &property, access_type);
3707 }
3708 /* }}} */
3709 
3710 ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
3711 {
3712         zval property;
3713 
3714         ZVAL_LONG(&property, value);
3715         return zend_declare_property(ce, name, name_length, &property, access_type);
3716 }
3717 /* }}} */
3718 
3719 ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type) /* {{{ */
3720 {
3721         zval property;
3722 
3723         ZVAL_DOUBLE(&property, value);
3724         return zend_declare_property(ce, name, name_length, &property, access_type);
3725 }
3726 /* }}} */
3727 
3728 ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type) /* {{{ */
3729 {
3730         zval property;
3731 
3732         ZVAL_NEW_STR(&property, zend_string_init(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
3733         return zend_declare_property(ce, name, name_length, &property, access_type);
3734 }
3735 /* }}} */
3736 
3737 ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type) /* {{{ */
3738 {
3739         zval property;
3740 
3741         ZVAL_NEW_STR(&property, zend_string_init(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
3742         return zend_declare_property(ce, name, name_length, &property, access_type);
3743 }
3744 /* }}} */
3745 
3746 ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
3747 {
3748         if (Z_CONSTANT_P(value)) {
3749                 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
3750         }
3751         return zend_hash_str_update(&ce->constants_table, name, name_length, value) ?
3752                 SUCCESS : FAILURE;
3753 }
3754 /* }}} */
3755 
3756 ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length) /* {{{ */
3757 {
3758         zval constant;
3759 
3760         ZVAL_NULL(&constant);
3761         return zend_declare_class_constant(ce, name, name_length, &constant);
3762 }
3763 /* }}} */
3764 
3765 ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value) /* {{{ */
3766 {
3767         zval constant;
3768 
3769         ZVAL_LONG(&constant, value);
3770         return zend_declare_class_constant(ce, name, name_length, &constant);
3771 }
3772 /* }}} */
3773 
3774 ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value) /* {{{ */
3775 {
3776         zval constant;
3777 
3778         ZVAL_BOOL(&constant, value);
3779         return zend_declare_class_constant(ce, name, name_length, &constant);
3780 }
3781 /* }}} */
3782 
3783 ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value) /* {{{ */
3784 {
3785         zval constant;
3786 
3787         ZVAL_DOUBLE(&constant, value);
3788         return zend_declare_class_constant(ce, name, name_length, &constant);
3789 }
3790 /* }}} */
3791 
3792 ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length) /* {{{ */
3793 {
3794         zval constant;
3795 
3796         ZVAL_NEW_STR(&constant, zend_string_init(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
3797         return zend_declare_class_constant(ce, name, name_length, &constant);
3798 }
3799 /* }}} */
3800 
3801 ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value) /* {{{ */
3802 {
3803         return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value));
3804 }
3805 /* }}} */
3806 
3807 ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value) /* {{{ */
3808 {
3809         zval property;
3810         zend_class_entry *old_scope = EG(scope);
3811 
3812         EG(scope) = scope;
3813 
3814         if (!Z_OBJ_HT_P(object)->write_property) {
3815                 zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
3816         }
3817         ZVAL_STR(&property, name);
3818         Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
3819 
3820         EG(scope) = old_scope;
3821 }
3822 /* }}} */
3823 
3824 ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value) /* {{{ */
3825 {
3826         zval property;
3827         zend_class_entry *old_scope = EG(scope);
3828 
3829         EG(scope) = scope;
3830 
3831         if (!Z_OBJ_HT_P(object)->write_property) {
3832                 zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
3833         }
3834         ZVAL_STRINGL(&property, name, name_length);
3835         Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
3836         zval_ptr_dtor(&property);
3837 
3838         EG(scope) = old_scope;
3839 }
3840 /* }}} */
3841 
3842 ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length) /* {{{ */
3843 {
3844         zval tmp;
3845 
3846         ZVAL_NULL(&tmp);
3847         zend_update_property(scope, object, name, name_length, &tmp);
3848 }
3849 /* }}} */
3850 
3851 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value) /* {{{ */
3852 {
3853         zval tmp;
3854 
3855         ZVAL_BOOL(&tmp, value);
3856         zend_update_property(scope, object, name, name_length, &tmp);
3857 }
3858 /* }}} */
3859 
3860 ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value) /* {{{ */
3861 {
3862         zval tmp;
3863 
3864         ZVAL_LONG(&tmp, value);
3865         zend_update_property(scope, object, name, name_length, &tmp);
3866 }
3867 /* }}} */
3868 
3869 ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, size_t name_length, double value) /* {{{ */
3870 {
3871         zval tmp;
3872 
3873         ZVAL_DOUBLE(&tmp, value);
3874         zend_update_property(scope, object, name, name_length, &tmp);
3875 }
3876 /* }}} */
3877 
3878 ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_string *value) /* {{{ */
3879 {
3880         zval tmp;
3881 
3882         ZVAL_STR(&tmp, value);
3883         zend_update_property(scope, object, name, name_length, &tmp);
3884 }
3885 /* }}} */
3886 
3887 ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value) /* {{{ */
3888 {
3889         zval tmp;
3890 
3891         ZVAL_STRING(&tmp, value);
3892         Z_SET_REFCOUNT(tmp, 0);
3893         zend_update_property(scope, object, name, name_length, &tmp);
3894 }
3895 /* }}} */
3896 
3897 ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
3898 {
3899         zval tmp;
3900 
3901         ZVAL_STRINGL(&tmp, value, value_len);
3902         Z_SET_REFCOUNT(tmp, 0);
3903         zend_update_property(scope, object, name, name_length, &tmp);
3904 }
3905 /* }}} */
3906 
3907 ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */
3908 {
3909         zval *property;
3910         zend_class_entry *old_scope = EG(scope);
3911         zend_string *key = zend_string_init(name, name_length, 0);
3912 
3913         EG(scope) = scope;
3914         property = zend_std_get_static_property(scope, key, 0);
3915         EG(scope) = old_scope;
3916         zend_string_free(key);
3917         if (!property) {
3918                 return FAILURE;
3919         } else {
3920                 if (property != value) {
3921                         if (Z_ISREF_P(property)) {
3922                                 zval_dtor(property);
3923                                 ZVAL_COPY_VALUE(property, value);
3924                                 if (Z_REFCOUNTED_P(value) && Z_REFCOUNT_P(value) > 0) {
3925                                         zval_opt_copy_ctor(property);
3926                                 }
3927                         } else {
3928                                 zval garbage;
3929 
3930                                 ZVAL_COPY_VALUE(&garbage, property);
3931                                 if (Z_REFCOUNTED_P(value)) {
3932                                         Z_ADDREF_P(value);
3933                                         if (Z_ISREF_P(value)) {
3934                                                 SEPARATE_ZVAL(value);
3935                                         }
3936                                 }
3937                                 ZVAL_COPY_VALUE(property, value);
3938                                 zval_ptr_dtor(&garbage);
3939                         }
3940                 }
3941                 return SUCCESS;
3942         }
3943 }
3944 /* }}} */
3945 
3946 ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length) /* {{{ */
3947 {
3948         zval tmp;
3949 
3950         ZVAL_NULL(&tmp);
3951         return zend_update_static_property(scope, name, name_length, &tmp);
3952 }
3953 /* }}} */
3954 
3955 ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
3956 {
3957         zval tmp;
3958 
3959         ZVAL_BOOL(&tmp, value);
3960         return zend_update_static_property(scope, name, name_length, &tmp);
3961 }
3962 /* }}} */
3963 
3964 ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
3965 {
3966         zval tmp;
3967 
3968         ZVAL_LONG(&tmp, value);
3969         return zend_update_static_property(scope, name, name_length, &tmp);
3970 }
3971 /* }}} */
3972 
3973 ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value) /* {{{ */
3974 {
3975         zval tmp;
3976 
3977         ZVAL_DOUBLE(&tmp, value);
3978         return zend_update_static_property(scope, name, name_length, &tmp);
3979 }
3980 /* }}} */
3981 
3982 ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value) /* {{{ */
3983 {
3984         zval tmp;
3985 
3986         ZVAL_STRING(&tmp, value);
3987         Z_SET_REFCOUNT(tmp, 0);
3988         return zend_update_static_property(scope, name, name_length, &tmp);
3989 }
3990 /* }}} */
3991 
3992 ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
3993 {
3994         zval tmp;
3995 
3996         ZVAL_STRINGL(&tmp, value, value_len);
3997         Z_SET_REFCOUNT(tmp, 0);
3998         return zend_update_static_property(scope, name, name_length, &tmp);
3999 }
4000 /* }}} */
4001 
4002 ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv) /* {{{ */
4003 {
4004         zval property, *value;
4005         zend_class_entry *old_scope = EG(scope);
4006 
4007         EG(scope) = scope;
4008 
4009         if (!Z_OBJ_HT_P(object)->read_property) {
4010                 zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be read", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
4011         }
4012 
4013         ZVAL_STRINGL(&property, name, name_length);
4014         value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
4015         zval_ptr_dtor(&property);
4016 
4017         EG(scope) = old_scope;
4018         return value;
4019 }
4020 /* }}} */
4021 
4022 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent) /* {{{ */
4023 {
4024         zval *property;
4025         zend_class_entry *old_scope = EG(scope);
4026         zend_string *key = zend_string_init(name, name_length, 0);
4027 
4028         EG(scope) = scope;
4029         property = zend_std_get_static_property(scope, key, silent);
4030         EG(scope) = old_scope;
4031         zend_string_free(key);
4032 
4033         return property;
4034 }
4035 /* }}} */
4036 
4037 ZEND_API void zend_save_error_handling(zend_error_handling *current) /* {{{ */
4038 {
4039         current->handling = EG(error_handling);
4040         current->exception = EG(exception_class);
4041         ZVAL_COPY(&current->user_handler, &EG(user_error_handler));
4042 }
4043 /* }}} */
4044 
4045 ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current) /* {{{ */
4046 {
4047         if (current) {
4048                 zend_save_error_handling(current);
4049                 if (error_handling != EH_NORMAL && Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
4050                         zval_ptr_dtor(&EG(user_error_handler));
4051                         ZVAL_UNDEF(&EG(user_error_handler));
4052                 }
4053         }
4054         EG(error_handling) = error_handling;
4055         EG(exception_class) = error_handling == EH_THROW ? exception_class : NULL;
4056 }
4057 /* }}} */
4058 
4059 static int same_zval(zval *zv1, zval *zv2)  /* {{{ */
4060 {
4061         if (Z_TYPE_P(zv1) != Z_TYPE_P(zv2)) {
4062                 return 0;
4063         }
4064         switch (Z_TYPE_P(zv1)) {
4065                 case IS_UNDEF:
4066                 case IS_NULL:
4067                 case IS_FALSE:
4068                 case IS_TRUE:
4069                         return 1;
4070                 case IS_LONG:
4071                         return Z_LVAL_P(zv1) == Z_LVAL_P(zv2);
4072                 case IS_DOUBLE:
4073                         return Z_LVAL_P(zv1) == Z_LVAL_P(zv2);
4074                 case IS_STRING:
4075                 case IS_ARRAY:
4076                 case IS_OBJECT:
4077                 case IS_RESOURCE:
4078                         return Z_COUNTED_P(zv1) == Z_COUNTED_P(zv2);
4079                 default:
4080                         return 0;
4081         }
4082 }
4083 /* }}} */
4084 
4085 ZEND_API void zend_restore_error_handling(zend_error_handling *saved) /* {{{ */
4086 {
4087         EG(error_handling) = saved->handling;
4088         EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL;
4089         if (Z_TYPE(saved->user_handler) != IS_UNDEF
4090                 && !same_zval(&saved->user_handler, &EG(user_error_handler))) {
4091                 zval_ptr_dtor(&EG(user_error_handler));
4092                 ZVAL_COPY_VALUE(&EG(user_error_handler), &saved->user_handler);
4093         } else if (Z_TYPE(saved->user_handler)) {
4094                 zval_ptr_dtor(&saved->user_handler);
4095         }
4096         ZVAL_UNDEF(&saved->user_handler);
4097 }
4098 /* }}} */
4099 
4100 ZEND_API zend_string* zend_find_alias_name(zend_class_entry *ce, zend_string *name) /* {{{ */
4101 {
4102         zend_trait_alias *alias, **alias_ptr;
4103 
4104         if ((alias_ptr = ce->trait_aliases)) {
4105                 alias = *alias_ptr;
4106                 while (alias) {
4107                         if (alias->alias && zend_string_equals_ci(alias->alias, name)) {
4108                                 return alias->alias;
4109                         }
4110                         alias_ptr++;
4111                         alias = *alias_ptr;
4112                 }
4113         }
4114 
4115         return name;
4116 }
4117 /* }}} */
4118 
4119 ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_function *f) /* {{{ */
4120 {
4121         zend_function *func;
4122         HashTable *function_table;
4123         zend_string *name;
4124 
4125         if (f->common.type != ZEND_USER_FUNCTION ||
4126             (f->op_array.refcount && *(f->op_array.refcount) < 2) ||
4127             !f->common.scope ||
4128             !f->common.scope->trait_aliases) {
4129                 return f->common.function_name;
4130         }
4131 
4132         function_table = &ce->function_table;
4133         ZEND_HASH_FOREACH_STR_KEY_PTR(function_table, name, func) {
4134                 if (func == f) {
4135                         if (!name) {
4136                                 return f->common.function_name;
4137                         }
4138                         if (ZSTR_LEN(name) == ZSTR_LEN(f->common.function_name) &&
4139                             !strncasecmp(ZSTR_VAL(name), ZSTR_VAL(f->common.function_name), ZSTR_LEN(f->common.function_name))) {
4140                                 return f->common.function_name;
4141                         }
4142                         return zend_find_alias_name(f->common.scope, name);
4143                 }
4144         } ZEND_HASH_FOREACH_END();
4145         return f->common.function_name;
4146 }
4147 /* }}} */
4148 
4149 ZEND_API const char *zend_get_object_type(const zend_class_entry *ce) /* {{{ */
4150 {
4151         if(ce->ce_flags & ZEND_ACC_TRAIT) {
4152                 return "trait";
4153         } else if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4154                 return "interface";
4155         } else {
4156                 return "class";
4157         }
4158 }
4159 /* }}} */
4160 
4161 /*
4162  * Local variables:
4163  * tab-width: 4
4164  * c-basic-offset: 4
4165  * indent-tabs-mode: t
4166  * End:
4167  */

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