xref: /PHP-7.4/ext/reflection/php_reflection.c (revision 988c3f96)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) The PHP Group                                          |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Timm Friebe <thekid@thekid.de>                              |
16    |          George Schlossnagle <george@omniti.com>                     |
17    |          Andrei Zmievski <andrei@gravitonic.com>                     |
18    |          Marcus Boerger <helly@php.net>                              |
19    |          Johannes Schlueter <johannes@php.net>                       |
20    +----------------------------------------------------------------------+
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include "php.h"
28 #include "php_ini.h"
29 #include "php_reflection.h"
30 #include "ext/standard/info.h"
31 #include "ext/standard/sha1.h"
32 #include "ext/standard/php_random.h"
33 
34 #include "zend.h"
35 #include "zend_API.h"
36 #include "zend_exceptions.h"
37 #include "zend_operators.h"
38 #include "zend_constants.h"
39 #include "zend_ini.h"
40 #include "zend_interfaces.h"
41 #include "zend_closures.h"
42 #include "zend_generators.h"
43 #include "zend_extensions.h"
44 #include "zend_builtin_functions.h"
45 #include "zend_smart_str.h"
46 
47 /* Key used to avoid leaking addresses in ReflectionProperty::getId() */
48 #define REFLECTION_KEY_LEN 16
49 ZEND_BEGIN_MODULE_GLOBALS(reflection)
50 	zend_bool key_initialized;
51 	unsigned char key[REFLECTION_KEY_LEN];
52 ZEND_END_MODULE_GLOBALS(reflection)
ZEND_DECLARE_MODULE_GLOBALS(reflection)53 ZEND_DECLARE_MODULE_GLOBALS(reflection)
54 
55 #define REFLECTION_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(reflection, v)
56 
57 static zend_always_inline zval *reflection_prop_name(zval *object) {
58 	/* $name is always in the first property slot. */
59 	ZEND_ASSERT(Z_OBJCE_P(object)->default_properties_count >= 1);
60 	return &Z_OBJ_P(object)->properties_table[0];
61 }
62 
reflection_prop_class(zval * object)63 static zend_always_inline zval *reflection_prop_class(zval *object) {
64 	/* $class is always in the second property slot. */
65 	ZEND_ASSERT(Z_OBJCE_P(object)->default_properties_count >= 2);
66 	return &Z_OBJ_P(object)->properties_table[1];
67 }
68 
69 /* Class entry pointers */
70 PHPAPI zend_class_entry *reflector_ptr;
71 PHPAPI zend_class_entry *reflection_exception_ptr;
72 PHPAPI zend_class_entry *reflection_ptr;
73 PHPAPI zend_class_entry *reflection_function_abstract_ptr;
74 PHPAPI zend_class_entry *reflection_function_ptr;
75 PHPAPI zend_class_entry *reflection_generator_ptr;
76 PHPAPI zend_class_entry *reflection_parameter_ptr;
77 PHPAPI zend_class_entry *reflection_type_ptr;
78 PHPAPI zend_class_entry *reflection_named_type_ptr;
79 PHPAPI zend_class_entry *reflection_class_ptr;
80 PHPAPI zend_class_entry *reflection_object_ptr;
81 PHPAPI zend_class_entry *reflection_method_ptr;
82 PHPAPI zend_class_entry *reflection_property_ptr;
83 PHPAPI zend_class_entry *reflection_class_constant_ptr;
84 PHPAPI zend_class_entry *reflection_extension_ptr;
85 PHPAPI zend_class_entry *reflection_zend_extension_ptr;
86 PHPAPI zend_class_entry *reflection_reference_ptr;
87 
88 /* Exception throwing macro */
89 #define _DO_THROW(msg) \
90 	zend_throw_exception(reflection_exception_ptr, msg, 0);
91 
92 #define GET_REFLECTION_OBJECT() do { \
93 	intern = Z_REFLECTION_P(ZEND_THIS); \
94 	if (intern->ptr == NULL) { \
95 		if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) { \
96 			return; \
97 		} \
98 		zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object"); \
99 		return; \
100 	} \
101 } while (0)
102 
103 #define GET_REFLECTION_OBJECT_PTR(target) do { \
104 	GET_REFLECTION_OBJECT(); \
105 	target = intern->ptr; \
106 } while (0)
107 
108 /* Class constants */
109 #define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value) \
110 	zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (zend_long)value);
111 
112 /* {{{ Object structure */
113 
114 /* Struct for properties */
115 typedef struct _property_reference {
116 	zend_property_info prop;
117 	zend_string *unmangled_name;
118 	zend_bool dynamic;
119 } property_reference;
120 
121 /* Struct for parameters */
122 typedef struct _parameter_reference {
123 	uint32_t offset;
124 	zend_bool required;
125 	struct _zend_arg_info *arg_info;
126 	zend_function *fptr;
127 } parameter_reference;
128 
129 /* Struct for type hints */
130 typedef struct _type_reference {
131 	zend_type type;
132 } type_reference;
133 
134 typedef enum {
135 	REF_TYPE_OTHER,      /* Must be 0 */
136 	REF_TYPE_FUNCTION,
137 	REF_TYPE_GENERATOR,
138 	REF_TYPE_PARAMETER,
139 	REF_TYPE_TYPE,
140 	REF_TYPE_PROPERTY,
141 	REF_TYPE_CLASS_CONSTANT
142 } reflection_type_t;
143 
144 /* Struct for reflection objects */
145 typedef struct {
146 	zval obj;
147 	void *ptr;
148 	zend_class_entry *ce;
149 	reflection_type_t ref_type;
150 	unsigned int ignore_visibility:1;
151 	zend_object zo;
152 } reflection_object;
153 
reflection_object_from_obj(zend_object * obj)154 static inline reflection_object *reflection_object_from_obj(zend_object *obj) {
155 	return (reflection_object*)((char*)(obj) - XtOffsetOf(reflection_object, zo));
156 }
157 
158 #define Z_REFLECTION_P(zv)  reflection_object_from_obj(Z_OBJ_P((zv)))
159 /* }}} */
160 
161 static zend_object_handlers reflection_object_handlers;
162 
is_closure_invoke(zend_class_entry * ce,zend_string * lcname)163 static inline zend_bool is_closure_invoke(zend_class_entry *ce, zend_string *lcname) {
164 	return ce == zend_ce_closure
165 		&& zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME);
166 }
167 
_default_load_name(zval * object)168 static zval *_default_load_name(zval *object) /* {{{ */
169 {
170 	return zend_hash_find_ex_ind(Z_OBJPROP_P(object), ZSTR_KNOWN(ZEND_STR_NAME), 1);
171 }
172 /* }}} */
173 
_default_get_name(zval * object,zval * return_value)174 static void _default_get_name(zval *object, zval *return_value) /* {{{ */
175 {
176 	zval *value;
177 
178 	if ((value = _default_load_name(object)) == NULL) {
179 		RETURN_FALSE;
180 	}
181 	ZVAL_COPY(return_value, value);
182 }
183 /* }}} */
184 
_copy_function(zend_function * fptr)185 static zend_function *_copy_function(zend_function *fptr) /* {{{ */
186 {
187 	if (fptr
188 		&& (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
189 	{
190 		zend_function *copy_fptr;
191 		copy_fptr = emalloc(sizeof(zend_function));
192 		memcpy(copy_fptr, fptr, sizeof(zend_function));
193 		copy_fptr->internal_function.function_name = zend_string_copy(fptr->internal_function.function_name);
194 		return copy_fptr;
195 	} else {
196 		/* no copy needed */
197 		return fptr;
198 	}
199 }
200 /* }}} */
201 
_free_function(zend_function * fptr)202 static void _free_function(zend_function *fptr) /* {{{ */
203 {
204 	if (fptr
205 		&& (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
206 	{
207 		zend_string_release_ex(fptr->internal_function.function_name, 0);
208 		zend_free_trampoline(fptr);
209 	}
210 }
211 /* }}} */
212 
reflection_free_objects_storage(zend_object * object)213 static void reflection_free_objects_storage(zend_object *object) /* {{{ */
214 {
215 	reflection_object *intern = reflection_object_from_obj(object);
216 	parameter_reference *reference;
217 	property_reference *prop_reference;
218 
219 	if (intern->ptr) {
220 		switch (intern->ref_type) {
221 		case REF_TYPE_PARAMETER:
222 			reference = (parameter_reference*)intern->ptr;
223 			_free_function(reference->fptr);
224 			efree(intern->ptr);
225 			break;
226 		case REF_TYPE_TYPE:
227 		{
228 			type_reference *type_ref = intern->ptr;
229 			if (ZEND_TYPE_IS_NAME(type_ref->type)) {
230 				zend_string_release(ZEND_TYPE_NAME(type_ref->type));
231 			}
232 			efree(type_ref);
233 			break;
234 		}
235 		case REF_TYPE_FUNCTION:
236 			_free_function(intern->ptr);
237 			break;
238 		case REF_TYPE_PROPERTY:
239 			prop_reference = (property_reference*)intern->ptr;
240 			zend_string_release_ex(prop_reference->unmangled_name, 0);
241 
242 			if (ZEND_TYPE_IS_NAME(prop_reference->prop.type)) {
243 				zend_string_release(ZEND_TYPE_NAME(prop_reference->prop.type));
244 			}
245 
246 			efree(intern->ptr);
247 			break;
248 		case REF_TYPE_GENERATOR:
249 		case REF_TYPE_CLASS_CONSTANT:
250 		case REF_TYPE_OTHER:
251 			break;
252 		}
253 	}
254 	intern->ptr = NULL;
255 	zval_ptr_dtor(&intern->obj);
256 	zend_object_std_dtor(object);
257 }
258 /* }}} */
259 
reflection_get_gc(zval * obj,zval ** gc_data,int * gc_data_count)260 static HashTable *reflection_get_gc(zval *obj, zval **gc_data, int *gc_data_count) /* {{{ */
261 {
262 	reflection_object *intern = Z_REFLECTION_P(obj);
263 	*gc_data = &intern->obj;
264 	*gc_data_count = 1;
265 	return zend_std_get_properties(obj);
266 }
267 /* }}} */
268 
reflection_objects_new(zend_class_entry * class_type)269 static zend_object *reflection_objects_new(zend_class_entry *class_type) /* {{{ */
270 {
271 	reflection_object *intern = zend_object_alloc(sizeof(reflection_object), class_type);
272 
273 	zend_object_std_init(&intern->zo, class_type);
274 	object_properties_init(&intern->zo, class_type);
275 	intern->zo.handlers = &reflection_object_handlers;
276 	return &intern->zo;
277 }
278 /* }}} */
279 
reflection_instantiate(zend_class_entry * pce,zval * object)280 static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{ */
281 {
282 	object_init_ex(object, pce);
283 	return object;
284 }
285 /* }}} */
286 
287 static void _const_string(smart_str *str, char *name, zval *value, char *indent);
288 static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent);
289 static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent, zend_bool dynamic);
290 static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char* indent);
291 static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent);
292 static void _extension_string(smart_str *str, zend_module_entry *module, char *indent);
293 static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent);
294 
295 /* {{{ _class_string */
_class_string(smart_str * str,zend_class_entry * ce,zval * obj,char * indent)296 static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent)
297 {
298 	int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
299 	zend_string *sub_indent = strpprintf(0, "%s    ", indent);
300 
301 	/* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
302 	if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
303 		smart_str_append_printf(str, "%s%s", indent, ZSTR_VAL(ce->info.user.doc_comment));
304 		smart_str_appendc(str, '\n');
305 	}
306 
307 	if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
308 		smart_str_append_printf(str, "%sObject of class [ ", indent);
309 	} else {
310 		char *kind = "Class";
311 		if (ce->ce_flags & ZEND_ACC_INTERFACE) {
312 			kind = "Interface";
313 		} else if (ce->ce_flags & ZEND_ACC_TRAIT) {
314 			kind = "Trait";
315 		}
316 		smart_str_append_printf(str, "%s%s [ ", indent, kind);
317 	}
318 	smart_str_append_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
319 	if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
320 		smart_str_append_printf(str, ":%s", ce->info.internal.module->name);
321 	}
322 	smart_str_append_printf(str, "> ");
323 	if (ce->get_iterator != NULL) {
324 		smart_str_append_printf(str, "<iterateable> ");
325 	}
326 	if (ce->ce_flags & ZEND_ACC_INTERFACE) {
327 		smart_str_append_printf(str, "interface ");
328 	} else if (ce->ce_flags & ZEND_ACC_TRAIT) {
329 		smart_str_append_printf(str, "trait ");
330 	} else {
331 		if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
332 			smart_str_append_printf(str, "abstract ");
333 		}
334 		if (ce->ce_flags & ZEND_ACC_FINAL) {
335 			smart_str_append_printf(str, "final ");
336 		}
337 		smart_str_append_printf(str, "class ");
338 	}
339 	smart_str_append_printf(str, "%s", ZSTR_VAL(ce->name));
340 	if (ce->parent) {
341 		smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name));
342 	}
343 
344 	if (ce->num_interfaces) {
345 		uint32_t i;
346 
347 		ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
348 		if (ce->ce_flags & ZEND_ACC_INTERFACE) {
349 			smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->interfaces[0]->name));
350 		} else {
351 			smart_str_append_printf(str, " implements %s", ZSTR_VAL(ce->interfaces[0]->name));
352 		}
353 		for (i = 1; i < ce->num_interfaces; ++i) {
354 			smart_str_append_printf(str, ", %s", ZSTR_VAL(ce->interfaces[i]->name));
355 		}
356 	}
357 	smart_str_append_printf(str, " ] {\n");
358 
359 	/* The information where a class is declared is only available for user classes */
360 	if (ce->type == ZEND_USER_CLASS) {
361 		smart_str_append_printf(str, "%s  @@ %s %d-%d\n", indent, ZSTR_VAL(ce->info.user.filename),
362 						ce->info.user.line_start, ce->info.user.line_end);
363 	}
364 
365 	/* Constants */
366 	smart_str_append_printf(str, "\n");
367 	count = zend_hash_num_elements(&ce->constants_table);
368 	smart_str_append_printf(str, "%s  - Constants [%d] {\n", indent, count);
369 	if (count > 0) {
370 		zend_string *key;
371 		zend_class_constant *c;
372 
373 		ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
374 			_class_const_string(str, ZSTR_VAL(key), c, ZSTR_VAL(sub_indent));
375 			if (UNEXPECTED(EG(exception))) {
376 				zend_string_release(sub_indent);
377 				return;
378 			}
379 		} ZEND_HASH_FOREACH_END();
380 	}
381 	smart_str_append_printf(str, "%s  }\n", indent);
382 
383 	/* Static properties */
384 	/* counting static properties */
385 	count = zend_hash_num_elements(&ce->properties_info);
386 	if (count > 0) {
387 		zend_property_info *prop;
388 
389 		ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
390 			if ((prop->flags & ZEND_ACC_PRIVATE) && prop->ce != ce) {
391 				count_shadow_props++;
392 			} else if (prop->flags & ZEND_ACC_STATIC) {
393 				count_static_props++;
394 			}
395 		} ZEND_HASH_FOREACH_END();
396 	}
397 
398 	/* static properties */
399 	smart_str_append_printf(str, "\n%s  - Static properties [%d] {\n", indent, count_static_props);
400 	if (count_static_props > 0) {
401 		zend_property_info *prop;
402 
403 		ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
404 			if ((prop->flags & ZEND_ACC_STATIC) && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
405 				_property_string(str, prop, NULL, ZSTR_VAL(sub_indent), 0);
406 			}
407 		} ZEND_HASH_FOREACH_END();
408 	}
409 	smart_str_append_printf(str, "%s  }\n", indent);
410 
411 	/* Static methods */
412 	/* counting static methods */
413 	count = zend_hash_num_elements(&ce->function_table);
414 	if (count > 0) {
415 		zend_function *mptr;
416 
417 		ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
418 			if (mptr->common.fn_flags & ZEND_ACC_STATIC
419 				&& ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
420 			{
421 				count_static_funcs++;
422 			}
423 		} ZEND_HASH_FOREACH_END();
424 	}
425 
426 	/* static methods */
427 	smart_str_append_printf(str, "\n%s  - Static methods [%d] {", indent, count_static_funcs);
428 	if (count_static_funcs > 0) {
429 		zend_function *mptr;
430 
431 		ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
432 			if (mptr->common.fn_flags & ZEND_ACC_STATIC
433 				&& ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
434 			{
435 				smart_str_append_printf(str, "\n");
436 				_function_string(str, mptr, ce, ZSTR_VAL(sub_indent));
437 			}
438 		} ZEND_HASH_FOREACH_END();
439 	} else {
440 		smart_str_append_printf(str, "\n");
441 	}
442 	smart_str_append_printf(str, "%s  }\n", indent);
443 
444 	/* Default/Implicit properties */
445 	count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
446 	smart_str_append_printf(str, "\n%s  - Properties [%d] {\n", indent, count);
447 	if (count > 0) {
448 		zend_property_info *prop;
449 
450 		ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
451 			if (!(prop->flags & ZEND_ACC_STATIC)
452 			 && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
453 				_property_string(str, prop, NULL, ZSTR_VAL(sub_indent), 0);
454 			}
455 		} ZEND_HASH_FOREACH_END();
456 	}
457 	smart_str_append_printf(str, "%s  }\n", indent);
458 
459 	if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
460 		HashTable    *properties = Z_OBJ_HT_P(obj)->get_properties(obj);
461 		zend_string  *prop_name;
462 		smart_str prop_str = {0};
463 
464 		count = 0;
465 		if (properties && zend_hash_num_elements(properties)) {
466 			ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) {
467 				if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */
468 					if (!zend_hash_exists(&ce->properties_info, prop_name)) {
469 						count++;
470 						_property_string(&prop_str, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent), 0);
471 					}
472 				}
473 			} ZEND_HASH_FOREACH_END();
474 		}
475 
476 		smart_str_append_printf(str, "\n%s  - Dynamic properties [%d] {\n", indent, count);
477 		smart_str_append_smart_str(str, &prop_str);
478 		smart_str_append_printf(str, "%s  }\n", indent);
479 		smart_str_free(&prop_str);
480 	}
481 
482 	/* Non static methods */
483 	count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
484 	if (count > 0) {
485 		zend_function *mptr;
486 		smart_str method_str = {0};
487 
488 		count = 0;
489 		ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
490 			if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
491 				&& ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
492 			{
493 				zend_function *closure;
494 				/* see if this is a closure */
495 				if (obj && is_closure_invoke(ce, mptr->common.function_name)
496 					&& (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
497 				{
498 					mptr = closure;
499 				} else {
500 					closure = NULL;
501 				}
502 				smart_str_appendc(&method_str, '\n');
503 				_function_string(&method_str, mptr, ce, ZSTR_VAL(sub_indent));
504 				count++;
505 				_free_function(closure);
506 			}
507 		} ZEND_HASH_FOREACH_END();
508 		smart_str_append_printf(str, "\n%s  - Methods [%d] {", indent, count);
509 		smart_str_append_smart_str(str, &method_str);
510 		if (!count) {
511 			smart_str_append_printf(str, "\n");
512 		}
513 		smart_str_free(&method_str);
514 	} else {
515 		smart_str_append_printf(str, "\n%s  - Methods [0] {\n", indent);
516 	}
517 	smart_str_append_printf(str, "%s  }\n", indent);
518 
519 	smart_str_append_printf(str, "%s}\n", indent);
520 	zend_string_release_ex(sub_indent, 0);
521 }
522 /* }}} */
523 
524 /* {{{ _const_string */
_const_string(smart_str * str,char * name,zval * value,char * indent)525 static void _const_string(smart_str *str, char *name, zval *value, char *indent)
526 {
527 	char *type = zend_zval_type_name(value);
528 
529 	if (Z_TYPE_P(value) == IS_ARRAY) {
530 		smart_str_append_printf(str, "%s    Constant [ %s %s ] { Array }\n",
531 						indent, type, name);
532 	} else if (Z_TYPE_P(value) == IS_STRING) {
533 		smart_str_append_printf(str, "%s    Constant [ %s %s ] { %s }\n",
534 						indent, type, name, Z_STRVAL_P(value));
535 	} else {
536 		zend_string *tmp_value_str;
537 		zend_string *value_str = zval_get_tmp_string(value, &tmp_value_str);
538 		smart_str_append_printf(str, "%s    Constant [ %s %s ] { %s }\n",
539 						indent, type, name, ZSTR_VAL(value_str));
540 		zend_tmp_string_release(tmp_value_str);
541 	}
542 }
543 /* }}} */
544 
545 /* {{{ _class_const_string */
_class_const_string(smart_str * str,char * name,zend_class_constant * c,char * indent)546 static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char *indent)
547 {
548 	char *visibility = zend_visibility_string(Z_ACCESS_FLAGS(c->value));
549 	char *type;
550 
551 	if (zval_update_constant_ex(&c->value, c->ce) == FAILURE) {
552 		return;
553 	}
554 
555 	type = zend_zval_type_name(&c->value);
556 
557 	if (Z_TYPE(c->value) == IS_ARRAY) {
558 		smart_str_append_printf(str, "%sConstant [ %s %s %s ] { Array }\n",
559 						indent, visibility, type, name);
560 	} else {
561 		zend_string *tmp_value_str;
562 		zend_string *value_str = zval_get_tmp_string(&c->value, &tmp_value_str);
563 
564 		smart_str_append_printf(str, "%sConstant [ %s %s %s ] { %s }\n",
565 						indent, visibility, type, name, ZSTR_VAL(value_str));
566 
567 		zend_tmp_string_release(tmp_value_str);
568 	}
569 }
570 /* }}} */
571 
572 /* {{{ _get_recv_opcode */
_get_recv_op(zend_op_array * op_array,uint32_t offset)573 static zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
574 {
575 	zend_op *op = op_array->opcodes;
576 	zend_op *end = op + op_array->last;
577 
578 	++offset;
579 	while (op < end) {
580 		if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT
581 		    || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == offset)
582 		{
583 			return op;
584 		}
585 		++op;
586 	}
587 	return NULL;
588 }
589 /* }}} */
590 
591 /* {{{ _parameter_string */
_parameter_string(smart_str * str,zend_function * fptr,struct _zend_arg_info * arg_info,uint32_t offset,zend_bool required,char * indent)592 static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, char* indent)
593 {
594 	smart_str_append_printf(str, "Parameter #%d [ ", offset);
595 	if (!required) {
596 		smart_str_append_printf(str, "<optional> ");
597 	} else {
598 		smart_str_append_printf(str, "<required> ");
599 	}
600 	if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
601 		smart_str_append_printf(str, "%s ",
602 			ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)));
603 		if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
604 			smart_str_append_printf(str, "or NULL ");
605 		}
606 	} else if (ZEND_TYPE_IS_CODE(arg_info->type)) {
607 		smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)));
608 		if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
609 			smart_str_append_printf(str, "or NULL ");
610 		}
611 	}
612 	if (arg_info->pass_by_reference) {
613 		smart_str_appendc(str, '&');
614 	}
615 	if (arg_info->is_variadic) {
616 		smart_str_appends(str, "...");
617 	}
618 	if (arg_info->name) {
619 		smart_str_append_printf(str, "$%s",
620 			(fptr->type == ZEND_INTERNAL_FUNCTION &&
621 			 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) ?
622 			((zend_internal_arg_info*)arg_info)->name :
623 			ZSTR_VAL(arg_info->name));
624 	} else {
625 		smart_str_append_printf(str, "$param%d", offset);
626 	}
627 	if (fptr->type == ZEND_USER_FUNCTION && !required) {
628 		zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
629 		if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
630 			zval zv;
631 
632 			smart_str_appends(str, " = ");
633 			ZVAL_COPY(&zv, RT_CONSTANT(precv, precv->op2));
634 			if (UNEXPECTED(zval_update_constant_ex(&zv, fptr->common.scope) == FAILURE)) {
635 				zval_ptr_dtor(&zv);
636 				return;
637 			}
638 			if (Z_TYPE(zv) == IS_TRUE) {
639 				smart_str_appends(str, "true");
640 			} else if (Z_TYPE(zv) == IS_FALSE) {
641 				smart_str_appends(str, "false");
642 			} else if (Z_TYPE(zv) == IS_NULL) {
643 				smart_str_appends(str, "NULL");
644 			} else if (Z_TYPE(zv) == IS_STRING) {
645 				smart_str_appendc(str, '\'');
646 				smart_str_appendl(str, Z_STRVAL(zv), MIN(Z_STRLEN(zv), 15));
647 				if (Z_STRLEN(zv) > 15) {
648 					smart_str_appends(str, "...");
649 				}
650 				smart_str_appendc(str, '\'');
651 			} else if (Z_TYPE(zv) == IS_ARRAY) {
652 				smart_str_appends(str, "Array");
653 			} else {
654 				zend_string *tmp_zv_str;
655 				zend_string *zv_str = zval_get_tmp_string(&zv, &tmp_zv_str);
656 				smart_str_append(str, zv_str);
657 				zend_tmp_string_release(tmp_zv_str);
658 			}
659 			zval_ptr_dtor(&zv);
660 		}
661 	}
662 	smart_str_appends(str, " ]");
663 }
664 /* }}} */
665 
666 /* {{{ _function_parameter_string */
_function_parameter_string(smart_str * str,zend_function * fptr,char * indent)667 static void _function_parameter_string(smart_str *str, zend_function *fptr, char* indent)
668 {
669 	struct _zend_arg_info *arg_info = fptr->common.arg_info;
670 	uint32_t i, num_args, num_required = fptr->common.required_num_args;
671 
672 	if (!arg_info) {
673 		return;
674 	}
675 
676 	num_args = fptr->common.num_args;
677 	if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
678 		num_args++;
679 	}
680 	smart_str_appendc(str, '\n');
681 	smart_str_append_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
682 	for (i = 0; i < num_args; i++) {
683 		smart_str_append_printf(str, "%s  ", indent);
684 		_parameter_string(str, fptr, arg_info, i, i < num_required, indent);
685 		smart_str_appendc(str, '\n');
686 		arg_info++;
687 	}
688 	smart_str_append_printf(str, "%s}\n", indent);
689 }
690 /* }}} */
691 
692 /* {{{ _function_closure_string */
_function_closure_string(smart_str * str,zend_function * fptr,char * indent)693 static void _function_closure_string(smart_str *str, zend_function *fptr, char* indent)
694 {
695 	uint32_t i, count;
696 	zend_string *key;
697 	HashTable *static_variables;
698 
699 	if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
700 		return;
701 	}
702 
703 	static_variables = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
704 	count = zend_hash_num_elements(static_variables);
705 
706 	if (!count) {
707 		return;
708 	}
709 
710 	smart_str_append_printf(str, "\n");
711 	smart_str_append_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
712 	i = 0;
713 	ZEND_HASH_FOREACH_STR_KEY(static_variables, key) {
714 		smart_str_append_printf(str, "%s    Variable #%d [ $%s ]\n", indent, i++, ZSTR_VAL(key));
715 	} ZEND_HASH_FOREACH_END();
716 	smart_str_append_printf(str, "%s}\n", indent);
717 }
718 /* }}} */
719 
720 /* {{{ _function_string */
_function_string(smart_str * str,zend_function * fptr,zend_class_entry * scope,char * indent)721 static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent)
722 {
723 	smart_str param_indent = {0};
724 	zend_function *overwrites;
725 	zend_string *lc_name;
726 
727 	/* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
728 	 * What's "wrong" is that any whitespace before the doc comment start is
729 	 * swallowed, leading to an unaligned comment.
730 	 */
731 	if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
732 		smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(fptr->op_array.doc_comment));
733 	}
734 
735 	smart_str_appendl(str, indent, strlen(indent));
736 	smart_str_append_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
737 	smart_str_append_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
738 	if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
739 		smart_str_appends(str, ", deprecated");
740 	}
741 	if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
742 		smart_str_append_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
743 	}
744 
745 	if (scope && fptr->common.scope) {
746 		if (fptr->common.scope != scope) {
747 			smart_str_append_printf(str, ", inherits %s", ZSTR_VAL(fptr->common.scope->name));
748 		} else if (fptr->common.scope->parent) {
749 			lc_name = zend_string_tolower(fptr->common.function_name);
750 			if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) {
751 				if (fptr->common.scope != overwrites->common.scope) {
752 					smart_str_append_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name));
753 				}
754 			}
755 			zend_string_release_ex(lc_name, 0);
756 		}
757 	}
758 	if (fptr->common.prototype && fptr->common.prototype->common.scope) {
759 		smart_str_append_printf(str, ", prototype %s", ZSTR_VAL(fptr->common.prototype->common.scope->name));
760 	}
761 	if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
762 		smart_str_appends(str, ", ctor");
763 	}
764 	if (fptr->common.fn_flags & ZEND_ACC_DTOR) {
765 		smart_str_appends(str, ", dtor");
766 	}
767 	smart_str_appends(str, "> ");
768 
769 	if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
770 		smart_str_appends(str, "abstract ");
771 	}
772 	if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
773 		smart_str_appends(str, "final ");
774 	}
775 	if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
776 		smart_str_appends(str, "static ");
777 	}
778 
779 	if (fptr->common.scope) {
780 		/* These are mutually exclusive */
781 		switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
782 			case ZEND_ACC_PUBLIC:
783 				smart_str_appends(str, "public ");
784 				break;
785 			case ZEND_ACC_PRIVATE:
786 				smart_str_appends(str, "private ");
787 				break;
788 			case ZEND_ACC_PROTECTED:
789 				smart_str_appends(str, "protected ");
790 				break;
791 			default:
792 				smart_str_appends(str, "<visibility error> ");
793 				break;
794 		}
795 		smart_str_appends(str, "method ");
796 	} else {
797 		smart_str_appends(str, "function ");
798 	}
799 
800 	if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
801 		smart_str_appendc(str, '&');
802 	}
803 	smart_str_append_printf(str, "%s ] {\n", ZSTR_VAL(fptr->common.function_name));
804 	/* The information where a function is declared is only available for user classes */
805 	if (fptr->type == ZEND_USER_FUNCTION) {
806 		smart_str_append_printf(str, "%s  @@ %s %d - %d\n", indent,
807 						ZSTR_VAL(fptr->op_array.filename),
808 						fptr->op_array.line_start,
809 						fptr->op_array.line_end);
810 	}
811 	smart_str_append_printf(&param_indent, "%s  ", indent);
812 	smart_str_0(&param_indent);
813 	if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
814 		_function_closure_string(str, fptr, ZSTR_VAL(param_indent.s));
815 	}
816 	_function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
817 	smart_str_free(&param_indent);
818 	if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
819 		smart_str_append_printf(str, "  %s- Return [ ", indent);
820 		if (ZEND_TYPE_IS_CLASS(fptr->common.arg_info[-1].type)) {
821 			smart_str_append_printf(str, "%s ",
822 				ZSTR_VAL(ZEND_TYPE_NAME(fptr->common.arg_info[-1].type)));
823 			if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) {
824 				smart_str_appends(str, "or NULL ");
825 			}
826 		} else if (ZEND_TYPE_IS_CODE(fptr->common.arg_info[-1].type)) {
827 			smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(fptr->common.arg_info[-1].type)));
828 			if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) {
829 				smart_str_appends(str, "or NULL ");
830 			}
831 		}
832 		smart_str_appends(str, "]\n");
833 	}
834 	smart_str_append_printf(str, "%s}\n", indent);
835 }
836 /* }}} */
837 
838 /* {{{ _property_string */
_property_string(smart_str * str,zend_property_info * prop,const char * prop_name,char * indent,zend_bool dynamic)839 static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent, zend_bool dynamic)
840 {
841 	smart_str_append_printf(str, "%sProperty [ ", indent);
842 	if (!prop) {
843 		smart_str_append_printf(str, "<dynamic> public $%s", prop_name);
844 	} else {
845 		if (!(prop->flags & ZEND_ACC_STATIC)) {
846 			if (dynamic) {
847 				smart_str_appends(str, "<implicit> ");
848 			} else {
849 				smart_str_appends(str, "<default> ");
850 			}
851 		}
852 
853 		/* These are mutually exclusive */
854 		switch (prop->flags & ZEND_ACC_PPP_MASK) {
855 			case ZEND_ACC_PUBLIC:
856 				smart_str_appends(str, "public ");
857 				break;
858 			case ZEND_ACC_PRIVATE:
859 				smart_str_appends(str, "private ");
860 				break;
861 			case ZEND_ACC_PROTECTED:
862 				smart_str_appends(str, "protected ");
863 				break;
864 		}
865 		if (prop->flags & ZEND_ACC_STATIC) {
866 			smart_str_appends(str, "static ");
867 		}
868 		if (!prop_name) {
869 			const char *class_name;
870 			zend_unmangle_property_name(prop->name, &class_name, &prop_name);
871 		}
872 		smart_str_append_printf(str, "$%s", prop_name);
873 	}
874 
875 	smart_str_appends(str, " ]\n");
876 }
877 /* }}} */
878 
_extension_ini_string(zend_ini_entry * ini_entry,smart_str * str,char * indent,int number)879 static void _extension_ini_string(zend_ini_entry *ini_entry, smart_str *str, char *indent, int number) /* {{{ */
880 {
881 	char *comma = "";
882 
883 	if (number == ini_entry->module_number) {
884 		smart_str_append_printf(str, "    %sEntry [ %s <", indent, ZSTR_VAL(ini_entry->name));
885 		if (ini_entry->modifiable == ZEND_INI_ALL) {
886 			smart_str_appends(str, "ALL");
887 		} else {
888 			if (ini_entry->modifiable & ZEND_INI_USER) {
889 				smart_str_appends(str, "USER");
890 				comma = ",";
891 			}
892 			if (ini_entry->modifiable & ZEND_INI_PERDIR) {
893 				smart_str_append_printf(str, "%sPERDIR", comma);
894 				comma = ",";
895 			}
896 			if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
897 				smart_str_append_printf(str, "%sSYSTEM", comma);
898 			}
899 		}
900 
901 		smart_str_appends(str, "> ]\n");
902 		smart_str_append_printf(str, "    %s  Current = '%s'\n", indent, ini_entry->value ? ZSTR_VAL(ini_entry->value) : "");
903 		if (ini_entry->modified) {
904 			smart_str_append_printf(str, "    %s  Default = '%s'\n", indent, ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : "");
905 		}
906 		smart_str_append_printf(str, "    %s}\n", indent);
907 	}
908 }
909 /* }}} */
910 
_extension_class_string(zend_class_entry * ce,zend_string * key,smart_str * str,char * indent,zend_module_entry * module,int * num_classes)911 static void _extension_class_string(zend_class_entry *ce, zend_string *key, smart_str *str, char *indent, zend_module_entry *module, int *num_classes) /* {{{ */
912 {
913 	if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
914 		/* dump class if it is not an alias */
915 		if (zend_string_equals_ci(ce->name, key)) {
916 			smart_str_append_printf(str, "\n");
917 			_class_string(str, ce, NULL, indent);
918 			(*num_classes)++;
919 		}
920 	}
921 }
922 /* }}} */
923 
_extension_string(smart_str * str,zend_module_entry * module,char * indent)924 static void _extension_string(smart_str *str, zend_module_entry *module, char *indent) /* {{{ */
925 {
926 	smart_str_append_printf(str, "%sExtension [ ", indent);
927 	if (module->type == MODULE_PERSISTENT) {
928 		smart_str_appends(str, "<persistent>");
929 	}
930 	if (module->type == MODULE_TEMPORARY) {
931 		smart_str_appends(str, "<temporary>" );
932 	}
933 	smart_str_append_printf(str, " extension #%d %s version %s ] {\n",
934 					module->module_number, module->name,
935 					(module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
936 
937 	if (module->deps) {
938 		const zend_module_dep* dep = module->deps;
939 
940 		smart_str_appends(str, "\n  - Dependencies {\n");
941 
942 		while(dep->name) {
943 			smart_str_append_printf(str, "%s    Dependency [ %s (", indent, dep->name);
944 
945 			switch(dep->type) {
946 			case MODULE_DEP_REQUIRED:
947 				smart_str_appends(str, "Required");
948 				break;
949 			case MODULE_DEP_CONFLICTS:
950 				smart_str_appends(str, "Conflicts");
951 				break;
952 			case MODULE_DEP_OPTIONAL:
953 				smart_str_appends(str, "Optional");
954 				break;
955 			default:
956 				smart_str_appends(str, "Error"); /* shouldn't happen */
957 				break;
958 			}
959 
960 			if (dep->rel) {
961 				smart_str_append_printf(str, " %s", dep->rel);
962 			}
963 			if (dep->version) {
964 				smart_str_append_printf(str, " %s", dep->version);
965 			}
966 			smart_str_appends(str, ") ]\n");
967 			dep++;
968 		}
969 		smart_str_append_printf(str, "%s  }\n", indent);
970 	}
971 
972 	{
973 		smart_str str_ini = {0};
974 		zend_ini_entry *ini_entry;
975 		ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) {
976 			_extension_ini_string(ini_entry, &str_ini, indent, module->module_number);
977 		} ZEND_HASH_FOREACH_END();
978 		if (smart_str_get_len(&str_ini) > 0) {
979 			smart_str_append_printf(str, "\n  - INI {\n");
980 			smart_str_append_smart_str(str, &str_ini);
981 			smart_str_append_printf(str, "%s  }\n", indent);
982 		}
983 		smart_str_free(&str_ini);
984 	}
985 
986 	{
987 		smart_str str_constants = {0};
988 		zend_constant *constant;
989 		int num_constants = 0;
990 
991 		ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) {
992 			if (ZEND_CONSTANT_MODULE_NUMBER(constant) == module->module_number) {
993 				_const_string(&str_constants, ZSTR_VAL(constant->name), &constant->value, indent);
994 				num_constants++;
995 			}
996 		} ZEND_HASH_FOREACH_END();
997 
998 		if (num_constants) {
999 			smart_str_append_printf(str, "\n  - Constants [%d] {\n", num_constants);
1000 			smart_str_append_smart_str(str, &str_constants);
1001 			smart_str_append_printf(str, "%s  }\n", indent);
1002 		}
1003 		smart_str_free(&str_constants);
1004 	}
1005 
1006 	{
1007 		zend_function *fptr;
1008 		int first = 1;
1009 
1010 		ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
1011 			if (fptr->common.type==ZEND_INTERNAL_FUNCTION
1012 				&& fptr->internal_function.module == module) {
1013 				if (first) {
1014 					smart_str_append_printf(str, "\n  - Functions {\n");
1015 					first = 0;
1016 				}
1017 				_function_string(str, fptr, NULL, "    ");
1018 			}
1019 		} ZEND_HASH_FOREACH_END();
1020 		if (!first) {
1021 			smart_str_append_printf(str, "%s  }\n", indent);
1022 		}
1023 	}
1024 
1025 	{
1026 		zend_string *sub_indent = strpprintf(0, "%s    ", indent);
1027 		smart_str str_classes = {0};
1028 		zend_string *key;
1029 		zend_class_entry *ce;
1030 		int num_classes = 0;
1031 
1032 		ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
1033 			_extension_class_string(ce, key, &str_classes, ZSTR_VAL(sub_indent), module, &num_classes);
1034 		} ZEND_HASH_FOREACH_END();
1035 		if (num_classes) {
1036 			smart_str_append_printf(str, "\n  - Classes [%d] {", num_classes);
1037 			smart_str_append_smart_str(str, &str_classes);
1038 			smart_str_append_printf(str, "%s  }\n", indent);
1039 		}
1040 		smart_str_free(&str_classes);
1041 		zend_string_release_ex(sub_indent, 0);
1042 	}
1043 
1044 	smart_str_append_printf(str, "%s}\n", indent);
1045 }
1046 /* }}} */
1047 
_zend_extension_string(smart_str * str,zend_extension * extension,char * indent)1048 static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent) /* {{{ */
1049 {
1050 	smart_str_append_printf(str, "%sZend Extension [ %s ", indent, extension->name);
1051 
1052 	if (extension->version) {
1053 		smart_str_append_printf(str, "%s ", extension->version);
1054 	}
1055 	if (extension->copyright) {
1056 		smart_str_append_printf(str, "%s ", extension->copyright);
1057 	}
1058 	if (extension->author) {
1059 		smart_str_append_printf(str, "by %s ", extension->author);
1060 	}
1061 	if (extension->URL) {
1062 		smart_str_append_printf(str, "<%s> ", extension->URL);
1063 	}
1064 
1065 	smart_str_appends(str, "]\n");
1066 }
1067 /* }}} */
1068 
1069 /* {{{ _function_check_flag */
_function_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)1070 static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
1071 {
1072 	reflection_object *intern;
1073 	zend_function *mptr;
1074 
1075 	if (zend_parse_parameters_none() == FAILURE) {
1076 		return;
1077 	}
1078 	GET_REFLECTION_OBJECT_PTR(mptr);
1079 	RETURN_BOOL(mptr->common.fn_flags & mask);
1080 }
1081 /* }}} */
1082 
1083 /* {{{ zend_reflection_class_factory */
zend_reflection_class_factory(zend_class_entry * ce,zval * object)1084 PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object)
1085 {
1086 	reflection_object *intern;
1087 
1088 	reflection_instantiate(reflection_class_ptr, object);
1089 	intern = Z_REFLECTION_P(object);
1090 	intern->ptr = ce;
1091 	intern->ref_type = REF_TYPE_OTHER;
1092 	intern->ce = ce;
1093 	ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
1094 }
1095 /* }}} */
1096 
1097 /* {{{ reflection_extension_factory */
reflection_extension_factory(zval * object,const char * name_str)1098 static void reflection_extension_factory(zval *object, const char *name_str)
1099 {
1100 	reflection_object *intern;
1101 	size_t name_len = strlen(name_str);
1102 	zend_string *lcname;
1103 	struct _zend_module_entry *module;
1104 
1105 	lcname = zend_string_alloc(name_len, 0);
1106 	zend_str_tolower_copy(ZSTR_VAL(lcname), name_str, name_len);
1107 	module = zend_hash_find_ptr(&module_registry, lcname);
1108 	zend_string_efree(lcname);
1109 	if (!module) {
1110 		return;
1111 	}
1112 
1113 	reflection_instantiate(reflection_extension_ptr, object);
1114 	intern = Z_REFLECTION_P(object);
1115 	intern->ptr = module;
1116 	intern->ref_type = REF_TYPE_OTHER;
1117 	intern->ce = NULL;
1118 	ZVAL_STRINGL(reflection_prop_name(object), module->name, name_len);
1119 }
1120 /* }}} */
1121 
1122 /* {{{ reflection_parameter_factory */
reflection_parameter_factory(zend_function * fptr,zval * closure_object,struct _zend_arg_info * arg_info,uint32_t offset,zend_bool required,zval * object)1123 static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, zval *object)
1124 {
1125 	reflection_object *intern;
1126 	parameter_reference *reference;
1127 	zval *prop_name;
1128 
1129 	reflection_instantiate(reflection_parameter_ptr, object);
1130 	intern = Z_REFLECTION_P(object);
1131 	reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
1132 	reference->arg_info = arg_info;
1133 	reference->offset = offset;
1134 	reference->required = required;
1135 	reference->fptr = fptr;
1136 	intern->ptr = reference;
1137 	intern->ref_type = REF_TYPE_PARAMETER;
1138 	intern->ce = fptr->common.scope;
1139 	if (closure_object) {
1140 		Z_ADDREF_P(closure_object);
1141 		ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
1142 	}
1143 
1144 	prop_name = reflection_prop_name(object);
1145 	if (arg_info->name) {
1146 		if (fptr->type == ZEND_INTERNAL_FUNCTION &&
1147 		    !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
1148 			ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)->name);
1149 		} else {
1150 			ZVAL_STR_COPY(prop_name, arg_info->name);
1151 		}
1152 	} else {
1153 		ZVAL_NULL(prop_name);
1154 	}
1155 }
1156 /* }}} */
1157 
1158 /* {{{ reflection_type_factory */
reflection_type_factory(zend_type type,zval * object)1159 static void reflection_type_factory(zend_type type, zval *object)
1160 {
1161 	reflection_object *intern;
1162 	type_reference *reference;
1163 
1164 	reflection_instantiate(reflection_named_type_ptr, object);
1165 	intern = Z_REFLECTION_P(object);
1166 	reference = (type_reference*) emalloc(sizeof(type_reference));
1167 	reference->type = type;
1168 	intern->ptr = reference;
1169 	intern->ref_type = REF_TYPE_TYPE;
1170 
1171 	/* Property types may be resolved during the lifetime of the ReflectionType,
1172 	 * so we need to make sure that the strings we reference are not released. */
1173 	if (ZEND_TYPE_IS_NAME(type)) {
1174 		zend_string_addref(ZEND_TYPE_NAME(type));
1175 	}
1176 }
1177 /* }}} */
1178 
1179 /* {{{ reflection_function_factory */
reflection_function_factory(zend_function * function,zval * closure_object,zval * object)1180 static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object)
1181 {
1182 	reflection_object *intern;
1183 	reflection_instantiate(reflection_function_ptr, object);
1184 	intern = Z_REFLECTION_P(object);
1185 	intern->ptr = function;
1186 	intern->ref_type = REF_TYPE_FUNCTION;
1187 	intern->ce = NULL;
1188 	if (closure_object) {
1189 		Z_ADDREF_P(closure_object);
1190 		ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
1191 	}
1192 	ZVAL_STR_COPY(reflection_prop_name(object), function->common.function_name);
1193 }
1194 /* }}} */
1195 
1196 /* {{{ reflection_method_factory */
reflection_method_factory(zend_class_entry * ce,zend_function * method,zval * closure_object,zval * object)1197 static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object)
1198 {
1199 	reflection_object *intern;
1200 
1201 	reflection_instantiate(reflection_method_ptr, object);
1202 	intern = Z_REFLECTION_P(object);
1203 	intern->ptr = method;
1204 	intern->ref_type = REF_TYPE_FUNCTION;
1205 	intern->ce = ce;
1206 	if (closure_object) {
1207 		Z_ADDREF_P(closure_object);
1208 		ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
1209 	}
1210 
1211 	ZVAL_STR_COPY(reflection_prop_name(object),
1212 		(method->common.scope && method->common.scope->trait_aliases)
1213 			? zend_resolve_method_name(ce, method) : method->common.function_name);
1214 	ZVAL_STR_COPY(reflection_prop_class(object), method->common.scope->name);
1215 }
1216 /* }}} */
1217 
1218 /* {{{ reflection_property_factory */
reflection_property_factory(zend_class_entry * ce,zend_string * name,zend_property_info * prop,zval * object,zend_bool dynamic)1219 static void reflection_property_factory(zend_class_entry *ce, zend_string *name, zend_property_info *prop, zval *object, zend_bool dynamic)
1220 {
1221 	reflection_object *intern;
1222 	property_reference *reference;
1223 
1224 	if (!(prop->flags & ZEND_ACC_PRIVATE)) {
1225 		/* we have to search the class hierarchy for this (implicit) public or protected property */
1226 		zend_class_entry *tmp_ce = ce, *store_ce = ce;
1227 		zend_property_info *tmp_info = NULL;
1228 
1229 		while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, name)) == NULL) {
1230 			ce = tmp_ce;
1231 			tmp_ce = tmp_ce->parent;
1232 		}
1233 
1234 		if (tmp_info && (!(tmp_info->flags & ZEND_ACC_PRIVATE) || tmp_info->ce == tmp_ce)) { /* found something and it's not a parent's private */
1235 			prop = tmp_info;
1236 		} else { /* not found, use initial value */
1237 			ce = store_ce;
1238 		}
1239 	}
1240 
1241 	reflection_instantiate(reflection_property_ptr, object);
1242 	intern = Z_REFLECTION_P(object);
1243 	reference = (property_reference*) emalloc(sizeof(property_reference));
1244 	reference->prop = *prop;
1245 
1246 	if (ZEND_TYPE_IS_NAME(reference->prop.type)) {
1247 		zend_string_addref(ZEND_TYPE_NAME(reference->prop.type));
1248 	}
1249 
1250 	reference->unmangled_name = zend_string_copy(name);
1251 	reference->dynamic = dynamic;
1252 	intern->ptr = reference;
1253 	intern->ref_type = REF_TYPE_PROPERTY;
1254 	intern->ce = ce;
1255 	intern->ignore_visibility = 0;
1256 	ZVAL_STR_COPY(reflection_prop_name(object), name);
1257 	ZVAL_STR_COPY(reflection_prop_class(object), prop->ce->name);
1258 }
1259 /* }}} */
1260 
reflection_property_factory_str(zend_class_entry * ce,const char * name_str,size_t name_len,zend_property_info * prop,zval * object)1261 static void reflection_property_factory_str(zend_class_entry *ce, const char *name_str, size_t name_len, zend_property_info *prop, zval *object)
1262 {
1263 	zend_string *name = zend_string_init(name_str, name_len, 0);
1264 	reflection_property_factory(ce, name, prop, object, 0);
1265 	zend_string_release(name);
1266 }
1267 
1268 /* {{{ reflection_class_constant_factory */
reflection_class_constant_factory(zend_class_entry * ce,zend_string * name_str,zend_class_constant * constant,zval * object)1269 static void reflection_class_constant_factory(zend_class_entry *ce, zend_string *name_str, zend_class_constant *constant, zval *object)
1270 {
1271 	reflection_object *intern;
1272 
1273 	reflection_instantiate(reflection_class_constant_ptr, object);
1274 	intern = Z_REFLECTION_P(object);
1275 	intern->ptr = constant;
1276 	intern->ref_type = REF_TYPE_CLASS_CONSTANT;
1277 	intern->ce = constant->ce;
1278 	intern->ignore_visibility = 0;
1279 
1280 	ZVAL_STR_COPY(reflection_prop_name(object), name_str);
1281 	ZVAL_STR_COPY(reflection_prop_class(object), ce->name);
1282 }
1283 /* }}} */
1284 
reflection_export_impl(zval * return_value,zval * object,zend_bool return_output)1285 static void reflection_export_impl(zval *return_value, zval *object, zend_bool return_output) {
1286 	zval fname, retval;
1287 	int result;
1288 
1289 	/* Invoke the __toString() method */
1290 	ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring") - 1);
1291 	result = call_user_function(NULL, object, &fname, &retval, 0, NULL);
1292 	zval_ptr_dtor_str(&fname);
1293 
1294 	if (result == FAILURE) {
1295 		_DO_THROW("Invocation of method __toString() failed");
1296 		return;
1297 	}
1298 
1299 	if (Z_TYPE(retval) == IS_UNDEF) {
1300 		php_error_docref(NULL, E_WARNING, "%s::__toString() did not return anything", ZSTR_VAL(Z_OBJCE_P(object)->name));
1301 		RETURN_FALSE;
1302 	}
1303 
1304 	if (return_output) {
1305 		ZVAL_COPY_VALUE(return_value, &retval);
1306 	} else {
1307 		/* No need for _r variant, return of __toString should always be a string */
1308 		zend_print_zval(&retval, 0);
1309 		zend_printf("\n");
1310 		zval_ptr_dtor(&retval);
1311 	}
1312 }
1313 
1314 /* {{{ _reflection_export */
_reflection_export(INTERNAL_FUNCTION_PARAMETERS,zend_class_entry * ce_ptr,int ctor_argc)1315 static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
1316 {
1317 	zval reflector;
1318 	zval *argument_ptr, *argument2_ptr;
1319 	zval retval, params[2];
1320 	int result;
1321 	int return_output = 0;
1322 	zend_fcall_info fci;
1323 	zend_fcall_info_cache fcc;
1324 
1325 	if (ctor_argc == 1) {
1326 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &argument_ptr, &return_output) == FAILURE) {
1327 			return;
1328 		}
1329 		ZVAL_COPY_VALUE(&params[0], argument_ptr);
1330 		ZVAL_NULL(&params[1]);
1331 	} else {
1332 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|b", &argument_ptr, &argument2_ptr, &return_output) == FAILURE) {
1333 			return;
1334 		}
1335 		ZVAL_COPY_VALUE(&params[0], argument_ptr);
1336 		ZVAL_COPY_VALUE(&params[1], argument2_ptr);
1337 	}
1338 
1339 	/* Create object */
1340 	if (object_init_ex(&reflector, ce_ptr) == FAILURE) {
1341 		_DO_THROW("Could not create reflector");
1342 		return;
1343 	}
1344 
1345 	/* Call __construct() */
1346 
1347 	fci.size = sizeof(fci);
1348 	ZVAL_UNDEF(&fci.function_name);
1349 	fci.object = Z_OBJ(reflector);
1350 	fci.retval = &retval;
1351 	fci.param_count = ctor_argc;
1352 	fci.params = params;
1353 	fci.no_separation = 1;
1354 
1355 	fcc.function_handler = ce_ptr->constructor;
1356 	fcc.called_scope = Z_OBJCE(reflector);
1357 	fcc.object = Z_OBJ(reflector);
1358 
1359 	result = zend_call_function(&fci, &fcc);
1360 
1361 	zval_ptr_dtor(&retval);
1362 
1363 	if (EG(exception)) {
1364 		zval_ptr_dtor(&reflector);
1365 		return;
1366 	}
1367 	if (result == FAILURE) {
1368 		zval_ptr_dtor(&reflector);
1369 		_DO_THROW("Could not create reflector");
1370 		return;
1371 	}
1372 
1373 	reflection_export_impl(return_value, &reflector, return_output);
1374 
1375 	/* Destruct reflector which is no longer needed */
1376 	zval_ptr_dtor(&reflector);
1377 }
1378 /* }}} */
1379 
1380 /* {{{ _reflection_param_get_default_param */
_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS)1381 static parameter_reference *_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS)
1382 {
1383 	reflection_object *intern;
1384 	parameter_reference *param;
1385 
1386 	intern = Z_REFLECTION_P(ZEND_THIS);
1387 	if (intern->ptr == NULL) {
1388 		if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) {
1389 			return NULL;
1390 		}
1391 		zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object");
1392 		return NULL;
1393 	}
1394 
1395 	param = intern->ptr;
1396 	if (param->fptr->type != ZEND_USER_FUNCTION) {
1397 		zend_throw_exception_ex(reflection_exception_ptr, 0, "Cannot determine default value for internal functions");
1398 		return NULL;
1399 	}
1400 
1401 	return param;
1402 }
1403 /* }}} */
1404 
1405 /* {{{ _reflection_param_get_default_precv */
_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS,parameter_reference * param)1406 static zend_op *_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS, parameter_reference *param)
1407 {
1408 	zend_op *precv;
1409 
1410 	if (param == NULL) {
1411 		return NULL;
1412 	}
1413 
1414 	precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
1415 	if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
1416 		zend_throw_exception_ex(reflection_exception_ptr, 0, "Internal error: Failed to retrieve the default value");
1417 		return NULL;
1418 	}
1419 
1420 	return precv;
1421 }
1422 /* }}} */
1423 
1424 /* {{{ Preventing __clone from being called */
ZEND_METHOD(reflection,__clone)1425 ZEND_METHOD(reflection, __clone)
1426 {
1427 	/* Should never be executable */
1428 	_DO_THROW("Cannot clone object using __clone()");
1429 }
1430 /* }}} */
1431 
1432 /* {{{ proto public static mixed Reflection::export(Reflector r [, bool return])
1433    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection,export)1434 ZEND_METHOD(reflection, export)
1435 {
1436 	zval *object;
1437 	zend_bool return_output = 0;
1438 
1439 	ZEND_PARSE_PARAMETERS_START(1, 2)
1440 		Z_PARAM_OBJECT_OF_CLASS(object, reflector_ptr)
1441 		Z_PARAM_OPTIONAL
1442 		Z_PARAM_BOOL(return_output)
1443 	ZEND_PARSE_PARAMETERS_END();
1444 
1445 	reflection_export_impl(return_value, object, return_output);
1446 }
1447 /* }}} */
1448 
1449 /* {{{ proto public static array Reflection::getModifierNames(int modifiers)
1450    Returns an array of modifier names */
ZEND_METHOD(reflection,getModifierNames)1451 ZEND_METHOD(reflection, getModifierNames)
1452 {
1453 	zend_long modifiers;
1454 
1455 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &modifiers) == FAILURE) {
1456 		return;
1457 	}
1458 
1459 	array_init(return_value);
1460 
1461 	if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1462 		add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1);
1463 	}
1464 	if (modifiers & ZEND_ACC_FINAL) {
1465 		add_next_index_stringl(return_value, "final", sizeof("final")-1);
1466 	}
1467 
1468 	/* These are mutually exclusive */
1469 	switch (modifiers & ZEND_ACC_PPP_MASK) {
1470 		case ZEND_ACC_PUBLIC:
1471 			add_next_index_stringl(return_value, "public", sizeof("public")-1);
1472 			break;
1473 		case ZEND_ACC_PRIVATE:
1474 			add_next_index_stringl(return_value, "private", sizeof("private")-1);
1475 			break;
1476 		case ZEND_ACC_PROTECTED:
1477 			add_next_index_stringl(return_value, "protected", sizeof("protected")-1);
1478 			break;
1479 	}
1480 
1481 	if (modifiers & ZEND_ACC_STATIC) {
1482 		add_next_index_stringl(return_value, "static", sizeof("static")-1);
1483 	}
1484 }
1485 /* }}} */
1486 
1487 /* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return])
1488    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_function,export)1489 ZEND_METHOD(reflection_function, export)
1490 {
1491 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_function_ptr, 1);
1492 }
1493 /* }}} */
1494 
1495 /* {{{ proto public void ReflectionFunction::__construct(string name)
1496    Constructor. Throws an Exception in case the given function does not exist */
ZEND_METHOD(reflection_function,__construct)1497 ZEND_METHOD(reflection_function, __construct)
1498 {
1499 	zval *object;
1500 	zval *closure = NULL;
1501 	reflection_object *intern;
1502 	zend_function *fptr;
1503 	zend_string *fname, *lcname;
1504 
1505 	object = ZEND_THIS;
1506 	intern = Z_REFLECTION_P(object);
1507 
1508 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &closure, zend_ce_closure) == SUCCESS) {
1509 		fptr = (zend_function*)zend_get_closure_method_def(closure);
1510 		Z_ADDREF_P(closure);
1511 	} else {
1512 		ALLOCA_FLAG(use_heap)
1513 
1514 		if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "S", &fname) == FAILURE) {
1515 			return;
1516 		}
1517 
1518 		if (UNEXPECTED(ZSTR_VAL(fname)[0] == '\\')) {
1519 			/* Ignore leading "\" */
1520 			ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
1521 			zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
1522 			fptr = zend_fetch_function(lcname);
1523 			ZSTR_ALLOCA_FREE(lcname, use_heap);
1524 		} else {
1525 			lcname = zend_string_tolower(fname);
1526 			fptr = zend_fetch_function(lcname);
1527 			zend_string_release(lcname);
1528 		}
1529 
1530 		if (fptr == NULL) {
1531 			zend_throw_exception_ex(reflection_exception_ptr, 0,
1532 				"Function %s() does not exist", ZSTR_VAL(fname));
1533 			return;
1534 		}
1535 	}
1536 
1537 	if (intern->ptr) {
1538 		zval_ptr_dtor(&intern->obj);
1539 		zval_ptr_dtor(reflection_prop_name(object));
1540 	}
1541 
1542 	ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name);
1543 	intern->ptr = fptr;
1544 	intern->ref_type = REF_TYPE_FUNCTION;
1545 	if (closure) {
1546 		ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure));
1547 	} else {
1548 		ZVAL_UNDEF(&intern->obj);
1549 	}
1550 	intern->ce = NULL;
1551 }
1552 /* }}} */
1553 
1554 /* {{{ proto public string ReflectionFunction::__toString()
1555    Returns a string representation */
ZEND_METHOD(reflection_function,__toString)1556 ZEND_METHOD(reflection_function, __toString)
1557 {
1558 	reflection_object *intern;
1559 	zend_function *fptr;
1560 	smart_str str = {0};
1561 
1562 	if (zend_parse_parameters_none() == FAILURE) {
1563 		return;
1564 	}
1565 	GET_REFLECTION_OBJECT_PTR(fptr);
1566 	_function_string(&str, fptr, intern->ce, "");
1567 	RETURN_STR(smart_str_extract(&str));
1568 }
1569 /* }}} */
1570 
1571 /* {{{ proto public string ReflectionFunction::getName()
1572    Returns this function's name */
ZEND_METHOD(reflection_function,getName)1573 ZEND_METHOD(reflection_function, getName)
1574 {
1575 	if (zend_parse_parameters_none() == FAILURE) {
1576 		return;
1577 	}
1578 	_default_get_name(ZEND_THIS, return_value);
1579 }
1580 /* }}} */
1581 
1582 /* {{{ proto public bool ReflectionFunction::isClosure()
1583    Returns whether this is a closure */
ZEND_METHOD(reflection_function,isClosure)1584 ZEND_METHOD(reflection_function, isClosure)
1585 {
1586 	reflection_object *intern;
1587 	zend_function *fptr;
1588 
1589 	if (zend_parse_parameters_none() == FAILURE) {
1590 		return;
1591 	}
1592 	GET_REFLECTION_OBJECT_PTR(fptr);
1593 	RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE);
1594 }
1595 /* }}} */
1596 
1597 /* {{{ proto public bool ReflectionFunction::getClosureThis()
1598    Returns this pointer bound to closure */
ZEND_METHOD(reflection_function,getClosureThis)1599 ZEND_METHOD(reflection_function, getClosureThis)
1600 {
1601 	reflection_object *intern;
1602 	zval* closure_this;
1603 
1604 	if (zend_parse_parameters_none() == FAILURE) {
1605 		return;
1606 	}
1607 	GET_REFLECTION_OBJECT();
1608 	if (!Z_ISUNDEF(intern->obj)) {
1609 		closure_this = zend_get_closure_this_ptr(&intern->obj);
1610 		if (!Z_ISUNDEF_P(closure_this)) {
1611 			Z_ADDREF_P(closure_this);
1612 			ZVAL_OBJ(return_value, Z_OBJ_P(closure_this));
1613 		}
1614 	}
1615 }
1616 /* }}} */
1617 
1618 /* {{{ proto public ReflectionClass ReflectionFunction::getClosureScopeClass()
1619    Returns the scope associated to the closure */
ZEND_METHOD(reflection_function,getClosureScopeClass)1620 ZEND_METHOD(reflection_function, getClosureScopeClass)
1621 {
1622 	reflection_object *intern;
1623 	const zend_function *closure_func;
1624 
1625 	if (zend_parse_parameters_none() == FAILURE) {
1626 		return;
1627 	}
1628 	GET_REFLECTION_OBJECT();
1629 	if (!Z_ISUNDEF(intern->obj)) {
1630 		closure_func = zend_get_closure_method_def(&intern->obj);
1631 		if (closure_func && closure_func->common.scope) {
1632 			zend_reflection_class_factory(closure_func->common.scope, return_value);
1633 		}
1634 	}
1635 }
1636 /* }}} */
1637 
1638 /* {{{ proto public mixed ReflectionFunction::getClosure()
1639    Returns a dynamically created closure for the function */
ZEND_METHOD(reflection_function,getClosure)1640 ZEND_METHOD(reflection_function, getClosure)
1641 {
1642 	reflection_object *intern;
1643 	zend_function *fptr;
1644 
1645 	if (zend_parse_parameters_none() == FAILURE) {
1646 		return;
1647 	}
1648 	GET_REFLECTION_OBJECT_PTR(fptr);
1649 
1650 	if (!Z_ISUNDEF(intern->obj)) {
1651 		/* Closures are immutable objects */
1652 		Z_ADDREF(intern->obj);
1653 		ZVAL_OBJ(return_value, Z_OBJ(intern->obj));
1654 	} else {
1655 		zend_create_fake_closure(return_value, fptr, NULL, NULL, NULL);
1656 	}
1657 }
1658 /* }}} */
1659 
1660 /* {{{ proto public bool ReflectionFunction::isInternal()
1661    Returns whether this is an internal function */
ZEND_METHOD(reflection_function,isInternal)1662 ZEND_METHOD(reflection_function, isInternal)
1663 {
1664 	reflection_object *intern;
1665 	zend_function *fptr;
1666 
1667 	if (zend_parse_parameters_none() == FAILURE) {
1668 		return;
1669 	}
1670 	GET_REFLECTION_OBJECT_PTR(fptr);
1671 	RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION);
1672 }
1673 /* }}} */
1674 
1675 /* {{{ proto public bool ReflectionFunction::isUserDefined()
1676    Returns whether this is a user-defined function */
ZEND_METHOD(reflection_function,isUserDefined)1677 ZEND_METHOD(reflection_function, isUserDefined)
1678 {
1679 	reflection_object *intern;
1680 	zend_function *fptr;
1681 
1682 	if (zend_parse_parameters_none() == FAILURE) {
1683 		return;
1684 	}
1685 	GET_REFLECTION_OBJECT_PTR(fptr);
1686 	RETURN_BOOL(fptr->type == ZEND_USER_FUNCTION);
1687 }
1688 /* }}} */
1689 
1690 /* {{{ proto public bool ReflectionFunction::isDisabled()
1691    Returns whether this function has been disabled or not */
ZEND_METHOD(reflection_function,isDisabled)1692 ZEND_METHOD(reflection_function, isDisabled)
1693 {
1694 	reflection_object *intern;
1695 	zend_function *fptr;
1696 
1697 	GET_REFLECTION_OBJECT_PTR(fptr);
1698 	RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.handler == zif_display_disabled_function);
1699 }
1700 /* }}} */
1701 
1702 /* {{{ proto public string ReflectionFunction::getFileName()
1703    Returns the filename of the file this function was declared in */
ZEND_METHOD(reflection_function,getFileName)1704 ZEND_METHOD(reflection_function, getFileName)
1705 {
1706 	reflection_object *intern;
1707 	zend_function *fptr;
1708 
1709 	if (zend_parse_parameters_none() == FAILURE) {
1710 		return;
1711 	}
1712 	GET_REFLECTION_OBJECT_PTR(fptr);
1713 	if (fptr->type == ZEND_USER_FUNCTION) {
1714 		RETURN_STR_COPY(fptr->op_array.filename);
1715 	}
1716 	RETURN_FALSE;
1717 }
1718 /* }}} */
1719 
1720 /* {{{ proto public int ReflectionFunction::getStartLine()
1721    Returns the line this function's declaration starts at */
ZEND_METHOD(reflection_function,getStartLine)1722 ZEND_METHOD(reflection_function, getStartLine)
1723 {
1724 	reflection_object *intern;
1725 	zend_function *fptr;
1726 
1727 	if (zend_parse_parameters_none() == FAILURE) {
1728 		return;
1729 	}
1730 	GET_REFLECTION_OBJECT_PTR(fptr);
1731 	if (fptr->type == ZEND_USER_FUNCTION) {
1732 		RETURN_LONG(fptr->op_array.line_start);
1733 	}
1734 	RETURN_FALSE;
1735 }
1736 /* }}} */
1737 
1738 /* {{{ proto public int ReflectionFunction::getEndLine()
1739    Returns the line this function's declaration ends at */
ZEND_METHOD(reflection_function,getEndLine)1740 ZEND_METHOD(reflection_function, getEndLine)
1741 {
1742 	reflection_object *intern;
1743 	zend_function *fptr;
1744 
1745 	if (zend_parse_parameters_none() == FAILURE) {
1746 		return;
1747 	}
1748 	GET_REFLECTION_OBJECT_PTR(fptr);
1749 	if (fptr->type == ZEND_USER_FUNCTION) {
1750 		RETURN_LONG(fptr->op_array.line_end);
1751 	}
1752 	RETURN_FALSE;
1753 }
1754 /* }}} */
1755 
1756 /* {{{ proto public string ReflectionFunction::getDocComment()
1757    Returns the doc comment for this function */
ZEND_METHOD(reflection_function,getDocComment)1758 ZEND_METHOD(reflection_function, getDocComment)
1759 {
1760 	reflection_object *intern;
1761 	zend_function *fptr;
1762 
1763 	if (zend_parse_parameters_none() == FAILURE) {
1764 		return;
1765 	}
1766 	GET_REFLECTION_OBJECT_PTR(fptr);
1767 	if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
1768 		RETURN_STR_COPY(fptr->op_array.doc_comment);
1769 	}
1770 	RETURN_FALSE;
1771 }
1772 /* }}} */
1773 
1774 /* {{{ proto public array ReflectionFunction::getStaticVariables()
1775    Returns an associative array containing this function's static variables and their values */
ZEND_METHOD(reflection_function,getStaticVariables)1776 ZEND_METHOD(reflection_function, getStaticVariables)
1777 {
1778 	reflection_object *intern;
1779 	zend_function *fptr;
1780 	zval *val;
1781 
1782 	if (zend_parse_parameters_none() == FAILURE) {
1783 		return;
1784 	}
1785 	GET_REFLECTION_OBJECT_PTR(fptr);
1786 
1787 	/* Return an empty array in case no static variables exist */
1788 	if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
1789 		HashTable *ht;
1790 
1791 		array_init(return_value);
1792 		ht = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
1793 		if (!ht) {
1794 			ZEND_ASSERT(fptr->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
1795 			ht = zend_array_dup(fptr->op_array.static_variables);
1796 			ZEND_MAP_PTR_SET(fptr->op_array.static_variables_ptr, ht);
1797 		}
1798 		ZEND_HASH_FOREACH_VAL(ht, val) {
1799 			if (UNEXPECTED(zval_update_constant_ex(val, fptr->common.scope) != SUCCESS)) {
1800 				return;
1801 			}
1802 		} ZEND_HASH_FOREACH_END();
1803 		zend_hash_copy(Z_ARRVAL_P(return_value), ht, zval_add_ref);
1804 	} else {
1805 		RETURN_EMPTY_ARRAY();
1806 	}
1807 }
1808 /* }}} */
1809 
1810 /* {{{ proto public mixed ReflectionFunction::invoke([mixed* args])
1811    Invokes the function */
ZEND_METHOD(reflection_function,invoke)1812 ZEND_METHOD(reflection_function, invoke)
1813 {
1814 	zval retval;
1815 	zval *params = NULL;
1816 	int result, num_args = 0;
1817 	zend_fcall_info fci;
1818 	zend_fcall_info_cache fcc;
1819 	reflection_object *intern;
1820 	zend_function *fptr;
1821 
1822 	GET_REFLECTION_OBJECT_PTR(fptr);
1823 
1824 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &params, &num_args) == FAILURE) {
1825 		return;
1826 	}
1827 
1828 	fci.size = sizeof(fci);
1829 	ZVAL_UNDEF(&fci.function_name);
1830 	fci.object = NULL;
1831 	fci.retval = &retval;
1832 	fci.param_count = num_args;
1833 	fci.params = params;
1834 	fci.no_separation = 1;
1835 
1836 	fcc.function_handler = fptr;
1837 	fcc.called_scope = NULL;
1838 	fcc.object = NULL;
1839 
1840 	if (!Z_ISUNDEF(intern->obj)) {
1841 		Z_OBJ_HT(intern->obj)->get_closure(
1842 			&intern->obj, &fcc.called_scope, &fcc.function_handler, &fcc.object);
1843 	}
1844 
1845 	result = zend_call_function(&fci, &fcc);
1846 
1847 	if (result == FAILURE) {
1848 		zend_throw_exception_ex(reflection_exception_ptr, 0,
1849 			"Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
1850 		return;
1851 	}
1852 
1853 	if (Z_TYPE(retval) != IS_UNDEF) {
1854 		if (Z_ISREF(retval)) {
1855 			zend_unwrap_reference(&retval);
1856 		}
1857 		ZVAL_COPY_VALUE(return_value, &retval);
1858 	}
1859 }
1860 /* }}} */
1861 
1862 /* {{{ proto public mixed ReflectionFunction::invokeArgs(array args)
1863    Invokes the function and pass its arguments as array. */
ZEND_METHOD(reflection_function,invokeArgs)1864 ZEND_METHOD(reflection_function, invokeArgs)
1865 {
1866 	zval retval;
1867 	zval *params, *val;
1868 	int result;
1869 	int i, argc;
1870 	zend_fcall_info fci;
1871 	zend_fcall_info_cache fcc;
1872 	reflection_object *intern;
1873 	zend_function *fptr;
1874 	zval *param_array;
1875 
1876 	GET_REFLECTION_OBJECT_PTR(fptr);
1877 
1878 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &param_array) == FAILURE) {
1879 		return;
1880 	}
1881 
1882 	argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
1883 
1884 	params = safe_emalloc(sizeof(zval), argc, 0);
1885 	argc = 0;
1886 	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
1887 		ZVAL_COPY(&params[argc], val);
1888 		argc++;
1889 	} ZEND_HASH_FOREACH_END();
1890 
1891 	fci.size = sizeof(fci);
1892 	ZVAL_UNDEF(&fci.function_name);
1893 	fci.object = NULL;
1894 	fci.retval = &retval;
1895 	fci.param_count = argc;
1896 	fci.params = params;
1897 	fci.no_separation = 1;
1898 
1899 	fcc.function_handler = fptr;
1900 	fcc.called_scope = NULL;
1901 	fcc.object = NULL;
1902 
1903 	if (!Z_ISUNDEF(intern->obj)) {
1904 		Z_OBJ_HT(intern->obj)->get_closure(
1905 			&intern->obj, &fcc.called_scope, &fcc.function_handler, &fcc.object);
1906 	}
1907 
1908 	result = zend_call_function(&fci, &fcc);
1909 
1910 	for (i = 0; i < argc; i++) {
1911 		zval_ptr_dtor(&params[i]);
1912 	}
1913 	efree(params);
1914 
1915 	if (result == FAILURE) {
1916 		zend_throw_exception_ex(reflection_exception_ptr, 0,
1917 			"Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
1918 		return;
1919 	}
1920 
1921 	if (Z_TYPE(retval) != IS_UNDEF) {
1922 		if (Z_ISREF(retval)) {
1923 			zend_unwrap_reference(&retval);
1924 		}
1925 		ZVAL_COPY_VALUE(return_value, &retval);
1926 	}
1927 }
1928 /* }}} */
1929 
1930 /* {{{ proto public bool ReflectionFunction::returnsReference()
1931    Gets whether this function returns a reference */
ZEND_METHOD(reflection_function,returnsReference)1932 ZEND_METHOD(reflection_function, returnsReference)
1933 {
1934 	reflection_object *intern;
1935 	zend_function *fptr;
1936 
1937 	GET_REFLECTION_OBJECT_PTR(fptr);
1938 
1939 	RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0);
1940 }
1941 /* }}} */
1942 
1943 /* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
1944    Gets the number of parameters */
ZEND_METHOD(reflection_function,getNumberOfParameters)1945 ZEND_METHOD(reflection_function, getNumberOfParameters)
1946 {
1947 	reflection_object *intern;
1948 	zend_function *fptr;
1949 	uint32_t num_args;
1950 
1951 	GET_REFLECTION_OBJECT_PTR(fptr);
1952 
1953 	num_args = fptr->common.num_args;
1954 	if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
1955 		num_args++;
1956 	}
1957 
1958 	RETURN_LONG(num_args);
1959 }
1960 /* }}} */
1961 
1962 /* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
1963    Gets the number of required parameters */
ZEND_METHOD(reflection_function,getNumberOfRequiredParameters)1964 ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
1965 {
1966 	reflection_object *intern;
1967 	zend_function *fptr;
1968 
1969 	GET_REFLECTION_OBJECT_PTR(fptr);
1970 
1971 	RETURN_LONG(fptr->common.required_num_args);
1972 }
1973 /* }}} */
1974 
1975 /* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
1976    Returns an array of parameter objects for this function */
ZEND_METHOD(reflection_function,getParameters)1977 ZEND_METHOD(reflection_function, getParameters)
1978 {
1979 	reflection_object *intern;
1980 	zend_function *fptr;
1981 	uint32_t i, num_args;
1982 	struct _zend_arg_info *arg_info;
1983 
1984 	GET_REFLECTION_OBJECT_PTR(fptr);
1985 
1986 	arg_info= fptr->common.arg_info;
1987 	num_args = fptr->common.num_args;
1988 	if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
1989 		num_args++;
1990 	}
1991 
1992 	if (!num_args) {
1993 		RETURN_EMPTY_ARRAY();
1994 	}
1995 
1996 	array_init(return_value);
1997 	for (i = 0; i < num_args; i++) {
1998 		zval parameter;
1999 
2000 		reflection_parameter_factory(
2001 			_copy_function(fptr),
2002 			Z_ISUNDEF(intern->obj) ? NULL : &intern->obj,
2003 			arg_info,
2004 			i,
2005 			i < fptr->common.required_num_args,
2006 			&parameter
2007 		);
2008 		add_next_index_zval(return_value, &parameter);
2009 
2010 		arg_info++;
2011 	}
2012 }
2013 /* }}} */
2014 
2015 /* {{{ proto public ReflectionExtension|NULL ReflectionFunction::getExtension()
2016    Returns NULL or the extension the function belongs to */
ZEND_METHOD(reflection_function,getExtension)2017 ZEND_METHOD(reflection_function, getExtension)
2018 {
2019 	reflection_object *intern;
2020 	zend_function *fptr;
2021 	zend_internal_function *internal;
2022 
2023 	GET_REFLECTION_OBJECT_PTR(fptr);
2024 
2025 	if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2026 		RETURN_NULL();
2027 	}
2028 
2029 	internal = (zend_internal_function *)fptr;
2030 	if (internal->module) {
2031 		reflection_extension_factory(return_value, internal->module->name);
2032 	} else {
2033 		RETURN_NULL();
2034 	}
2035 }
2036 /* }}} */
2037 
2038 /* {{{ proto public string|false ReflectionFunction::getExtensionName()
2039    Returns false or the name of the extension the function belongs to */
ZEND_METHOD(reflection_function,getExtensionName)2040 ZEND_METHOD(reflection_function, getExtensionName)
2041 {
2042 	reflection_object *intern;
2043 	zend_function *fptr;
2044 	zend_internal_function *internal;
2045 
2046 	GET_REFLECTION_OBJECT_PTR(fptr);
2047 
2048 	if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2049 		RETURN_FALSE;
2050 	}
2051 
2052 	internal = (zend_internal_function *)fptr;
2053 	if (internal->module) {
2054 		RETURN_STRING(internal->module->name);
2055 	} else {
2056 		RETURN_FALSE;
2057 	}
2058 }
2059 /* }}} */
2060 
2061 /* {{{ proto public void ReflectionGenerator::__construct(object Generator) */
ZEND_METHOD(reflection_generator,__construct)2062 ZEND_METHOD(reflection_generator, __construct)
2063 {
2064 	zval *generator, *object;
2065 	reflection_object *intern;
2066 	zend_execute_data *ex;
2067 
2068 	object = ZEND_THIS;
2069 	intern = Z_REFLECTION_P(object);
2070 
2071 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O", &generator, zend_ce_generator) == FAILURE) {
2072 		return;
2073 	}
2074 
2075 	ex = ((zend_generator *) Z_OBJ_P(generator))->execute_data;
2076 	if (!ex) {
2077 		_DO_THROW("Cannot create ReflectionGenerator based on a terminated Generator");
2078 		return;
2079 	}
2080 
2081 	if (intern->ce) {
2082 		zval_ptr_dtor(&intern->obj);
2083 	}
2084 
2085 	intern->ref_type = REF_TYPE_GENERATOR;
2086 	Z_ADDREF_P(generator);
2087 	ZVAL_OBJ(&intern->obj, Z_OBJ_P(generator));
2088 	intern->ce = zend_ce_generator;
2089 }
2090 /* }}} */
2091 
2092 #define REFLECTION_CHECK_VALID_GENERATOR(ex) \
2093 	if (!ex) { \
2094 		_DO_THROW("Cannot fetch information from a terminated Generator"); \
2095 		return; \
2096 	}
2097 
2098 /* {{{ proto public array ReflectionGenerator::getTrace($options = DEBUG_BACKTRACE_PROVIDE_OBJECT) */
ZEND_METHOD(reflection_generator,getTrace)2099 ZEND_METHOD(reflection_generator, getTrace)
2100 {
2101 	zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
2102 	zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2103 	zend_generator *root_generator;
2104 	zend_execute_data *ex_backup = EG(current_execute_data);
2105 	zend_execute_data *ex = generator->execute_data;
2106 	zend_execute_data *root_prev = NULL, *cur_prev;
2107 
2108 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &options) == FAILURE) {
2109 		return;
2110 	}
2111 
2112 	REFLECTION_CHECK_VALID_GENERATOR(ex)
2113 
2114 	root_generator = zend_generator_get_current(generator);
2115 
2116 	cur_prev = generator->execute_data->prev_execute_data;
2117 	if (generator == root_generator) {
2118 		generator->execute_data->prev_execute_data = NULL;
2119 	} else {
2120 		root_prev = root_generator->execute_data->prev_execute_data;
2121 		generator->execute_fake.prev_execute_data = NULL;
2122 		root_generator->execute_data->prev_execute_data = &generator->execute_fake;
2123 	}
2124 
2125 	EG(current_execute_data) = root_generator->execute_data;
2126 	zend_fetch_debug_backtrace(return_value, 0, options, 0);
2127 	EG(current_execute_data) = ex_backup;
2128 
2129 	root_generator->execute_data->prev_execute_data = root_prev;
2130 	generator->execute_data->prev_execute_data = cur_prev;
2131 }
2132 /* }}} */
2133 
2134 /* {{{ proto public int ReflectionGenerator::getExecutingLine() */
ZEND_METHOD(reflection_generator,getExecutingLine)2135 ZEND_METHOD(reflection_generator, getExecutingLine)
2136 {
2137 	zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2138 	zend_execute_data *ex = generator->execute_data;
2139 
2140 	if (zend_parse_parameters_none() == FAILURE) {
2141 		return;
2142 	}
2143 
2144 	REFLECTION_CHECK_VALID_GENERATOR(ex)
2145 
2146 	ZVAL_LONG(return_value, ex->opline->lineno);
2147 }
2148 /* }}} */
2149 
2150 /* {{{ proto public string ReflectionGenerator::getExecutingFile() */
ZEND_METHOD(reflection_generator,getExecutingFile)2151 ZEND_METHOD(reflection_generator, getExecutingFile)
2152 {
2153 	zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2154 	zend_execute_data *ex = generator->execute_data;
2155 
2156 	if (zend_parse_parameters_none() == FAILURE) {
2157 		return;
2158 	}
2159 
2160 	REFLECTION_CHECK_VALID_GENERATOR(ex)
2161 
2162 	ZVAL_STR_COPY(return_value, ex->func->op_array.filename);
2163 }
2164 /* }}} */
2165 
2166 /* {{{ proto public ReflectionFunctionAbstract ReflectionGenerator::getFunction() */
ZEND_METHOD(reflection_generator,getFunction)2167 ZEND_METHOD(reflection_generator, getFunction)
2168 {
2169 	zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2170 	zend_execute_data *ex = generator->execute_data;
2171 
2172 	if (zend_parse_parameters_none() == FAILURE) {
2173 		return;
2174 	}
2175 
2176 	REFLECTION_CHECK_VALID_GENERATOR(ex)
2177 
2178 	if (ex->func->common.fn_flags & ZEND_ACC_CLOSURE) {
2179 		zval closure;
2180 		ZVAL_OBJ(&closure, ZEND_CLOSURE_OBJECT(ex->func));
2181 		reflection_function_factory(ex->func, &closure, return_value);
2182 	} else if (ex->func->op_array.scope) {
2183 		reflection_method_factory(ex->func->op_array.scope, ex->func, NULL, return_value);
2184 	} else {
2185 		reflection_function_factory(ex->func, NULL, return_value);
2186 	}
2187 }
2188 /* }}} */
2189 
2190 /* {{{ proto public object ReflectionGenerator::getThis() */
ZEND_METHOD(reflection_generator,getThis)2191 ZEND_METHOD(reflection_generator, getThis)
2192 {
2193 	zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2194 	zend_execute_data *ex = generator->execute_data;
2195 
2196 	if (zend_parse_parameters_none() == FAILURE) {
2197 		return;
2198 	}
2199 
2200 	REFLECTION_CHECK_VALID_GENERATOR(ex)
2201 
2202 	if (Z_TYPE(ex->This) == IS_OBJECT) {
2203 		Z_ADDREF(ex->This);
2204 		ZVAL_OBJ(return_value, Z_OBJ(ex->This));
2205 	} else {
2206 		ZVAL_NULL(return_value);
2207 	}
2208 }
2209 /* }}} */
2210 
2211 /* {{{ proto public Generator ReflectionGenerator::getExecutingGenerator() */
ZEND_METHOD(reflection_generator,getExecutingGenerator)2212 ZEND_METHOD(reflection_generator, getExecutingGenerator)
2213 {
2214 	zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2215 	zend_execute_data *ex = generator->execute_data;
2216 	zend_generator *current;
2217 
2218 	if (zend_parse_parameters_none() == FAILURE) {
2219 		return;
2220 	}
2221 
2222 	REFLECTION_CHECK_VALID_GENERATOR(ex)
2223 
2224 	current = zend_generator_get_current(generator);
2225 	GC_ADDREF(&current->std);
2226 
2227 	ZVAL_OBJ(return_value, (zend_object *) current);
2228 }
2229 /* }}} */
2230 
2231 /* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException
2232    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_parameter,export)2233 ZEND_METHOD(reflection_parameter, export)
2234 {
2235 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_parameter_ptr, 2);
2236 }
2237 /* }}} */
2238 
2239 /* {{{ proto public void ReflectionParameter::__construct(mixed function, mixed parameter)
2240    Constructor. Throws an Exception in case the given method does not exist */
ZEND_METHOD(reflection_parameter,__construct)2241 ZEND_METHOD(reflection_parameter, __construct)
2242 {
2243 	parameter_reference *ref;
2244 	zval *reference, *parameter;
2245 	zval *object;
2246 	zval *prop_name;
2247 	reflection_object *intern;
2248 	zend_function *fptr;
2249 	struct _zend_arg_info *arg_info;
2250 	int position;
2251 	uint32_t num_args;
2252 	zend_class_entry *ce = NULL;
2253 	zend_bool is_closure = 0;
2254 
2255 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zz", &reference, &parameter) == FAILURE) {
2256 		return;
2257 	}
2258 
2259 	object = ZEND_THIS;
2260 	intern = Z_REFLECTION_P(object);
2261 
2262 	/* First, find the function */
2263 	switch (Z_TYPE_P(reference)) {
2264 		case IS_STRING:
2265 			{
2266 				zend_string *lcname = zend_string_tolower(Z_STR_P(reference));
2267 				fptr = zend_hash_find_ptr(EG(function_table), lcname);
2268 				zend_string_release(lcname);
2269 				if (!fptr) {
2270 					zend_throw_exception_ex(reflection_exception_ptr, 0,
2271 						"Function %s() does not exist", Z_STRVAL_P(reference));
2272 					return;
2273 				}
2274 				ce = fptr->common.scope;
2275 			}
2276 			break;
2277 
2278 		case IS_ARRAY: {
2279 				zval *classref;
2280 				zval *method;
2281 				zend_string *name, *lcname;
2282 
2283 				if (((classref = zend_hash_index_find(Z_ARRVAL_P(reference), 0)) == NULL)
2284 					|| ((method = zend_hash_index_find(Z_ARRVAL_P(reference), 1)) == NULL))
2285 				{
2286 					_DO_THROW("Expected array($object, $method) or array($classname, $method)");
2287 					return;
2288 				}
2289 
2290 				if (Z_TYPE_P(classref) == IS_OBJECT) {
2291 					ce = Z_OBJCE_P(classref);
2292 				} else {
2293 					name = zval_try_get_string(classref);
2294 					if (UNEXPECTED(!name)) {
2295 						return;
2296 					}
2297 					if ((ce = zend_lookup_class(name)) == NULL) {
2298 						zend_throw_exception_ex(reflection_exception_ptr, 0,
2299 								"Class %s does not exist", ZSTR_VAL(name));
2300 						zend_string_release(name);
2301 						return;
2302 					}
2303 					zend_string_release(name);
2304 				}
2305 
2306 				name = zval_try_get_string(method);
2307 				if (UNEXPECTED(!name)) {
2308 					return;
2309 				}
2310 
2311 				lcname = zend_string_tolower(name);
2312 				if (Z_TYPE_P(classref) == IS_OBJECT && is_closure_invoke(ce, lcname)
2313 					&& (fptr = zend_get_closure_invoke_method(Z_OBJ_P(classref))) != NULL)
2314 				{
2315 					/* nothing to do. don't set is_closure since is the invoke handler,
2316 					   not the closure itself */
2317 				} else if ((fptr = zend_hash_find_ptr(&ce->function_table, lcname)) == NULL) {
2318 					zend_throw_exception_ex(reflection_exception_ptr, 0,
2319 						"Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
2320 					zend_string_release(name);
2321 					zend_string_release(lcname);
2322 					return;
2323 				}
2324 				zend_string_release(name);
2325 				zend_string_release(lcname);
2326 			}
2327 			break;
2328 
2329 		case IS_OBJECT: {
2330 				ce = Z_OBJCE_P(reference);
2331 
2332 				if (instanceof_function(ce, zend_ce_closure)) {
2333 					fptr = (zend_function *)zend_get_closure_method_def(reference);
2334 					Z_ADDREF_P(reference);
2335 					is_closure = 1;
2336 				} else if ((fptr = zend_hash_find_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE))) == NULL) {
2337 					zend_throw_exception_ex(reflection_exception_ptr, 0,
2338 						"Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZEND_INVOKE_FUNC_NAME);
2339 					return;
2340 				}
2341 			}
2342 			break;
2343 
2344 		default:
2345 			_DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
2346 			return;
2347 	}
2348 
2349 	/* Now, search for the parameter */
2350 	arg_info = fptr->common.arg_info;
2351 	num_args = fptr->common.num_args;
2352 	if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2353 		num_args++;
2354 	}
2355 	if (Z_TYPE_P(parameter) == IS_LONG) {
2356 		position= (int)Z_LVAL_P(parameter);
2357 		if (position < 0 || (uint32_t)position >= num_args) {
2358 			_DO_THROW("The parameter specified by its offset could not be found");
2359 			goto failure;
2360 		}
2361 	} else {
2362 		uint32_t i;
2363 
2364 		position = -1;
2365 		if (!try_convert_to_string(parameter)) {
2366 			goto failure;
2367 		}
2368 
2369 		if (fptr->type == ZEND_INTERNAL_FUNCTION &&
2370 		    !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2371 			for (i = 0; i < num_args; i++) {
2372 				if (arg_info[i].name) {
2373 					if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) {
2374 						position = i;
2375 						break;
2376 					}
2377 
2378 				}
2379 			}
2380 		} else {
2381 			for (i = 0; i < num_args; i++) {
2382 				if (arg_info[i].name) {
2383 					if (strcmp(ZSTR_VAL(arg_info[i].name), Z_STRVAL_P(parameter)) == 0) {
2384 						position = i;
2385 						break;
2386 					}
2387 				}
2388 			}
2389 		}
2390 		if (position == -1) {
2391 			_DO_THROW("The parameter specified by its name could not be found");
2392 			goto failure;
2393 		}
2394 	}
2395 
2396 	ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
2397 	ref->arg_info = &arg_info[position];
2398 	ref->offset = (uint32_t)position;
2399 	ref->required = (uint32_t)position < fptr->common.required_num_args;
2400 	ref->fptr = fptr;
2401 	/* TODO: copy fptr */
2402 	intern->ptr = ref;
2403 	intern->ref_type = REF_TYPE_PARAMETER;
2404 	intern->ce = ce;
2405 	if (reference && is_closure) {
2406 		ZVAL_COPY_VALUE(&intern->obj, reference);
2407 	}
2408 
2409 	prop_name = reflection_prop_name(object);
2410 	if (arg_info[position].name) {
2411 		if (fptr->type == ZEND_INTERNAL_FUNCTION &&
2412 		    !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2413 			ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)[position].name);
2414 		} else {
2415 			ZVAL_STR_COPY(prop_name, arg_info[position].name);
2416 		}
2417 	} else {
2418 		ZVAL_NULL(prop_name);
2419 	}
2420 	return;
2421 
2422 failure:
2423 	if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2424 		if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
2425 			zend_string_release_ex(fptr->common.function_name, 0);
2426 		}
2427 		zend_free_trampoline(fptr);
2428 	}
2429 	if (is_closure) {
2430 		zval_ptr_dtor(reference);
2431 	}
2432 }
2433 /* }}} */
2434 
2435 /* {{{ proto public string ReflectionParameter::__toString()
2436    Returns a string representation */
ZEND_METHOD(reflection_parameter,__toString)2437 ZEND_METHOD(reflection_parameter, __toString)
2438 {
2439 	reflection_object *intern;
2440 	parameter_reference *param;
2441 	smart_str str = {0};
2442 
2443 	if (zend_parse_parameters_none() == FAILURE) {
2444 		return;
2445 	}
2446 	GET_REFLECTION_OBJECT_PTR(param);
2447 	_parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "");
2448 	RETURN_STR(smart_str_extract(&str));
2449 }
2450 
2451 /* }}} */
2452 
2453 /* {{{ proto public string ReflectionParameter::getName()
2454    Returns this parameters's name */
ZEND_METHOD(reflection_parameter,getName)2455 ZEND_METHOD(reflection_parameter, getName)
2456 {
2457 	if (zend_parse_parameters_none() == FAILURE) {
2458 		return;
2459 	}
2460 	_default_get_name(ZEND_THIS, return_value);
2461 }
2462 /* }}} */
2463 
2464 /* {{{ proto public ReflectionFunction ReflectionParameter::getDeclaringFunction()
2465    Returns the ReflectionFunction for the function of this parameter */
ZEND_METHOD(reflection_parameter,getDeclaringFunction)2466 ZEND_METHOD(reflection_parameter, getDeclaringFunction)
2467 {
2468 	reflection_object *intern;
2469 	parameter_reference *param;
2470 
2471 	if (zend_parse_parameters_none() == FAILURE) {
2472 		return;
2473 	}
2474 	GET_REFLECTION_OBJECT_PTR(param);
2475 
2476 	if (!param->fptr->common.scope) {
2477 		reflection_function_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2478 	} else {
2479 		reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2480 	}
2481 }
2482 /* }}} */
2483 
2484 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass()
2485    Returns in which class this parameter is defined (not the type of the parameter) */
ZEND_METHOD(reflection_parameter,getDeclaringClass)2486 ZEND_METHOD(reflection_parameter, getDeclaringClass)
2487 {
2488 	reflection_object *intern;
2489 	parameter_reference *param;
2490 
2491 	if (zend_parse_parameters_none() == FAILURE) {
2492 		return;
2493 	}
2494 	GET_REFLECTION_OBJECT_PTR(param);
2495 
2496 	if (param->fptr->common.scope) {
2497 		zend_reflection_class_factory(param->fptr->common.scope, return_value);
2498 	}
2499 }
2500 /* }}} */
2501 
2502 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getClass()
2503    Returns this parameters's class hint or NULL if there is none */
ZEND_METHOD(reflection_parameter,getClass)2504 ZEND_METHOD(reflection_parameter, getClass)
2505 {
2506 	reflection_object *intern;
2507 	parameter_reference *param;
2508 	zend_class_entry *ce;
2509 
2510 	if (zend_parse_parameters_none() == FAILURE) {
2511 		return;
2512 	}
2513 	GET_REFLECTION_OBJECT_PTR(param);
2514 
2515 	if (ZEND_TYPE_IS_CLASS(param->arg_info->type)) {
2516 		/* Class name is stored as a string, we might also get "self" or "parent"
2517 		 * - For "self", simply use the function scope. If scope is NULL then
2518 		 *   the function is global and thus self does not make any sense
2519 		 *
2520 		 * - For "parent", use the function scope's parent. If scope is NULL then
2521 		 *   the function is global and thus parent does not make any sense.
2522 		 *   If the parent is NULL then the class does not extend anything and
2523 		 *   thus parent does not make any sense, either.
2524 		 *
2525 		 * TODO: Think about moving these checks to the compiler or some sort of
2526 		 * lint-mode.
2527 		 */
2528 		zend_string *class_name;
2529 
2530 		class_name = ZEND_TYPE_NAME(param->arg_info->type);
2531 		if (0 == zend_binary_strcasecmp(ZSTR_VAL(class_name), ZSTR_LEN(class_name), "self", sizeof("self")- 1)) {
2532 			ce = param->fptr->common.scope;
2533 			if (!ce) {
2534 				zend_throw_exception_ex(reflection_exception_ptr, 0,
2535 					"Parameter uses 'self' as type hint but function is not a class member!");
2536 				return;
2537 			}
2538 		} else if (0 == zend_binary_strcasecmp(ZSTR_VAL(class_name), ZSTR_LEN(class_name), "parent", sizeof("parent")- 1)) {
2539 			ce = param->fptr->common.scope;
2540 			if (!ce) {
2541 				zend_throw_exception_ex(reflection_exception_ptr, 0,
2542 					"Parameter uses 'parent' as type hint but function is not a class member!");
2543 				return;
2544 			}
2545 			if (!ce->parent) {
2546 				zend_throw_exception_ex(reflection_exception_ptr, 0,
2547 					"Parameter uses 'parent' as type hint although class does not have a parent!");
2548 				return;
2549 			}
2550 			ce = ce->parent;
2551 		} else {
2552 			ce = zend_lookup_class(class_name);
2553 			if (!ce) {
2554 				zend_throw_exception_ex(reflection_exception_ptr, 0,
2555 					"Class %s does not exist", ZSTR_VAL(class_name));
2556 				return;
2557 			}
2558 		}
2559 		zend_reflection_class_factory(ce, return_value);
2560 	}
2561 }
2562 /* }}} */
2563 
2564 /* {{{ proto public bool ReflectionParameter::hasType()
2565    Returns whether parameter has a type */
ZEND_METHOD(reflection_parameter,hasType)2566 ZEND_METHOD(reflection_parameter, hasType)
2567 {
2568 	reflection_object *intern;
2569 	parameter_reference *param;
2570 
2571 	if (zend_parse_parameters_none() == FAILURE) {
2572 		return;
2573 	}
2574 	GET_REFLECTION_OBJECT_PTR(param);
2575 
2576 	RETVAL_BOOL(ZEND_TYPE_IS_SET(param->arg_info->type));
2577 }
2578 /* }}} */
2579 
2580 /* {{{ proto public ReflectionType ReflectionParameter::getType()
2581    Returns the type associated with the parameter */
ZEND_METHOD(reflection_parameter,getType)2582 ZEND_METHOD(reflection_parameter, getType)
2583 {
2584 	reflection_object *intern;
2585 	parameter_reference *param;
2586 
2587 	if (zend_parse_parameters_none() == FAILURE) {
2588 		return;
2589 	}
2590 	GET_REFLECTION_OBJECT_PTR(param);
2591 
2592 	if (!ZEND_TYPE_IS_SET(param->arg_info->type)) {
2593 		RETURN_NULL();
2594 	}
2595 	reflection_type_factory(param->arg_info->type, return_value);
2596 }
2597 /* }}} */
2598 
2599 /* {{{ proto public bool ReflectionParameter::isArray()
2600    Returns whether parameter MUST be an array */
ZEND_METHOD(reflection_parameter,isArray)2601 ZEND_METHOD(reflection_parameter, isArray)
2602 {
2603 	reflection_object *intern;
2604 	parameter_reference *param;
2605 
2606 	if (zend_parse_parameters_none() == FAILURE) {
2607 		return;
2608 	}
2609 	GET_REFLECTION_OBJECT_PTR(param);
2610 
2611 	RETVAL_BOOL(ZEND_TYPE_CODE(param->arg_info->type) == IS_ARRAY);
2612 }
2613 /* }}} */
2614 
2615 /* {{{ proto public bool ReflectionParameter::isCallable()
2616    Returns whether parameter MUST be callable */
ZEND_METHOD(reflection_parameter,isCallable)2617 ZEND_METHOD(reflection_parameter, isCallable)
2618 {
2619 	reflection_object *intern;
2620 	parameter_reference *param;
2621 
2622 	if (zend_parse_parameters_none() == FAILURE) {
2623 		return;
2624 	}
2625 	GET_REFLECTION_OBJECT_PTR(param);
2626 
2627 	RETVAL_BOOL(ZEND_TYPE_CODE(param->arg_info->type) == IS_CALLABLE);
2628 }
2629 /* }}} */
2630 
2631 /* {{{ proto public bool ReflectionParameter::allowsNull()
2632    Returns whether NULL is allowed as this parameters's value */
ZEND_METHOD(reflection_parameter,allowsNull)2633 ZEND_METHOD(reflection_parameter, allowsNull)
2634 {
2635 	reflection_object *intern;
2636 	parameter_reference *param;
2637 
2638 	if (zend_parse_parameters_none() == FAILURE) {
2639 		return;
2640 	}
2641 	GET_REFLECTION_OBJECT_PTR(param);
2642 
2643 	RETVAL_BOOL(ZEND_TYPE_ALLOW_NULL(param->arg_info->type));
2644 }
2645 /* }}} */
2646 
2647 /* {{{ proto public bool ReflectionParameter::isPassedByReference()
2648    Returns whether this parameters is passed to by reference */
ZEND_METHOD(reflection_parameter,isPassedByReference)2649 ZEND_METHOD(reflection_parameter, isPassedByReference)
2650 {
2651 	reflection_object *intern;
2652 	parameter_reference *param;
2653 
2654 	if (zend_parse_parameters_none() == FAILURE) {
2655 		return;
2656 	}
2657 	GET_REFLECTION_OBJECT_PTR(param);
2658 
2659 	RETVAL_BOOL(param->arg_info->pass_by_reference);
2660 }
2661 /* }}} */
2662 
2663 /* {{{ proto public bool ReflectionParameter::canBePassedByValue()
2664    Returns whether this parameter can be passed by value */
ZEND_METHOD(reflection_parameter,canBePassedByValue)2665 ZEND_METHOD(reflection_parameter, canBePassedByValue)
2666 {
2667 	reflection_object *intern;
2668 	parameter_reference *param;
2669 
2670 	if (zend_parse_parameters_none() == FAILURE) {
2671 		return;
2672 	}
2673 	GET_REFLECTION_OBJECT_PTR(param);
2674 
2675 	/* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */
2676 	RETVAL_BOOL(param->arg_info->pass_by_reference != ZEND_SEND_BY_REF);
2677 }
2678 /* }}} */
2679 
2680 /* {{{ proto public bool ReflectionParameter::getPosition()
2681    Returns whether this parameter is an optional parameter */
ZEND_METHOD(reflection_parameter,getPosition)2682 ZEND_METHOD(reflection_parameter, getPosition)
2683 {
2684 	reflection_object *intern;
2685 	parameter_reference *param;
2686 
2687 	if (zend_parse_parameters_none() == FAILURE) {
2688 		return;
2689 	}
2690 	GET_REFLECTION_OBJECT_PTR(param);
2691 
2692 	RETVAL_LONG(param->offset);
2693 }
2694 /* }}} */
2695 
2696 /* {{{ proto public bool ReflectionParameter::isOptional()
2697    Returns whether this parameter is an optional parameter */
ZEND_METHOD(reflection_parameter,isOptional)2698 ZEND_METHOD(reflection_parameter, isOptional)
2699 {
2700 	reflection_object *intern;
2701 	parameter_reference *param;
2702 
2703 	if (zend_parse_parameters_none() == FAILURE) {
2704 		return;
2705 	}
2706 	GET_REFLECTION_OBJECT_PTR(param);
2707 
2708 	RETVAL_BOOL(!param->required);
2709 }
2710 /* }}} */
2711 
2712 /* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
2713    Returns whether the default value of this parameter is available */
ZEND_METHOD(reflection_parameter,isDefaultValueAvailable)2714 ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
2715 {
2716 	reflection_object *intern;
2717 	parameter_reference *param;
2718 	zend_op *precv;
2719 
2720 	if (zend_parse_parameters_none() == FAILURE) {
2721 		return;
2722 	}
2723 	GET_REFLECTION_OBJECT_PTR(param);
2724 
2725 	if (param->fptr->type != ZEND_USER_FUNCTION)
2726 	{
2727 		RETURN_FALSE;
2728 	}
2729 
2730 	precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
2731 	if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
2732 		RETURN_FALSE;
2733 	}
2734 	RETURN_TRUE;
2735 }
2736 /* }}} */
2737 
2738 /* {{{ proto public bool ReflectionParameter::getDefaultValue()
2739    Returns the default value of this parameter or throws an exception */
ZEND_METHOD(reflection_parameter,getDefaultValue)2740 ZEND_METHOD(reflection_parameter, getDefaultValue)
2741 {
2742 	parameter_reference *param;
2743 	zend_op *precv;
2744 
2745 	if (zend_parse_parameters_none() == FAILURE) {
2746 		return;
2747 	}
2748 
2749 	param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2750 	if (!param) {
2751 		return;
2752 	}
2753 
2754 	precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2755 	if (!precv) {
2756 		return;
2757 	}
2758 
2759 	ZVAL_COPY(return_value, RT_CONSTANT(precv, precv->op2));
2760 	if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
2761 		zval_update_constant_ex(return_value, param->fptr->common.scope);
2762 	}
2763 }
2764 /* }}} */
2765 
2766 /* {{{ proto public bool ReflectionParameter::isDefaultValueConstant()
2767    Returns whether the default value of this parameter is constant */
ZEND_METHOD(reflection_parameter,isDefaultValueConstant)2768 ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
2769 {
2770 	zend_op *precv;
2771 	parameter_reference *param;
2772 
2773 	if (zend_parse_parameters_none() == FAILURE) {
2774 		return;
2775 	}
2776 
2777 	param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2778 	if (!param) {
2779 		RETURN_FALSE;
2780 	}
2781 
2782 	precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2783 	if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT_AST) {
2784 		zend_ast *ast = Z_ASTVAL_P(RT_CONSTANT(precv, precv->op2));
2785 
2786 		if (ast->kind == ZEND_AST_CONSTANT
2787 		 || ast->kind == ZEND_AST_CONSTANT_CLASS) {
2788 			RETURN_TRUE;
2789 		}
2790 	}
2791 
2792 	RETURN_FALSE;
2793 }
2794 /* }}} */
2795 
2796 /* {{{ proto public mixed ReflectionParameter::getDefaultValueConstantName()
2797    Returns the default value's constant name if default value is constant or null */
ZEND_METHOD(reflection_parameter,getDefaultValueConstantName)2798 ZEND_METHOD(reflection_parameter, getDefaultValueConstantName)
2799 {
2800 	zend_op *precv;
2801 	parameter_reference *param;
2802 
2803 	if (zend_parse_parameters_none() == FAILURE) {
2804 		return;
2805 	}
2806 
2807 	param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2808 	if (!param) {
2809 		return;
2810 	}
2811 
2812 	precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2813 	if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT_AST) {
2814 		zend_ast *ast = Z_ASTVAL_P(RT_CONSTANT(precv, precv->op2));
2815 
2816 		if (ast->kind == ZEND_AST_CONSTANT) {
2817 			RETURN_STR_COPY(zend_ast_get_constant_name(ast));
2818 		} else if (ast->kind == ZEND_AST_CONSTANT_CLASS) {
2819 			RETURN_STRINGL("__CLASS__", sizeof("__CLASS__")-1);
2820 		}
2821 	}
2822 }
2823 /* }}} */
2824 
2825 /* {{{ proto public bool ReflectionParameter::isVariadic()
2826    Returns whether this parameter is a variadic parameter */
ZEND_METHOD(reflection_parameter,isVariadic)2827 ZEND_METHOD(reflection_parameter, isVariadic)
2828 {
2829 	reflection_object *intern;
2830 	parameter_reference *param;
2831 
2832 	if (zend_parse_parameters_none() == FAILURE) {
2833 		return;
2834 	}
2835 	GET_REFLECTION_OBJECT_PTR(param);
2836 
2837 	RETVAL_BOOL(param->arg_info->is_variadic);
2838 }
2839 /* }}} */
2840 
2841 /* {{{ proto public bool ReflectionType::allowsNull()
2842   Returns whether parameter MAY be null */
ZEND_METHOD(reflection_type,allowsNull)2843 ZEND_METHOD(reflection_type, allowsNull)
2844 {
2845 	reflection_object *intern;
2846 	type_reference *param;
2847 
2848 	if (zend_parse_parameters_none() == FAILURE) {
2849 		return;
2850 	}
2851 	GET_REFLECTION_OBJECT_PTR(param);
2852 
2853 	RETVAL_BOOL(ZEND_TYPE_ALLOW_NULL(param->type));
2854 }
2855 /* }}} */
2856 
2857 /* {{{ proto public bool ReflectionType::isBuiltin()
2858   Returns whether parameter is a builtin type */
ZEND_METHOD(reflection_type,isBuiltin)2859 ZEND_METHOD(reflection_type, isBuiltin)
2860 {
2861 	reflection_object *intern;
2862 	type_reference *param;
2863 
2864 	if (zend_parse_parameters_none() == FAILURE) {
2865 		return;
2866 	}
2867 	GET_REFLECTION_OBJECT_PTR(param);
2868 
2869 	RETVAL_BOOL(ZEND_TYPE_IS_CODE(param->type));
2870 }
2871 /* }}} */
2872 
2873 /* {{{ reflection_type_name */
reflection_type_name(type_reference * param)2874 static zend_string *reflection_type_name(type_reference *param) {
2875 	if (ZEND_TYPE_IS_NAME(param->type)) {
2876 		return zend_string_copy(ZEND_TYPE_NAME(param->type));
2877 	} else if (ZEND_TYPE_IS_CE(param->type)) {
2878 		return zend_string_copy(ZEND_TYPE_CE(param->type)->name);
2879 	} else {
2880 		char *name = zend_get_type_by_const(ZEND_TYPE_CODE(param->type));
2881 		return zend_string_init(name, strlen(name), 0);
2882 	}
2883 }
2884 /* }}} */
2885 
2886 /* {{{ proto public string ReflectionType::__toString()
2887    Return the text of the type hint */
ZEND_METHOD(reflection_type,__toString)2888 ZEND_METHOD(reflection_type, __toString)
2889 {
2890 	reflection_object *intern;
2891 	type_reference *param;
2892 
2893 	if (zend_parse_parameters_none() == FAILURE) {
2894 		return;
2895 	}
2896 	GET_REFLECTION_OBJECT_PTR(param);
2897 
2898 	RETURN_STR(reflection_type_name(param));
2899 }
2900 /* }}} */
2901 
2902 /* {{{ proto public string ReflectionNamedType::getName()
2903  Return the text of the type hint */
ZEND_METHOD(reflection_named_type,getName)2904 ZEND_METHOD(reflection_named_type, getName)
2905 {
2906 	reflection_object *intern;
2907 	type_reference *param;
2908 
2909 	if (zend_parse_parameters_none() == FAILURE) {
2910 		return;
2911 	}
2912 	GET_REFLECTION_OBJECT_PTR(param);
2913 
2914 	RETURN_STR(reflection_type_name(param));
2915 }
2916 /* }}} */
2917 
2918 /* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException
2919    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_method,export)2920 ZEND_METHOD(reflection_method, export)
2921 {
2922 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_method_ptr, 2);
2923 }
2924 /* }}} */
2925 
2926 /* {{{ proto public void ReflectionMethod::__construct(mixed class_or_method [, string name])
2927    Constructor. Throws an Exception in case the given method does not exist */
ZEND_METHOD(reflection_method,__construct)2928 ZEND_METHOD(reflection_method, __construct)
2929 {
2930 	zval *classname;
2931 	zval *object, *orig_obj;
2932 	reflection_object *intern;
2933 	char *lcname;
2934 	zend_class_entry *ce;
2935 	zend_function *mptr;
2936 	char *name_str, *tmp;
2937 	size_t name_len, tmp_len;
2938 	zval ztmp;
2939 
2940 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "zs", &classname, &name_str, &name_len) == FAILURE) {
2941 		if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
2942 			return;
2943 		}
2944 
2945 		if ((tmp = strstr(name_str, "::")) == NULL) {
2946 			zend_throw_exception_ex(reflection_exception_ptr, 0,
2947 				"Invalid method name %s", name_str);
2948 			return;
2949 		}
2950 		classname = &ztmp;
2951 		tmp_len = tmp - name_str;
2952 		ZVAL_STRINGL(classname, name_str, tmp_len);
2953 		name_len = name_len - (tmp_len + 2);
2954 		name_str = tmp + 2;
2955 		orig_obj = NULL;
2956 	} else if (Z_TYPE_P(classname) == IS_OBJECT) {
2957 		orig_obj = classname;
2958 	} else {
2959 		orig_obj = NULL;
2960 	}
2961 
2962 	object = ZEND_THIS;
2963 	intern = Z_REFLECTION_P(object);
2964 
2965 	/* Find the class entry */
2966 	switch (Z_TYPE_P(classname)) {
2967 		case IS_STRING:
2968 			if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
2969 				if (!EG(exception)) {
2970 					zend_throw_exception_ex(reflection_exception_ptr, 0,
2971 							"Class %s does not exist", Z_STRVAL_P(classname));
2972 				}
2973 				if (classname == &ztmp) {
2974 					zval_ptr_dtor_str(&ztmp);
2975 				}
2976 				return;
2977 			}
2978 			break;
2979 
2980 		case IS_OBJECT:
2981 			ce = Z_OBJCE_P(classname);
2982 			break;
2983 
2984 		default:
2985 			if (classname == &ztmp) {
2986 				zval_ptr_dtor_str(&ztmp);
2987 			}
2988 			_DO_THROW("The parameter class is expected to be either a string or an object");
2989 			return;
2990 	}
2991 
2992 	if (classname == &ztmp) {
2993 		zval_ptr_dtor_str(&ztmp);
2994 	}
2995 
2996 	lcname = zend_str_tolower_dup(name_str, name_len);
2997 
2998 	if (ce == zend_ce_closure && orig_obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
2999 		&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
3000 		&& (mptr = zend_get_closure_invoke_method(Z_OBJ_P(orig_obj))) != NULL)
3001 	{
3002 		/* do nothing, mptr already set */
3003 	} else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, name_len)) == NULL) {
3004 		efree(lcname);
3005 		zend_throw_exception_ex(reflection_exception_ptr, 0,
3006 			"Method %s::%s() does not exist", ZSTR_VAL(ce->name), name_str);
3007 		return;
3008 	}
3009 	efree(lcname);
3010 
3011 	ZVAL_STR_COPY(reflection_prop_name(object), mptr->common.function_name);
3012 	ZVAL_STR_COPY(reflection_prop_class(object), mptr->common.scope->name);
3013 	intern->ptr = mptr;
3014 	intern->ref_type = REF_TYPE_FUNCTION;
3015 	intern->ce = ce;
3016 }
3017 /* }}} */
3018 
3019 /* {{{ proto public string ReflectionMethod::__toString()
3020    Returns a string representation */
ZEND_METHOD(reflection_method,__toString)3021 ZEND_METHOD(reflection_method, __toString)
3022 {
3023 	reflection_object *intern;
3024 	zend_function *mptr;
3025 	smart_str str = {0};
3026 
3027 	if (zend_parse_parameters_none() == FAILURE) {
3028 		return;
3029 	}
3030 	GET_REFLECTION_OBJECT_PTR(mptr);
3031 	_function_string(&str, mptr, intern->ce, "");
3032 	RETURN_STR(smart_str_extract(&str));
3033 }
3034 /* }}} */
3035 
3036 /* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
3037    Invokes the function */
ZEND_METHOD(reflection_method,getClosure)3038 ZEND_METHOD(reflection_method, getClosure)
3039 {
3040 	reflection_object *intern;
3041 	zval *obj;
3042 	zend_function *mptr;
3043 
3044 	GET_REFLECTION_OBJECT_PTR(mptr);
3045 
3046 	if (mptr->common.fn_flags & ZEND_ACC_STATIC)  {
3047 		zend_create_fake_closure(return_value, mptr, mptr->common.scope, mptr->common.scope, NULL);
3048 	} else {
3049 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
3050 			return;
3051 		}
3052 
3053 		if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope)) {
3054 			_DO_THROW("Given object is not an instance of the class this method was declared in");
3055 			return;
3056 		}
3057 
3058 		/* This is an original closure object and __invoke is to be called. */
3059 		if (Z_OBJCE_P(obj) == zend_ce_closure &&
3060 			(mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
3061 		{
3062 			Z_ADDREF_P(obj);
3063 			ZVAL_OBJ(return_value, Z_OBJ_P(obj));
3064 		} else {
3065 			zend_create_fake_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj);
3066 		}
3067 	}
3068 }
3069 /* }}} */
3070 
3071 /* {{{ reflection_method_invoke */
reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS,int variadic)3072 static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic)
3073 {
3074 	zval retval;
3075 	zval *params = NULL, *val, *object;
3076 	reflection_object *intern;
3077 	zend_function *mptr;
3078 	int i, argc = 0, result;
3079 	zend_fcall_info fci;
3080 	zend_fcall_info_cache fcc;
3081 	zend_class_entry *obj_ce;
3082 	zval *param_array;
3083 
3084 	GET_REFLECTION_OBJECT_PTR(mptr);
3085 
3086 	if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
3087 		zend_throw_exception_ex(reflection_exception_ptr, 0,
3088 			"Trying to invoke abstract method %s::%s()",
3089 			ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3090 		return;
3091 	}
3092 
3093 	if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
3094 		zend_throw_exception_ex(reflection_exception_ptr, 0,
3095 			"Trying to invoke %s method %s::%s() from scope %s",
3096 			mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
3097 			ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name),
3098 			ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
3099 		return;
3100 	}
3101 
3102 	if (variadic) {
3103 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!*", &object, &params, &argc) == FAILURE) {
3104 			return;
3105 		}
3106 	} else {
3107 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", &object, &param_array) == FAILURE) {
3108 			return;
3109 		}
3110 
3111 		argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
3112 
3113 		params = safe_emalloc(sizeof(zval), argc, 0);
3114 		argc = 0;
3115 		ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
3116 			ZVAL_COPY(&params[argc], val);
3117 			argc++;
3118 		} ZEND_HASH_FOREACH_END();
3119 	}
3120 
3121 	/* In case this is a static method, we shouldn't pass an object_ptr
3122 	 * (which is used as calling context aka $this). We can thus ignore the
3123 	 * first parameter.
3124 	 *
3125 	 * Else, we verify that the given object is an instance of the class.
3126 	 */
3127 	if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3128 		object = NULL;
3129 		obj_ce = mptr->common.scope;
3130 	} else {
3131 		if (!object) {
3132 			zend_throw_exception_ex(reflection_exception_ptr, 0,
3133 				"Trying to invoke non static method %s::%s() without an object",
3134 				ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3135 			return;
3136 		}
3137 
3138 		obj_ce = Z_OBJCE_P(object);
3139 
3140 		if (!instanceof_function(obj_ce, mptr->common.scope)) {
3141 			if (!variadic) {
3142 				efree(params);
3143 			}
3144 			_DO_THROW("Given object is not an instance of the class this method was declared in");
3145 			return;
3146 		}
3147 	}
3148 
3149 	fci.size = sizeof(fci);
3150 	ZVAL_UNDEF(&fci.function_name);
3151 	fci.object = object ? Z_OBJ_P(object) : NULL;
3152 	fci.retval = &retval;
3153 	fci.param_count = argc;
3154 	fci.params = params;
3155 	fci.no_separation = 1;
3156 
3157 	fcc.function_handler = mptr;
3158 	fcc.called_scope = intern->ce;
3159 	fcc.object = object ? Z_OBJ_P(object) : NULL;
3160 
3161 	/*
3162 	 * Copy the zend_function when calling via handler (e.g. Closure::__invoke())
3163 	 */
3164 	if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
3165 		fcc.function_handler = _copy_function(mptr);
3166 	}
3167 
3168 	result = zend_call_function(&fci, &fcc);
3169 
3170 	if (!variadic) {
3171 		for (i = 0; i < argc; i++) {
3172 			zval_ptr_dtor(&params[i]);
3173 		}
3174 		efree(params);
3175 	}
3176 
3177 	if (result == FAILURE) {
3178 		zend_throw_exception_ex(reflection_exception_ptr, 0,
3179 			"Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3180 		return;
3181 	}
3182 
3183 	if (Z_TYPE(retval) != IS_UNDEF) {
3184 		if (Z_ISREF(retval)) {
3185 			zend_unwrap_reference(&retval);
3186 		}
3187 		ZVAL_COPY_VALUE(return_value, &retval);
3188 	}
3189 }
3190 /* }}} */
3191 
3192 /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
3193    Invokes the method. */
ZEND_METHOD(reflection_method,invoke)3194 ZEND_METHOD(reflection_method, invoke)
3195 {
3196 	reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3197 }
3198 /* }}} */
3199 
3200 /* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
3201    Invokes the function and pass its arguments as array. */
ZEND_METHOD(reflection_method,invokeArgs)3202 ZEND_METHOD(reflection_method, invokeArgs)
3203 {
3204 	reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3205 }
3206 /* }}} */
3207 
3208 /* {{{ proto public bool ReflectionMethod::isFinal()
3209    Returns whether this method is final */
ZEND_METHOD(reflection_method,isFinal)3210 ZEND_METHOD(reflection_method, isFinal)
3211 {
3212 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
3213 }
3214 /* }}} */
3215 
3216 /* {{{ proto public bool ReflectionMethod::isAbstract()
3217    Returns whether this method is abstract */
ZEND_METHOD(reflection_method,isAbstract)3218 ZEND_METHOD(reflection_method, isAbstract)
3219 {
3220 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ABSTRACT);
3221 }
3222 /* }}} */
3223 
3224 /* {{{ proto public bool ReflectionMethod::isPublic()
3225    Returns whether this method is public */
ZEND_METHOD(reflection_method,isPublic)3226 ZEND_METHOD(reflection_method, isPublic)
3227 {
3228 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
3229 }
3230 /* }}} */
3231 
3232 /* {{{ proto public bool ReflectionMethod::isPrivate()
3233    Returns whether this method is private */
ZEND_METHOD(reflection_method,isPrivate)3234 ZEND_METHOD(reflection_method, isPrivate)
3235 {
3236 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
3237 }
3238 /* }}} */
3239 
3240 /* {{{ proto public bool ReflectionMethod::isProtected()
3241    Returns whether this method is protected */
ZEND_METHOD(reflection_method,isProtected)3242 ZEND_METHOD(reflection_method, isProtected)
3243 {
3244 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
3245 }
3246 /* }}} */
3247 
3248 /* {{{ proto public bool ReflectionMethod::isStatic()
3249    Returns whether this method is static */
ZEND_METHOD(reflection_method,isStatic)3250 ZEND_METHOD(reflection_method, isStatic)
3251 {
3252 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
3253 }
3254 /* }}} */
3255 
3256 /* {{{ proto public bool ReflectionFunction::isDeprecated()
3257    Returns whether this function is deprecated */
ZEND_METHOD(reflection_function,isDeprecated)3258 ZEND_METHOD(reflection_function, isDeprecated)
3259 {
3260 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_DEPRECATED);
3261 }
3262 /* }}} */
3263 
3264 /* {{{ proto public bool ReflectionFunction::isGenerator()
3265    Returns whether this function is a generator */
ZEND_METHOD(reflection_function,isGenerator)3266 ZEND_METHOD(reflection_function, isGenerator)
3267 {
3268 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_GENERATOR);
3269 }
3270 /* }}} */
3271 
3272 /* {{{ proto public bool ReflectionFunction::isVariadic()
3273    Returns whether this function is variadic */
ZEND_METHOD(reflection_function,isVariadic)3274 ZEND_METHOD(reflection_function, isVariadic)
3275 {
3276 	_function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_VARIADIC);
3277 }
3278 /* }}} */
3279 
3280 /* {{{ proto public bool ReflectionFunction::inNamespace()
3281    Returns whether this function is defined in namespace */
ZEND_METHOD(reflection_function,inNamespace)3282 ZEND_METHOD(reflection_function, inNamespace)
3283 {
3284 	zval *name;
3285 	const char *backslash;
3286 
3287 	if (zend_parse_parameters_none() == FAILURE) {
3288 		return;
3289 	}
3290 	if ((name = _default_load_name(ZEND_THIS)) == NULL) {
3291 		RETURN_FALSE;
3292 	}
3293 	if (Z_TYPE_P(name) == IS_STRING
3294 		&& (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3295 		&& backslash > Z_STRVAL_P(name))
3296 	{
3297 		RETURN_TRUE;
3298 	}
3299 	RETURN_FALSE;
3300 }
3301 /* }}} */
3302 
3303 /* {{{ proto public string ReflectionFunction::getNamespaceName()
3304    Returns the name of namespace where this function is defined */
ZEND_METHOD(reflection_function,getNamespaceName)3305 ZEND_METHOD(reflection_function, getNamespaceName)
3306 {
3307 	zval *name;
3308 	const char *backslash;
3309 
3310 	if (zend_parse_parameters_none() == FAILURE) {
3311 		return;
3312 	}
3313 	if ((name = _default_load_name(ZEND_THIS)) == NULL) {
3314 		RETURN_FALSE;
3315 	}
3316 	if (Z_TYPE_P(name) == IS_STRING
3317 		&& (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3318 		&& backslash > Z_STRVAL_P(name))
3319 	{
3320 		RETURN_STRINGL(Z_STRVAL_P(name), backslash - Z_STRVAL_P(name));
3321 	}
3322 	RETURN_EMPTY_STRING();
3323 }
3324 /* }}} */
3325 
3326 /* {{{ proto public string ReflectionFunction::getShortName()
3327    Returns the short name of the function (without namespace part) */
ZEND_METHOD(reflection_function,getShortName)3328 ZEND_METHOD(reflection_function, getShortName)
3329 {
3330 	zval *name;
3331 	const char *backslash;
3332 
3333 	if (zend_parse_parameters_none() == FAILURE) {
3334 		return;
3335 	}
3336 	if ((name = _default_load_name(ZEND_THIS)) == NULL) {
3337 		RETURN_FALSE;
3338 	}
3339 	if (Z_TYPE_P(name) == IS_STRING
3340 		&& (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3341 		&& backslash > Z_STRVAL_P(name))
3342 	{
3343 		RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
3344 	}
3345 	ZVAL_COPY_DEREF(return_value, name);
3346 }
3347 /* }}} */
3348 
3349 /* {{{ proto public bool ReflectionFunctionAbstract:hasReturnType()
3350    Return whether the function has a return type */
ZEND_METHOD(reflection_function,hasReturnType)3351 ZEND_METHOD(reflection_function, hasReturnType)
3352 {
3353 	reflection_object *intern;
3354 	zend_function *fptr;
3355 
3356 	if (zend_parse_parameters_none() == FAILURE) {
3357 		return;
3358 	}
3359 
3360 	GET_REFLECTION_OBJECT_PTR(fptr);
3361 
3362 	RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
3363 }
3364 /* }}} */
3365 
3366 /* {{{ proto public string ReflectionFunctionAbstract::getReturnType()
3367    Returns the return type associated with the function */
ZEND_METHOD(reflection_function,getReturnType)3368 ZEND_METHOD(reflection_function, getReturnType)
3369 {
3370 	reflection_object *intern;
3371 	zend_function *fptr;
3372 
3373 	if (zend_parse_parameters_none() == FAILURE) {
3374 		return;
3375 	}
3376 
3377 	GET_REFLECTION_OBJECT_PTR(fptr);
3378 
3379 	if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
3380 		RETURN_NULL();
3381 	}
3382 
3383 	reflection_type_factory(fptr->common.arg_info[-1].type, return_value);
3384 }
3385 /* }}} */
3386 
3387 /* {{{ proto public bool ReflectionMethod::isConstructor()
3388    Returns whether this method is the constructor */
ZEND_METHOD(reflection_method,isConstructor)3389 ZEND_METHOD(reflection_method, isConstructor)
3390 {
3391 	reflection_object *intern;
3392 	zend_function *mptr;
3393 
3394 	if (zend_parse_parameters_none() == FAILURE) {
3395 		return;
3396 	}
3397 	GET_REFLECTION_OBJECT_PTR(mptr);
3398 	/* we need to check if the ctor is the ctor of the class level we we
3399 	 * looking at since we might be looking at an inherited old style ctor
3400 	 * defined in base class. */
3401 	RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
3402 }
3403 /* }}} */
3404 
3405 /* {{{ proto public bool ReflectionMethod::isDestructor()
3406    Returns whether this method is static */
ZEND_METHOD(reflection_method,isDestructor)3407 ZEND_METHOD(reflection_method, isDestructor)
3408 {
3409 	reflection_object *intern;
3410 	zend_function *mptr;
3411 
3412 	if (zend_parse_parameters_none() == FAILURE) {
3413 		return;
3414 	}
3415 	GET_REFLECTION_OBJECT_PTR(mptr);
3416 	RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR);
3417 }
3418 /* }}} */
3419 
3420 /* {{{ proto public int ReflectionMethod::getModifiers()
3421    Returns a bitfield of the access modifiers for this method */
ZEND_METHOD(reflection_method,getModifiers)3422 ZEND_METHOD(reflection_method, getModifiers)
3423 {
3424 	reflection_object *intern;
3425 	zend_function *mptr;
3426 	uint32_t keep_flags = ZEND_ACC_PPP_MASK
3427 		| ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL;
3428 
3429 	if (zend_parse_parameters_none() == FAILURE) {
3430 		return;
3431 	}
3432 	GET_REFLECTION_OBJECT_PTR(mptr);
3433 
3434 	RETURN_LONG((mptr->common.fn_flags & keep_flags));
3435 }
3436 /* }}} */
3437 
3438 /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
3439    Get the declaring class */
ZEND_METHOD(reflection_method,getDeclaringClass)3440 ZEND_METHOD(reflection_method, getDeclaringClass)
3441 {
3442 	reflection_object *intern;
3443 	zend_function *mptr;
3444 
3445 	GET_REFLECTION_OBJECT_PTR(mptr);
3446 
3447 	if (zend_parse_parameters_none() == FAILURE) {
3448 		return;
3449 	}
3450 
3451 	zend_reflection_class_factory(mptr->common.scope, return_value);
3452 }
3453 /* }}} */
3454 
3455 /* {{{ proto public ReflectionClass ReflectionMethod::getPrototype()
3456    Get the prototype */
ZEND_METHOD(reflection_method,getPrototype)3457 ZEND_METHOD(reflection_method, getPrototype)
3458 {
3459 	reflection_object *intern;
3460 	zend_function *mptr;
3461 
3462 	GET_REFLECTION_OBJECT_PTR(mptr);
3463 
3464 	if (zend_parse_parameters_none() == FAILURE) {
3465 		return;
3466 	}
3467 
3468 	if (!mptr->common.prototype) {
3469 		zend_throw_exception_ex(reflection_exception_ptr, 0,
3470 			"Method %s::%s does not have a prototype", ZSTR_VAL(intern->ce->name), ZSTR_VAL(mptr->common.function_name));
3471 		return;
3472 	}
3473 
3474 	reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value);
3475 }
3476 /* }}} */
3477 
3478 /* {{{ proto public void ReflectionMethod::setAccessible(bool visible)
3479    Sets whether non-public methods can be invoked */
ZEND_METHOD(reflection_method,setAccessible)3480 ZEND_METHOD(reflection_method, setAccessible)
3481 {
3482 	reflection_object *intern;
3483 	zend_bool visible;
3484 
3485 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
3486 		return;
3487 	}
3488 
3489 	intern = Z_REFLECTION_P(ZEND_THIS);
3490 
3491 	intern->ignore_visibility = visible;
3492 }
3493 /* }}} */
3494 
3495 /* {{{ proto public void ReflectionClassConstant::__construct(mixed class, string name)
3496    Constructor. Throws an Exception in case the given class constant does not exist */
ZEND_METHOD(reflection_class_constant,__construct)3497 ZEND_METHOD(reflection_class_constant, __construct)
3498 {
3499 	zval *classname, *object;
3500 	zend_string *constname;
3501 	reflection_object *intern;
3502 	zend_class_entry *ce;
3503 	zend_class_constant *constant = NULL;
3504 
3505 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zS", &classname, &constname) == FAILURE) {
3506 		return;
3507 	}
3508 
3509 	object = ZEND_THIS;
3510 	intern = Z_REFLECTION_P(object);
3511 
3512 	/* Find the class entry */
3513 	switch (Z_TYPE_P(classname)) {
3514 		case IS_STRING:
3515 			if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
3516 				zend_throw_exception_ex(reflection_exception_ptr, 0,
3517 						"Class %s does not exist", Z_STRVAL_P(classname));
3518 				return;
3519 			}
3520 			break;
3521 
3522 		case IS_OBJECT:
3523 			ce = Z_OBJCE_P(classname);
3524 			break;
3525 
3526 		default:
3527 			_DO_THROW("The parameter class is expected to be either a string or an object");
3528 			return;
3529 	}
3530 
3531 	if ((constant = zend_hash_find_ptr(&ce->constants_table, constname)) == NULL) {
3532 		zend_throw_exception_ex(reflection_exception_ptr, 0, "Class Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
3533 		return;
3534 	}
3535 
3536 	intern->ptr = constant;
3537 	intern->ref_type = REF_TYPE_CLASS_CONSTANT;
3538 	intern->ce = constant->ce;
3539 	intern->ignore_visibility = 0;
3540 	ZVAL_STR_COPY(reflection_prop_name(object), constname);
3541 	ZVAL_STR_COPY(reflection_prop_class(object), ce->name);
3542 }
3543 /* }}} */
3544 
3545 /* {{{ proto public string ReflectionClassConstant::__toString()
3546    Returns a string representation */
ZEND_METHOD(reflection_class_constant,__toString)3547 ZEND_METHOD(reflection_class_constant, __toString)
3548 {
3549 	reflection_object *intern;
3550 	zend_class_constant *ref;
3551 	smart_str str = {0};
3552 	zval name;
3553 
3554 	if (zend_parse_parameters_none() == FAILURE) {
3555 		return;
3556 	}
3557 	GET_REFLECTION_OBJECT_PTR(ref);
3558 	_default_get_name(ZEND_THIS, &name);
3559 	_class_const_string(&str, Z_STRVAL(name), ref, "");
3560 	zval_ptr_dtor(&name);
3561 	RETURN_STR(smart_str_extract(&str));
3562 }
3563 /* }}} */
3564 
3565 /* {{{ proto public string ReflectionClassConstant::getName()
3566    Returns the constant' name */
ZEND_METHOD(reflection_class_constant,getName)3567 ZEND_METHOD(reflection_class_constant, getName)
3568 {
3569 	if (zend_parse_parameters_none() == FAILURE) {
3570 		return;
3571 	}
3572 	_default_get_name(ZEND_THIS, return_value);
3573 }
3574 /* }}} */
3575 
_class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)3576 static void _class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
3577 {
3578 	reflection_object *intern;
3579 	zend_class_constant *ref;
3580 
3581 	if (zend_parse_parameters_none() == FAILURE) {
3582 		return;
3583 	}
3584 	GET_REFLECTION_OBJECT_PTR(ref);
3585 	RETURN_BOOL(Z_ACCESS_FLAGS(ref->value) & mask);
3586 }
3587 /* }}} */
3588 
3589 /* {{{ proto public bool ReflectionClassConstant::isPublic()
3590    Returns whether this constant is public */
ZEND_METHOD(reflection_class_constant,isPublic)3591 ZEND_METHOD(reflection_class_constant, isPublic)
3592 {
3593 	_class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
3594 }
3595 /* }}} */
3596 
3597 /* {{{ proto public bool ReflectionClassConstant::isPrivate()
3598    Returns whether this constant is private */
ZEND_METHOD(reflection_class_constant,isPrivate)3599 ZEND_METHOD(reflection_class_constant, isPrivate)
3600 {
3601 	_class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
3602 }
3603 /* }}} */
3604 
3605 /* {{{ proto public bool ReflectionClassConstant::isProtected()
3606    Returns whether this constant is protected */
ZEND_METHOD(reflection_class_constant,isProtected)3607 ZEND_METHOD(reflection_class_constant, isProtected)
3608 {
3609 	_class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
3610 }
3611 /* }}} */
3612 
3613 /* {{{ proto public int ReflectionClassConstant::getModifiers()
3614    Returns a bitfield of the access modifiers for this constant */
ZEND_METHOD(reflection_class_constant,getModifiers)3615 ZEND_METHOD(reflection_class_constant, getModifiers)
3616 {
3617 	reflection_object *intern;
3618 	zend_class_constant *ref;
3619 
3620 	if (zend_parse_parameters_none() == FAILURE) {
3621 		return;
3622 	}
3623 	GET_REFLECTION_OBJECT_PTR(ref);
3624 
3625 	RETURN_LONG(Z_ACCESS_FLAGS(ref->value));
3626 }
3627 /* }}} */
3628 
3629 /* {{{ proto public mixed ReflectionClassConstant::getValue()
3630    Returns this constant's value */
ZEND_METHOD(reflection_class_constant,getValue)3631 ZEND_METHOD(reflection_class_constant, getValue)
3632 {
3633 	reflection_object *intern;
3634 	zend_class_constant *ref;
3635 
3636 	if (zend_parse_parameters_none() == FAILURE) {
3637 		return;
3638 	}
3639 	GET_REFLECTION_OBJECT_PTR(ref);
3640 
3641 	ZVAL_COPY_OR_DUP(return_value, &ref->value);
3642 	if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
3643 		zval_update_constant_ex(return_value, ref->ce);
3644 	}
3645 }
3646 /* }}} */
3647 
3648 /* {{{ proto public ReflectionClass ReflectionClassConstant::getDeclaringClass()
3649    Get the declaring class */
ZEND_METHOD(reflection_class_constant,getDeclaringClass)3650 ZEND_METHOD(reflection_class_constant, getDeclaringClass)
3651 {
3652 	reflection_object *intern;
3653 	zend_class_constant *ref;
3654 
3655 	if (zend_parse_parameters_none() == FAILURE) {
3656 		return;
3657 	}
3658 	GET_REFLECTION_OBJECT_PTR(ref);
3659 
3660 	zend_reflection_class_factory(ref->ce, return_value);
3661 }
3662 /* }}} */
3663 
3664 /* {{{ proto public string ReflectionClassConstant::getDocComment()
3665    Returns the doc comment for this constant */
ZEND_METHOD(reflection_class_constant,getDocComment)3666 ZEND_METHOD(reflection_class_constant, getDocComment)
3667 {
3668 	reflection_object *intern;
3669 	zend_class_constant *ref;
3670 
3671 	if (zend_parse_parameters_none() == FAILURE) {
3672 		return;
3673 	}
3674 	GET_REFLECTION_OBJECT_PTR(ref);
3675 	if (ref->doc_comment) {
3676 		RETURN_STR_COPY(ref->doc_comment);
3677 	}
3678 	RETURN_FALSE;
3679 }
3680 /* }}} */
3681 
3682 /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException
3683    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class,export)3684 ZEND_METHOD(reflection_class, export)
3685 {
3686 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_ptr, 1);
3687 }
3688 /* }}} */
3689 
3690 /* {{{ reflection_class_object_ctor */
reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS,int is_object)3691 static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
3692 {
3693 	zval *argument;
3694 	zval *object;
3695 	reflection_object *intern;
3696 	zend_class_entry *ce;
3697 
3698 	if (is_object) {
3699 		ZEND_PARSE_PARAMETERS_START(1, 1)
3700 			Z_PARAM_OBJECT(argument)
3701 		ZEND_PARSE_PARAMETERS_END();
3702 	} else {
3703 		ZEND_PARSE_PARAMETERS_START(1, 1)
3704 			Z_PARAM_ZVAL(argument)
3705 		ZEND_PARSE_PARAMETERS_END();
3706 	}
3707 
3708 	object = ZEND_THIS;
3709 	intern = Z_REFLECTION_P(object);
3710 
3711 	if (Z_TYPE_P(argument) == IS_OBJECT) {
3712 		ZVAL_STR_COPY(reflection_prop_name(object), Z_OBJCE_P(argument)->name);
3713 		intern->ptr = Z_OBJCE_P(argument);
3714 		if (is_object) {
3715 			ZVAL_COPY(&intern->obj, argument);
3716 		}
3717 	} else {
3718 		if (!try_convert_to_string(argument)) {
3719 			return;
3720 		}
3721 
3722 		if ((ce = zend_lookup_class(Z_STR_P(argument))) == NULL) {
3723 			if (!EG(exception)) {
3724 				zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", Z_STRVAL_P(argument));
3725 			}
3726 			return;
3727 		}
3728 
3729 		ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
3730 		intern->ptr = ce;
3731 	}
3732 	intern->ref_type = REF_TYPE_OTHER;
3733 }
3734 /* }}} */
3735 
3736 /* {{{ proto public void ReflectionClass::__construct(mixed argument) throws ReflectionException
3737    Constructor. Takes a string or an instance as an argument */
ZEND_METHOD(reflection_class,__construct)3738 ZEND_METHOD(reflection_class, __construct)
3739 {
3740 	reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3741 }
3742 /* }}} */
3743 
3744 /* {{{ add_class_vars */
add_class_vars(zend_class_entry * ce,int statics,zval * return_value)3745 static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value)
3746 {
3747 	zend_property_info *prop_info;
3748 	zval *prop, prop_copy;
3749 	zend_string *key;
3750 
3751 	ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
3752 		if (((prop_info->flags & ZEND_ACC_PRIVATE) &&
3753 		     prop_info->ce != ce)) {
3754 			continue;
3755 		}
3756 		prop = NULL;
3757 		if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
3758 			prop = &ce->default_static_members_table[prop_info->offset];
3759 			ZVAL_DEINDIRECT(prop);
3760 		} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
3761 			prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
3762 		}
3763 		if (!prop || (prop_info->type && Z_ISUNDEF_P(prop))) {
3764 			continue;
3765 		}
3766 
3767 		/* copy: enforce read only access */
3768 		ZVAL_DEREF(prop);
3769 		ZVAL_COPY_OR_DUP(&prop_copy, prop);
3770 
3771 		/* this is necessary to make it able to work with default array
3772 		* properties, returned to user */
3773 		if (Z_TYPE(prop_copy) == IS_CONSTANT_AST) {
3774 			if (UNEXPECTED(zval_update_constant_ex(&prop_copy, ce) != SUCCESS)) {
3775 				return;
3776 			}
3777 		}
3778 
3779 		zend_hash_update(Z_ARRVAL_P(return_value), key, &prop_copy);
3780 	} ZEND_HASH_FOREACH_END();
3781 }
3782 /* }}} */
3783 
3784 /* {{{ proto public array ReflectionClass::getStaticProperties()
3785    Returns an associative array containing all static property values of the class */
ZEND_METHOD(reflection_class,getStaticProperties)3786 ZEND_METHOD(reflection_class, getStaticProperties)
3787 {
3788 	reflection_object *intern;
3789 	zend_class_entry *ce;
3790 	zend_property_info *prop_info;
3791 	zval *prop;
3792 	zend_string *key;
3793 
3794 	if (zend_parse_parameters_none() == FAILURE) {
3795 		return;
3796 	}
3797 
3798 	GET_REFLECTION_OBJECT_PTR(ce);
3799 
3800 	if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3801 		return;
3802 	}
3803 
3804 	if (ce->default_static_members_count && !CE_STATIC_MEMBERS(ce)) {
3805 		zend_class_init_statics(ce);
3806 	}
3807 
3808 	array_init(return_value);
3809 
3810 	ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
3811 		if (((prop_info->flags & ZEND_ACC_PRIVATE) &&
3812 		     prop_info->ce != ce)) {
3813 			continue;
3814 		}
3815 		if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
3816 			continue;
3817 		}
3818 
3819 		prop = &CE_STATIC_MEMBERS(ce)[prop_info->offset];
3820 		ZVAL_DEINDIRECT(prop);
3821 
3822 		if (prop_info->type && Z_ISUNDEF_P(prop)) {
3823 			continue;
3824 		}
3825 
3826 		/* enforce read only access */
3827 		ZVAL_DEREF(prop);
3828 		Z_TRY_ADDREF_P(prop);
3829 
3830 		zend_hash_update(Z_ARRVAL_P(return_value), key, prop);
3831 	} ZEND_HASH_FOREACH_END();
3832 }
3833 /* }}} */
3834 
3835 /* {{{ proto public mixed ReflectionClass::getStaticPropertyValue(string name [, mixed default])
3836    Returns the value of a static property */
ZEND_METHOD(reflection_class,getStaticPropertyValue)3837 ZEND_METHOD(reflection_class, getStaticPropertyValue)
3838 {
3839 	reflection_object *intern;
3840 	zend_class_entry *ce, *old_scope;
3841 	zend_string *name;
3842 	zval *prop, *def_value = NULL;
3843 
3844 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &name, &def_value) == FAILURE) {
3845 		return;
3846 	}
3847 
3848 	GET_REFLECTION_OBJECT_PTR(ce);
3849 
3850 	if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3851 		return;
3852 	}
3853 
3854 	old_scope = EG(fake_scope);
3855 	EG(fake_scope) = ce;
3856 	prop = zend_std_get_static_property(ce, name, BP_VAR_IS);
3857 	EG(fake_scope) = old_scope;
3858 
3859 	if (!prop) {
3860 		if (def_value) {
3861 			ZVAL_COPY(return_value, def_value);
3862 		} else {
3863 			zend_throw_exception_ex(reflection_exception_ptr, 0,
3864 				"Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3865 		}
3866 		return;
3867 	} else {
3868 		ZVAL_COPY_DEREF(return_value, prop);
3869 	}
3870 }
3871 /* }}} */
3872 
3873 /* {{{ proto public void ReflectionClass::setStaticPropertyValue(string $name, mixed $value)
3874    Sets the value of a static property */
ZEND_METHOD(reflection_class,setStaticPropertyValue)3875 ZEND_METHOD(reflection_class, setStaticPropertyValue)
3876 {
3877 	reflection_object *intern;
3878 	zend_class_entry *ce, *old_scope;
3879 	zend_property_info *prop_info;
3880 	zend_string *name;
3881 	zval *variable_ptr, *value;
3882 
3883 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &name, &value) == FAILURE) {
3884 		return;
3885 	}
3886 
3887 	GET_REFLECTION_OBJECT_PTR(ce);
3888 
3889 	if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3890 		return;
3891 	}
3892 	old_scope = EG(fake_scope);
3893 	EG(fake_scope) = ce;
3894 	variable_ptr =  zend_std_get_static_property_with_info(ce, name, BP_VAR_W, &prop_info);
3895 	EG(fake_scope) = old_scope;
3896 	if (!variable_ptr) {
3897 		zend_clear_exception();
3898 		zend_throw_exception_ex(reflection_exception_ptr, 0,
3899 				"Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3900 		return;
3901 	}
3902 
3903 	if (Z_ISREF_P(variable_ptr)) {
3904 		zend_reference *ref = Z_REF_P(variable_ptr);
3905 		variable_ptr = Z_REFVAL_P(variable_ptr);
3906 
3907 		if (!zend_verify_ref_assignable_zval(ref, value, 0)) {
3908 			return;
3909 		}
3910 	}
3911 
3912 	if (prop_info->type && !zend_verify_property_type(prop_info, value, 0)) {
3913 		return;
3914 	}
3915 
3916 	zval_ptr_dtor(variable_ptr);
3917 	ZVAL_COPY(variable_ptr, value);
3918 
3919 }
3920 /* }}} */
3921 
3922 /* {{{ proto public array ReflectionClass::getDefaultProperties()
3923    Returns an associative array containing copies of all default property values of the class */
ZEND_METHOD(reflection_class,getDefaultProperties)3924 ZEND_METHOD(reflection_class, getDefaultProperties)
3925 {
3926 	reflection_object *intern;
3927 	zend_class_entry *ce;
3928 
3929 	if (zend_parse_parameters_none() == FAILURE) {
3930 		return;
3931 	}
3932 	GET_REFLECTION_OBJECT_PTR(ce);
3933 	array_init(return_value);
3934 	if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3935 		return;
3936 	}
3937 	add_class_vars(ce, 1, return_value);
3938 	add_class_vars(ce, 0, return_value);
3939 }
3940 /* }}} */
3941 
3942 /* {{{ proto public string ReflectionClass::__toString()
3943    Returns a string representation */
ZEND_METHOD(reflection_class,__toString)3944 ZEND_METHOD(reflection_class, __toString)
3945 {
3946 	reflection_object *intern;
3947 	zend_class_entry *ce;
3948 	smart_str str = {0};
3949 
3950 	if (zend_parse_parameters_none() == FAILURE) {
3951 		return;
3952 	}
3953 	GET_REFLECTION_OBJECT_PTR(ce);
3954 	_class_string(&str, ce, &intern->obj, "");
3955 	RETURN_STR(smart_str_extract(&str));
3956 }
3957 /* }}} */
3958 
3959 /* {{{ proto public string ReflectionClass::getName()
3960    Returns the class' name */
ZEND_METHOD(reflection_class,getName)3961 ZEND_METHOD(reflection_class, getName)
3962 {
3963 	if (zend_parse_parameters_none() == FAILURE) {
3964 		return;
3965 	}
3966 	_default_get_name(ZEND_THIS, return_value);
3967 }
3968 /* }}} */
3969 
3970 /* {{{ proto public bool ReflectionClass::isInternal()
3971    Returns whether this class is an internal class */
ZEND_METHOD(reflection_class,isInternal)3972 ZEND_METHOD(reflection_class, isInternal)
3973 {
3974 	reflection_object *intern;
3975 	zend_class_entry *ce;
3976 
3977 	if (zend_parse_parameters_none() == FAILURE) {
3978 		return;
3979 	}
3980 	GET_REFLECTION_OBJECT_PTR(ce);
3981 	RETURN_BOOL(ce->type == ZEND_INTERNAL_CLASS);
3982 }
3983 /* }}} */
3984 
3985 /* {{{ proto public bool ReflectionClass::isUserDefined()
3986    Returns whether this class is user-defined */
ZEND_METHOD(reflection_class,isUserDefined)3987 ZEND_METHOD(reflection_class, isUserDefined)
3988 {
3989 	reflection_object *intern;
3990 	zend_class_entry *ce;
3991 
3992 	if (zend_parse_parameters_none() == FAILURE) {
3993 		return;
3994 	}
3995 	GET_REFLECTION_OBJECT_PTR(ce);
3996 	RETURN_BOOL(ce->type == ZEND_USER_CLASS);
3997 }
3998 /* }}} */
3999 
4000 /* {{{ proto public bool ReflectionClass::isAnonymous()
4001    Returns whether this class is anonymous */
ZEND_METHOD(reflection_class,isAnonymous)4002 ZEND_METHOD(reflection_class, isAnonymous)
4003 {
4004 	reflection_object *intern;
4005 	zend_class_entry *ce;
4006 
4007 	if (zend_parse_parameters_none() == FAILURE) {
4008 		return;
4009 	}
4010 	GET_REFLECTION_OBJECT_PTR(ce);
4011 	RETURN_BOOL(ce->ce_flags & ZEND_ACC_ANON_CLASS);
4012 }
4013 /* }}} */
4014 
4015 /* {{{ proto public string ReflectionClass::getFileName()
4016    Returns the filename of the file this class was declared in */
ZEND_METHOD(reflection_class,getFileName)4017 ZEND_METHOD(reflection_class, getFileName)
4018 {
4019 	reflection_object *intern;
4020 	zend_class_entry *ce;
4021 
4022 	if (zend_parse_parameters_none() == FAILURE) {
4023 		return;
4024 	}
4025 	GET_REFLECTION_OBJECT_PTR(ce);
4026 	if (ce->type == ZEND_USER_CLASS) {
4027 		RETURN_STR_COPY(ce->info.user.filename);
4028 	}
4029 	RETURN_FALSE;
4030 }
4031 /* }}} */
4032 
4033 /* {{{ proto public int ReflectionClass::getStartLine()
4034    Returns the line this class' declaration starts at */
ZEND_METHOD(reflection_class,getStartLine)4035 ZEND_METHOD(reflection_class, getStartLine)
4036 {
4037 	reflection_object *intern;
4038 	zend_class_entry *ce;
4039 
4040 	if (zend_parse_parameters_none() == FAILURE) {
4041 		return;
4042 	}
4043 	GET_REFLECTION_OBJECT_PTR(ce);
4044 	if (ce->type == ZEND_USER_CLASS) {
4045 		RETURN_LONG(ce->info.user.line_start);
4046 	}
4047 	RETURN_FALSE;
4048 }
4049 /* }}} */
4050 
4051 /* {{{ proto public int ReflectionClass::getEndLine()
4052    Returns the line this class' declaration ends at */
ZEND_METHOD(reflection_class,getEndLine)4053 ZEND_METHOD(reflection_class, getEndLine)
4054 {
4055 	reflection_object *intern;
4056 	zend_class_entry *ce;
4057 
4058 	if (zend_parse_parameters_none() == FAILURE) {
4059 		return;
4060 	}
4061 	GET_REFLECTION_OBJECT_PTR(ce);
4062 	if (ce->type == ZEND_USER_CLASS) {
4063 		RETURN_LONG(ce->info.user.line_end);
4064 	}
4065 	RETURN_FALSE;
4066 }
4067 /* }}} */
4068 
4069 /* {{{ proto public string ReflectionClass::getDocComment()
4070    Returns the doc comment for this class */
ZEND_METHOD(reflection_class,getDocComment)4071 ZEND_METHOD(reflection_class, getDocComment)
4072 {
4073 	reflection_object *intern;
4074 	zend_class_entry *ce;
4075 
4076 	if (zend_parse_parameters_none() == FAILURE) {
4077 		return;
4078 	}
4079 	GET_REFLECTION_OBJECT_PTR(ce);
4080 	if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
4081 		RETURN_STR_COPY(ce->info.user.doc_comment);
4082 	}
4083 	RETURN_FALSE;
4084 }
4085 /* }}} */
4086 
4087 /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor()
4088    Returns the class' constructor if there is one, NULL otherwise */
ZEND_METHOD(reflection_class,getConstructor)4089 ZEND_METHOD(reflection_class, getConstructor)
4090 {
4091 	reflection_object *intern;
4092 	zend_class_entry *ce;
4093 
4094 	if (zend_parse_parameters_none() == FAILURE) {
4095 		return;
4096 	}
4097 	GET_REFLECTION_OBJECT_PTR(ce);
4098 
4099 	if (ce->constructor) {
4100 		reflection_method_factory(ce, ce->constructor, NULL, return_value);
4101 	} else {
4102 		RETURN_NULL();
4103 	}
4104 }
4105 /* }}} */
4106 
4107 /* {{{ proto public bool ReflectionClass::hasMethod(string name)
4108    Returns whether a method exists or not */
ZEND_METHOD(reflection_class,hasMethod)4109 ZEND_METHOD(reflection_class, hasMethod)
4110 {
4111 	reflection_object *intern;
4112 	zend_class_entry *ce;
4113 	zend_string *name, *lc_name;
4114 
4115 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4116 		return;
4117 	}
4118 
4119 	GET_REFLECTION_OBJECT_PTR(ce);
4120 	lc_name = zend_string_tolower(name);
4121 	RETVAL_BOOL(zend_hash_exists(&ce->function_table, lc_name) || is_closure_invoke(ce, lc_name));
4122 	zend_string_release(lc_name);
4123 }
4124 /* }}} */
4125 
4126 /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException
4127    Returns the class' method specified by its name */
ZEND_METHOD(reflection_class,getMethod)4128 ZEND_METHOD(reflection_class, getMethod)
4129 {
4130 	reflection_object *intern;
4131 	zend_class_entry *ce;
4132 	zend_function *mptr;
4133 	zval obj_tmp;
4134 	zend_string *name, *lc_name;
4135 
4136 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4137 		return;
4138 	}
4139 
4140 	GET_REFLECTION_OBJECT_PTR(ce);
4141 	lc_name = zend_string_tolower(name);
4142 	if (!Z_ISUNDEF(intern->obj) && is_closure_invoke(ce, lc_name)
4143 		&& (mptr = zend_get_closure_invoke_method(Z_OBJ(intern->obj))) != NULL)
4144 	{
4145 		/* don't assign closure_object since we only reflect the invoke handler
4146 		   method and not the closure definition itself */
4147 		reflection_method_factory(ce, mptr, NULL, return_value);
4148 	} else if (Z_ISUNDEF(intern->obj) && is_closure_invoke(ce, lc_name)
4149 		&& object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(Z_OBJ(obj_tmp))) != NULL) {
4150 		/* don't assign closure_object since we only reflect the invoke handler
4151 		   method and not the closure definition itself */
4152 		reflection_method_factory(ce, mptr, NULL, return_value);
4153 		zval_ptr_dtor(&obj_tmp);
4154 	} else if ((mptr = zend_hash_find_ptr(&ce->function_table, lc_name)) != NULL) {
4155 		reflection_method_factory(ce, mptr, NULL, return_value);
4156 	} else {
4157 		zend_throw_exception_ex(reflection_exception_ptr, 0,
4158 				"Method %s does not exist", ZSTR_VAL(name));
4159 	}
4160 	zend_string_release(lc_name);
4161 }
4162 /* }}} */
4163 
4164 /* {{{ _addmethod */
_addmethod(zend_function * mptr,zend_class_entry * ce,zval * retval,zend_long filter)4165 static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter)
4166 {
4167 	if (mptr->common.fn_flags & filter) {
4168 		zval method;
4169 		reflection_method_factory(ce, mptr, NULL, &method);
4170 		add_next_index_zval(retval, &method);
4171 	}
4172 }
4173 /* }}} */
4174 
4175 /* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods([long $filter])
4176    Returns an array of this class' methods */
ZEND_METHOD(reflection_class,getMethods)4177 ZEND_METHOD(reflection_class, getMethods)
4178 {
4179 	reflection_object *intern;
4180 	zend_class_entry *ce;
4181 	zend_function *mptr;
4182 	zend_long filter = 0;
4183 	zend_bool filter_is_null = 1;
4184 
4185 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4186 		return;
4187 	}
4188 
4189 	if (filter_is_null) {
4190 		filter = ZEND_ACC_PPP_MASK | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL | ZEND_ACC_STATIC;
4191 	}
4192 
4193 	GET_REFLECTION_OBJECT_PTR(ce);
4194 
4195 	array_init(return_value);
4196 	ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
4197 		_addmethod(mptr, ce, return_value, filter);
4198 	} ZEND_HASH_FOREACH_END();
4199 
4200 	if (instanceof_function(ce, zend_ce_closure)) {
4201 		zend_bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
4202 		zval obj_tmp;
4203 		zend_object *obj;
4204 		if (!has_obj) {
4205 			object_init_ex(&obj_tmp, ce);
4206 			obj = Z_OBJ(obj_tmp);
4207 		} else {
4208 			obj = Z_OBJ(intern->obj);
4209 		}
4210 		zend_function *closure = zend_get_closure_invoke_method(obj);
4211 		if (closure) {
4212 			_addmethod(closure, ce, return_value, filter);
4213 		}
4214 		if (!has_obj) {
4215 			zval_ptr_dtor(&obj_tmp);
4216 		}
4217 	}
4218 }
4219 /* }}} */
4220 
4221 /* {{{ proto public bool ReflectionClass::hasProperty(string name)
4222    Returns whether a property exists or not */
ZEND_METHOD(reflection_class,hasProperty)4223 ZEND_METHOD(reflection_class, hasProperty)
4224 {
4225 	reflection_object *intern;
4226 	zend_property_info *property_info;
4227 	zend_class_entry *ce;
4228 	zend_string *name;
4229 	zval property;
4230 
4231 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4232 		return;
4233 	}
4234 
4235 	GET_REFLECTION_OBJECT_PTR(ce);
4236 	if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4237 		if ((property_info->flags & ZEND_ACC_PRIVATE) && property_info->ce != ce) {
4238 			RETURN_FALSE;
4239 		}
4240 		RETURN_TRUE;
4241 	} else {
4242 		if (Z_TYPE(intern->obj) != IS_UNDEF) {
4243 			ZVAL_STR_COPY(&property, name);
4244 			if (Z_OBJ_HANDLER(intern->obj, has_property)(&intern->obj, &property, 2, NULL)) {
4245 				zval_ptr_dtor(&property);
4246 				RETURN_TRUE;
4247 			}
4248 			zval_ptr_dtor(&property);
4249 		}
4250 		RETURN_FALSE;
4251 	}
4252 }
4253 /* }}} */
4254 
4255 /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException
4256    Returns the class' property specified by its name */
ZEND_METHOD(reflection_class,getProperty)4257 ZEND_METHOD(reflection_class, getProperty)
4258 {
4259 	reflection_object *intern;
4260 	zend_class_entry *ce, *ce2;
4261 	zend_property_info *property_info;
4262 	zend_string *name, *classname;
4263 	char *tmp, *str_name;
4264 	size_t classname_len, str_name_len;
4265 
4266 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4267 		return;
4268 	}
4269 
4270 	GET_REFLECTION_OBJECT_PTR(ce);
4271 	if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4272 		if (!(property_info->flags & ZEND_ACC_PRIVATE) || property_info->ce == ce) {
4273 			reflection_property_factory(ce, name, property_info, return_value, 0);
4274 			return;
4275 		}
4276 	} else if (Z_TYPE(intern->obj) != IS_UNDEF) {
4277 		/* Check for dynamic properties */
4278 		if (zend_hash_exists(Z_OBJ_HT(intern->obj)->get_properties(&intern->obj), name)) {
4279 			zend_property_info property_info_tmp;
4280 			property_info_tmp.flags = ZEND_ACC_PUBLIC;
4281 			property_info_tmp.name = name;
4282 			property_info_tmp.doc_comment = NULL;
4283 			property_info_tmp.ce = ce;
4284 			property_info_tmp.type = 0;
4285 
4286 			reflection_property_factory(ce, name, &property_info_tmp, return_value, 1);
4287 			return;
4288 		}
4289 	}
4290 	str_name = ZSTR_VAL(name);
4291 	if ((tmp = strstr(ZSTR_VAL(name), "::")) != NULL) {
4292 		classname_len = tmp - ZSTR_VAL(name);
4293 		classname = zend_string_alloc(classname_len, 0);
4294 		zend_str_tolower_copy(ZSTR_VAL(classname), ZSTR_VAL(name), classname_len);
4295 		ZSTR_VAL(classname)[classname_len] = '\0';
4296 		str_name_len = ZSTR_LEN(name) - (classname_len + 2);
4297 		str_name = tmp + 2;
4298 
4299 		ce2 = zend_lookup_class(classname);
4300 		if (!ce2) {
4301 			if (!EG(exception)) {
4302 				zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", ZSTR_VAL(classname));
4303 			}
4304 			zend_string_release_ex(classname, 0);
4305 			return;
4306 		}
4307 		zend_string_release_ex(classname, 0);
4308 
4309 		if (!instanceof_function(ce, ce2)) {
4310 			zend_throw_exception_ex(reflection_exception_ptr, -1, "Fully qualified property name %s::%s does not specify a base class of %s", ZSTR_VAL(ce2->name), str_name, ZSTR_VAL(ce->name));
4311 			return;
4312 		}
4313 		ce = ce2;
4314 
4315 		property_info = zend_hash_str_find_ptr(&ce->properties_info, str_name, str_name_len);
4316 		if (property_info != NULL
4317 		 && (!(property_info->flags & ZEND_ACC_PRIVATE)
4318 		  || property_info->ce == ce)) {
4319 			reflection_property_factory_str(ce, str_name, str_name_len, property_info, return_value);
4320 			return;
4321 		}
4322 	}
4323 	zend_throw_exception_ex(reflection_exception_ptr, 0,
4324 			"Property %s does not exist", str_name);
4325 }
4326 /* }}} */
4327 
4328 /* {{{ _addproperty */
_addproperty(zend_property_info * pptr,zend_string * key,zend_class_entry * ce,zval * retval,long filter)4329 static void _addproperty(zend_property_info *pptr, zend_string *key, zend_class_entry *ce, zval *retval, long filter)
4330 {
4331 	if ((pptr->flags & ZEND_ACC_PRIVATE) && pptr->ce != ce) {
4332 		return;
4333 	}
4334 
4335 	if (pptr->flags	& filter) {
4336 		zval property;
4337 		reflection_property_factory(ce, key, pptr, &property, 0);
4338 		add_next_index_zval(retval, &property);
4339 	}
4340 }
4341 /* }}} */
4342 
4343 /* {{{ _adddynproperty */
_adddynproperty(zval * ptr,zend_string * key,zend_class_entry * ce,zval * retval)4344 static void _adddynproperty(zval *ptr, zend_string *key, zend_class_entry *ce, zval *retval)
4345 {
4346 	zend_property_info property_info;
4347 	zval property;
4348 
4349 	/* under some circumstances, the properties hash table may contain numeric
4350 	 * properties (e.g. when casting from array). This is a WON'T FIX bug, at
4351 	 * least for the moment. Ignore these */
4352 	if (key == NULL) {
4353 		return;
4354 	}
4355 
4356 	/* Not a dynamic property */
4357 	if (Z_TYPE_P(ptr) == IS_INDIRECT) {
4358 		return;
4359 	}
4360 
4361 	property_info.doc_comment = NULL;
4362 	property_info.flags = ZEND_ACC_PUBLIC;
4363 	property_info.name = key;
4364 	property_info.ce = ce;
4365 	property_info.offset = -1;
4366 	property_info.type = 0;
4367 	reflection_property_factory(ce, key, &property_info, &property, 1);
4368 	add_next_index_zval(retval, &property);
4369 }
4370 /* }}} */
4371 
4372 /* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties([long $filter])
4373    Returns an array of this class' properties */
ZEND_METHOD(reflection_class,getProperties)4374 ZEND_METHOD(reflection_class, getProperties)
4375 {
4376 	reflection_object *intern;
4377 	zend_class_entry *ce;
4378 	zend_string *key;
4379 	zend_property_info *prop_info;
4380 	zend_long filter = 0;
4381 	zend_bool filter_is_null = 1;
4382 
4383 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4384 		return;
4385 	}
4386 
4387 	if (filter_is_null) {
4388 		filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
4389 	}
4390 
4391 	GET_REFLECTION_OBJECT_PTR(ce);
4392 
4393 	array_init(return_value);
4394 	ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
4395 		_addproperty(prop_info, key, ce, return_value, filter);
4396 	} ZEND_HASH_FOREACH_END();
4397 
4398 	if (Z_TYPE(intern->obj) != IS_UNDEF && (filter & ZEND_ACC_PUBLIC) != 0) {
4399 		HashTable *properties = Z_OBJ_HT(intern->obj)->get_properties(&intern->obj);
4400 		zval *prop;
4401 		ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
4402 			_adddynproperty(prop, key, ce, return_value);
4403 		} ZEND_HASH_FOREACH_END();
4404 	}
4405 }
4406 /* }}} */
4407 
4408 /* {{{ proto public bool ReflectionClass::hasConstant(string name)
4409    Returns whether a constant exists or not */
ZEND_METHOD(reflection_class,hasConstant)4410 ZEND_METHOD(reflection_class, hasConstant)
4411 {
4412 	reflection_object *intern;
4413 	zend_class_entry *ce;
4414 	zend_string *name;
4415 
4416 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4417 		return;
4418 	}
4419 
4420 	GET_REFLECTION_OBJECT_PTR(ce);
4421 	if (zend_hash_exists(&ce->constants_table, name)) {
4422 		RETURN_TRUE;
4423 	} else {
4424 		RETURN_FALSE;
4425 	}
4426 }
4427 /* }}} */
4428 
4429 /* {{{ proto public array ReflectionClass::getConstants()
4430    Returns an associative array containing this class' constants and their values */
ZEND_METHOD(reflection_class,getConstants)4431 ZEND_METHOD(reflection_class, getConstants)
4432 {
4433 	reflection_object *intern;
4434 	zend_class_entry *ce;
4435 	zend_string *key;
4436 	zend_class_constant *c;
4437 	zval val;
4438 
4439 	if (zend_parse_parameters_none() == FAILURE) {
4440 		return;
4441 	}
4442 	GET_REFLECTION_OBJECT_PTR(ce);
4443 	array_init(return_value);
4444 	ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
4445 		if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
4446 			zend_array_destroy(Z_ARRVAL_P(return_value));
4447 			RETURN_NULL();
4448 		}
4449 		ZVAL_COPY_OR_DUP(&val, &c->value);
4450 		zend_hash_add_new(Z_ARRVAL_P(return_value), key, &val);
4451 	} ZEND_HASH_FOREACH_END();
4452 }
4453 /* }}} */
4454 
4455 /* {{{ proto public array ReflectionClass::getReflectionConstants()
4456    Returns an associative array containing this class' constants as ReflectionClassConstant objects */
ZEND_METHOD(reflection_class,getReflectionConstants)4457 ZEND_METHOD(reflection_class, getReflectionConstants)
4458 {
4459 	reflection_object *intern;
4460 	zend_class_entry *ce;
4461 	zend_string *name;
4462 	zend_class_constant *constant;
4463 
4464 	if (zend_parse_parameters_none() == FAILURE) {
4465 		return;
4466 	}
4467 	GET_REFLECTION_OBJECT_PTR(ce);
4468 	array_init(return_value);
4469 	ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
4470 		zval class_const;
4471 		reflection_class_constant_factory(ce, name, constant, &class_const);
4472 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
4473 	} ZEND_HASH_FOREACH_END();
4474 }
4475 /* }}} */
4476 
4477 /* {{{ proto public mixed ReflectionClass::getConstant(string name)
4478    Returns the class' constant specified by its name */
ZEND_METHOD(reflection_class,getConstant)4479 ZEND_METHOD(reflection_class, getConstant)
4480 {
4481 	reflection_object *intern;
4482 	zend_class_entry *ce;
4483 	zend_class_constant *c;
4484 	zend_string *name;
4485 
4486 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4487 		return;
4488 	}
4489 
4490 	GET_REFLECTION_OBJECT_PTR(ce);
4491 	ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
4492 		if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
4493 			return;
4494 		}
4495 	} ZEND_HASH_FOREACH_END();
4496 	if ((c = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
4497 		RETURN_FALSE;
4498 	}
4499 	ZVAL_COPY_OR_DUP(return_value, &c->value);
4500 }
4501 /* }}} */
4502 
4503 /* {{{ proto public mixed ReflectionClass::getReflectionConstant(string name)
4504    Returns the class' constant as ReflectionClassConstant objects */
ZEND_METHOD(reflection_class,getReflectionConstant)4505 ZEND_METHOD(reflection_class, getReflectionConstant)
4506 {
4507 	reflection_object *intern;
4508 	zend_class_entry *ce;
4509 	zend_class_constant *constant;
4510 	zend_string *name;
4511 
4512 	GET_REFLECTION_OBJECT_PTR(ce);
4513 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4514 		return;
4515 	}
4516 
4517 	if ((constant = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
4518 		RETURN_FALSE;
4519 	}
4520 	reflection_class_constant_factory(ce, name, constant, return_value);
4521 }
4522 /* }}} */
4523 
4524 /* {{{ _class_check_flag */
_class_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)4525 static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
4526 {
4527 	reflection_object *intern;
4528 	zend_class_entry *ce;
4529 
4530 	if (zend_parse_parameters_none() == FAILURE) {
4531 		return;
4532 	}
4533 	GET_REFLECTION_OBJECT_PTR(ce);
4534 	RETVAL_BOOL(ce->ce_flags & mask);
4535 }
4536 /* }}} */
4537 
4538 /* {{{ proto public bool ReflectionClass::isInstantiable()
4539    Returns whether this class is instantiable */
ZEND_METHOD(reflection_class,isInstantiable)4540 ZEND_METHOD(reflection_class, isInstantiable)
4541 {
4542 	reflection_object *intern;
4543 	zend_class_entry *ce;
4544 
4545 	if (zend_parse_parameters_none() == FAILURE) {
4546 		return;
4547 	}
4548 	GET_REFLECTION_OBJECT_PTR(ce);
4549 	if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
4550 		RETURN_FALSE;
4551 	}
4552 
4553 	/* Basically, the class is instantiable. Though, if there is a constructor
4554 	 * and it is not publicly accessible, it isn't! */
4555 	if (!ce->constructor) {
4556 		RETURN_TRUE;
4557 	}
4558 
4559 	RETURN_BOOL(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC);
4560 }
4561 /* }}} */
4562 
4563 /* {{{ proto public bool ReflectionClass::isCloneable()
4564    Returns whether this class is cloneable */
ZEND_METHOD(reflection_class,isCloneable)4565 ZEND_METHOD(reflection_class, isCloneable)
4566 {
4567 	reflection_object *intern;
4568 	zend_class_entry *ce;
4569 	zval obj;
4570 
4571 	if (zend_parse_parameters_none() == FAILURE) {
4572 		return;
4573 	}
4574 	GET_REFLECTION_OBJECT_PTR(ce);
4575 	if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
4576 		RETURN_FALSE;
4577 	}
4578 	if (!Z_ISUNDEF(intern->obj)) {
4579 		if (ce->clone) {
4580 			RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
4581 		} else {
4582 			RETURN_BOOL(Z_OBJ_HANDLER(intern->obj, clone_obj) != NULL);
4583 		}
4584 	} else {
4585 		if (ce->clone) {
4586 			RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
4587 		} else {
4588 			if (UNEXPECTED(object_init_ex(&obj, ce) != SUCCESS)) {
4589 				return;
4590 			}
4591 			/* We're not calling the constructor, so don't call the destructor either. */
4592 			zend_object_store_ctor_failed(Z_OBJ(obj));
4593 			RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL);
4594 			zval_ptr_dtor(&obj);
4595 		}
4596 	}
4597 }
4598 /* }}} */
4599 
4600 /* {{{ proto public bool ReflectionClass::isInterface()
4601    Returns whether this is an interface or a class */
ZEND_METHOD(reflection_class,isInterface)4602 ZEND_METHOD(reflection_class, isInterface)
4603 {
4604 	_class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE);
4605 }
4606 /* }}} */
4607 
4608 /* {{{ proto public bool ReflectionClass::isTrait()
4609    Returns whether this is a trait */
ZEND_METHOD(reflection_class,isTrait)4610 ZEND_METHOD(reflection_class, isTrait)
4611 {
4612 	_class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT);
4613 }
4614 /* }}} */
4615 
4616 /* {{{ proto public bool ReflectionClass::isFinal()
4617    Returns whether this class is final */
ZEND_METHOD(reflection_class,isFinal)4618 ZEND_METHOD(reflection_class, isFinal)
4619 {
4620 	_class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
4621 }
4622 /* }}} */
4623 
4624 /* {{{ proto public bool ReflectionClass::isAbstract()
4625    Returns whether this class is abstract */
ZEND_METHOD(reflection_class,isAbstract)4626 ZEND_METHOD(reflection_class, isAbstract)
4627 {
4628 	_class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
4629 }
4630 /* }}} */
4631 
4632 /* {{{ proto public int ReflectionClass::getModifiers()
4633    Returns a bitfield of the access modifiers for this class */
ZEND_METHOD(reflection_class,getModifiers)4634 ZEND_METHOD(reflection_class, getModifiers)
4635 {
4636 	reflection_object *intern;
4637 	zend_class_entry *ce;
4638 	uint32_t keep_flags = ZEND_ACC_FINAL
4639 		| ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
4640 
4641 	if (zend_parse_parameters_none() == FAILURE) {
4642 		return;
4643 	}
4644 	GET_REFLECTION_OBJECT_PTR(ce);
4645 
4646 	RETURN_LONG((ce->ce_flags & keep_flags));
4647 }
4648 /* }}} */
4649 
4650 /* {{{ proto public bool ReflectionClass::isInstance(stdclass object)
4651    Returns whether the given object is an instance of this class */
ZEND_METHOD(reflection_class,isInstance)4652 ZEND_METHOD(reflection_class, isInstance)
4653 {
4654 	reflection_object *intern;
4655 	zend_class_entry *ce;
4656 	zval *object;
4657 
4658 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
4659 		return;
4660 	}
4661 	GET_REFLECTION_OBJECT_PTR(ce);
4662 	RETURN_BOOL(instanceof_function(Z_OBJCE_P(object), ce));
4663 }
4664 /* }}} */
4665 
4666 /* {{{ proto public object ReflectionClass::newInstance(mixed* args, ...)
4667    Returns an instance of this class */
ZEND_METHOD(reflection_class,newInstance)4668 ZEND_METHOD(reflection_class, newInstance)
4669 {
4670 	zval retval;
4671 	reflection_object *intern;
4672 	zend_class_entry *ce, *old_scope;
4673 	zend_function *constructor;
4674 
4675 	GET_REFLECTION_OBJECT_PTR(ce);
4676 
4677 	if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
4678 		return;
4679 	}
4680 
4681 	old_scope = EG(fake_scope);
4682 	EG(fake_scope) = ce;
4683 	constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
4684 	EG(fake_scope) = old_scope;
4685 
4686 	/* Run the constructor if there is one */
4687 	if (constructor) {
4688 		zval *params = NULL;
4689 		int ret, i, num_args = 0;
4690 		zend_fcall_info fci;
4691 		zend_fcall_info_cache fcc;
4692 
4693 		if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
4694 			zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
4695 			zval_ptr_dtor(return_value);
4696 			RETURN_NULL();
4697 		}
4698 
4699 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &params, &num_args) == FAILURE) {
4700 			zval_ptr_dtor(return_value);
4701 			RETURN_FALSE;
4702 		}
4703 
4704 		for (i = 0; i < num_args; i++) {
4705 			Z_TRY_ADDREF(params[i]);
4706 		}
4707 
4708 		fci.size = sizeof(fci);
4709 		ZVAL_UNDEF(&fci.function_name);
4710 		fci.object = Z_OBJ_P(return_value);
4711 		fci.retval = &retval;
4712 		fci.param_count = num_args;
4713 		fci.params = params;
4714 		fci.no_separation = 1;
4715 
4716 		fcc.function_handler = constructor;
4717 		fcc.called_scope = Z_OBJCE_P(return_value);
4718 		fcc.object = Z_OBJ_P(return_value);
4719 
4720 		ret = zend_call_function(&fci, &fcc);
4721 		zval_ptr_dtor(&retval);
4722 		for (i = 0; i < num_args; i++) {
4723 			zval_ptr_dtor(&params[i]);
4724 		}
4725 
4726 		if (EG(exception)) {
4727 			zend_object_store_ctor_failed(Z_OBJ_P(return_value));
4728 		}
4729 		if (ret == FAILURE) {
4730 			php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
4731 			zval_ptr_dtor(return_value);
4732 			RETURN_NULL();
4733 		}
4734 	} else if (ZEND_NUM_ARGS()) {
4735 		zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name));
4736 	}
4737 }
4738 /* }}} */
4739 
4740 /* {{{ proto public object ReflectionClass::newInstanceWithoutConstructor()
4741    Returns an instance of this class without invoking its constructor */
ZEND_METHOD(reflection_class,newInstanceWithoutConstructor)4742 ZEND_METHOD(reflection_class, newInstanceWithoutConstructor)
4743 {
4744 	reflection_object *intern;
4745 	zend_class_entry *ce;
4746 
4747 	GET_REFLECTION_OBJECT_PTR(ce);
4748 
4749 	if (ce->type == ZEND_INTERNAL_CLASS
4750 			&& ce->create_object != NULL && (ce->ce_flags & ZEND_ACC_FINAL)) {
4751 		zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s is an internal class marked as final that cannot be instantiated without invoking its constructor", ZSTR_VAL(ce->name));
4752 		return;
4753 	}
4754 
4755 	object_init_ex(return_value, ce);
4756 }
4757 /* }}} */
4758 
4759 /* {{{ proto public object ReflectionClass::newInstanceArgs([array args])
4760    Returns an instance of this class */
ZEND_METHOD(reflection_class,newInstanceArgs)4761 ZEND_METHOD(reflection_class, newInstanceArgs)
4762 {
4763 	zval retval, *val;
4764 	reflection_object *intern;
4765 	zend_class_entry *ce, *old_scope;
4766 	int ret, i, argc = 0;
4767 	HashTable *args;
4768 	zend_function *constructor;
4769 
4770 	GET_REFLECTION_OBJECT_PTR(ce);
4771 
4772 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|h", &args) == FAILURE) {
4773 		return;
4774 	}
4775 
4776 	if (ZEND_NUM_ARGS() > 0) {
4777 		argc = args->nNumOfElements;
4778 	}
4779 
4780 	if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
4781 		return;
4782 	}
4783 
4784 	old_scope = EG(fake_scope);
4785 	EG(fake_scope) = ce;
4786 	constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
4787 	EG(fake_scope) = old_scope;
4788 
4789 	/* Run the constructor if there is one */
4790 	if (constructor) {
4791 		zval *params = NULL;
4792 		zend_fcall_info fci;
4793 		zend_fcall_info_cache fcc;
4794 
4795 		if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
4796 			zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
4797 			zval_ptr_dtor(return_value);
4798 			RETURN_NULL();
4799 		}
4800 
4801 		if (argc) {
4802 			params = safe_emalloc(sizeof(zval), argc, 0);
4803 			argc = 0;
4804 			ZEND_HASH_FOREACH_VAL(args, val) {
4805 				ZVAL_COPY(&params[argc], val);
4806 				argc++;
4807 			} ZEND_HASH_FOREACH_END();
4808 		}
4809 
4810 		fci.size = sizeof(fci);
4811 		ZVAL_UNDEF(&fci.function_name);
4812 		fci.object = Z_OBJ_P(return_value);
4813 		fci.retval = &retval;
4814 		fci.param_count = argc;
4815 		fci.params = params;
4816 		fci.no_separation = 1;
4817 
4818 		fcc.function_handler = constructor;
4819 		fcc.called_scope = Z_OBJCE_P(return_value);
4820 		fcc.object = Z_OBJ_P(return_value);
4821 
4822 		ret = zend_call_function(&fci, &fcc);
4823 		zval_ptr_dtor(&retval);
4824 		if (params) {
4825 			for (i = 0; i < argc; i++) {
4826 				zval_ptr_dtor(&params[i]);
4827 			}
4828 			efree(params);
4829 		}
4830 
4831 		if (EG(exception)) {
4832 			zend_object_store_ctor_failed(Z_OBJ_P(return_value));
4833 		}
4834 		if (ret == FAILURE) {
4835 			zval_ptr_dtor(&retval);
4836 			php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
4837 			zval_ptr_dtor(return_value);
4838 			RETURN_NULL();
4839 		}
4840 	} else if (argc) {
4841 		zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name));
4842 	}
4843 }
4844 /* }}} */
4845 
4846 /* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces()
4847    Returns an array of interfaces this class implements */
ZEND_METHOD(reflection_class,getInterfaces)4848 ZEND_METHOD(reflection_class, getInterfaces)
4849 {
4850 	reflection_object *intern;
4851 	zend_class_entry *ce;
4852 
4853 	if (zend_parse_parameters_none() == FAILURE) {
4854 		return;
4855 	}
4856 	GET_REFLECTION_OBJECT_PTR(ce);
4857 
4858 	if (ce->num_interfaces) {
4859 		uint32_t i;
4860 
4861 		ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
4862 		array_init(return_value);
4863 		for (i=0; i < ce->num_interfaces; i++) {
4864 			zval interface;
4865 			zend_reflection_class_factory(ce->interfaces[i], &interface);
4866 			zend_hash_update(Z_ARRVAL_P(return_value), ce->interfaces[i]->name, &interface);
4867 		}
4868 	} else {
4869 		RETURN_EMPTY_ARRAY();
4870 	}
4871 }
4872 /* }}} */
4873 
4874 /* {{{ proto public String[] ReflectionClass::getInterfaceNames()
4875    Returns an array of names of interfaces this class implements */
ZEND_METHOD(reflection_class,getInterfaceNames)4876 ZEND_METHOD(reflection_class, getInterfaceNames)
4877 {
4878 	reflection_object *intern;
4879 	zend_class_entry *ce;
4880 	uint32_t i;
4881 
4882 	if (zend_parse_parameters_none() == FAILURE) {
4883 		return;
4884 	}
4885 	GET_REFLECTION_OBJECT_PTR(ce);
4886 
4887 	if (!ce->num_interfaces) {
4888 		/* Return an empty array if this class implements no interfaces */
4889 		RETURN_EMPTY_ARRAY();
4890 	}
4891 
4892 	ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
4893 	array_init(return_value);
4894 
4895 	for (i=0; i < ce->num_interfaces; i++) {
4896 		add_next_index_str(return_value, zend_string_copy(ce->interfaces[i]->name));
4897 	}
4898 }
4899 /* }}} */
4900 
4901 /* {{{ proto public ReflectionClass[] ReflectionClass::getTraits()
4902    Returns an array of traits used by this class */
ZEND_METHOD(reflection_class,getTraits)4903 ZEND_METHOD(reflection_class, getTraits)
4904 {
4905 	reflection_object *intern;
4906 	zend_class_entry *ce;
4907 	uint32_t i;
4908 
4909 	if (zend_parse_parameters_none() == FAILURE) {
4910 		return;
4911 	}
4912 	GET_REFLECTION_OBJECT_PTR(ce);
4913 
4914 	if (!ce->num_traits) {
4915 		RETURN_EMPTY_ARRAY();
4916 	}
4917 
4918 	array_init(return_value);
4919 
4920 	for (i=0; i < ce->num_traits; i++) {
4921 		zval trait;
4922 		zend_class_entry *trait_ce;
4923 
4924 		trait_ce = zend_fetch_class_by_name(ce->trait_names[i].name,
4925 			ce->trait_names[i].lc_name, ZEND_FETCH_CLASS_TRAIT);
4926 		ZEND_ASSERT(trait_ce);
4927 		zend_reflection_class_factory(trait_ce, &trait);
4928 		zend_hash_update(Z_ARRVAL_P(return_value), ce->trait_names[i].name, &trait);
4929 	}
4930 }
4931 /* }}} */
4932 
4933 /* {{{ proto public String[] ReflectionClass::getTraitNames()
4934    Returns an array of names of traits used by this class */
ZEND_METHOD(reflection_class,getTraitNames)4935 ZEND_METHOD(reflection_class, getTraitNames)
4936 {
4937 	reflection_object *intern;
4938 	zend_class_entry *ce;
4939 	uint32_t i;
4940 
4941 	if (zend_parse_parameters_none() == FAILURE) {
4942 		return;
4943 	}
4944 	GET_REFLECTION_OBJECT_PTR(ce);
4945 
4946 	if (!ce->num_traits) {
4947 		RETURN_EMPTY_ARRAY();
4948 	}
4949 
4950 	array_init(return_value);
4951 
4952 	for (i=0; i < ce->num_traits; i++) {
4953 		add_next_index_str(return_value, zend_string_copy(ce->trait_names[i].name));
4954 	}
4955 }
4956 /* }}} */
4957 
4958 /* {{{ proto public array ReflectionClass::getTraitAliases()
4959    Returns an array of trait aliases */
ZEND_METHOD(reflection_class,getTraitAliases)4960 ZEND_METHOD(reflection_class, getTraitAliases)
4961 {
4962 	reflection_object *intern;
4963 	zend_class_entry *ce;
4964 
4965 	if (zend_parse_parameters_none() == FAILURE) {
4966 		return;
4967 	}
4968 	GET_REFLECTION_OBJECT_PTR(ce);
4969 
4970 
4971 	if (ce->trait_aliases) {
4972 		uint32_t i = 0;
4973 
4974 		array_init(return_value);
4975 		while (ce->trait_aliases[i]) {
4976 			zend_string *mname;
4977 			zend_trait_method_reference *cur_ref = &ce->trait_aliases[i]->trait_method;
4978 
4979 			if (ce->trait_aliases[i]->alias) {
4980 
4981 				mname = zend_string_alloc(ZSTR_LEN(cur_ref->class_name) + ZSTR_LEN(cur_ref->method_name) + 2, 0);
4982 				snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(cur_ref->class_name), ZSTR_VAL(cur_ref->method_name));
4983 				add_assoc_str_ex(return_value, ZSTR_VAL(ce->trait_aliases[i]->alias), ZSTR_LEN(ce->trait_aliases[i]->alias), mname);
4984 			}
4985 			i++;
4986 		}
4987 	} else {
4988 		RETURN_EMPTY_ARRAY();
4989 	}
4990 }
4991 /* }}} */
4992 
4993 /* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
4994    Returns the class' parent class, or, if none exists, FALSE */
ZEND_METHOD(reflection_class,getParentClass)4995 ZEND_METHOD(reflection_class, getParentClass)
4996 {
4997 	reflection_object *intern;
4998 	zend_class_entry *ce;
4999 
5000 	if (zend_parse_parameters_none() == FAILURE) {
5001 		return;
5002 	}
5003 	GET_REFLECTION_OBJECT_PTR(ce);
5004 
5005 	if (ce->parent) {
5006 		zend_reflection_class_factory(ce->parent, return_value);
5007 	} else {
5008 		RETURN_FALSE;
5009 	}
5010 }
5011 /* }}} */
5012 
5013 /* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
5014    Returns whether this class is a subclass of another class */
ZEND_METHOD(reflection_class,isSubclassOf)5015 ZEND_METHOD(reflection_class, isSubclassOf)
5016 {
5017 	reflection_object *intern, *argument;
5018 	zend_class_entry *ce, *class_ce;
5019 	zval *class_name;
5020 
5021 	GET_REFLECTION_OBJECT_PTR(ce);
5022 
5023 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &class_name) == FAILURE) {
5024 		return;
5025 	}
5026 
5027 	switch (Z_TYPE_P(class_name)) {
5028 		case IS_STRING:
5029 			if ((class_ce = zend_lookup_class(Z_STR_P(class_name))) == NULL) {
5030 				zend_throw_exception_ex(reflection_exception_ptr, 0,
5031 						"Class %s does not exist", Z_STRVAL_P(class_name));
5032 				return;
5033 			}
5034 			break;
5035 		case IS_OBJECT:
5036 			if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr)) {
5037 				argument = Z_REFLECTION_P(class_name);
5038 				if (argument->ptr == NULL) {
5039 					zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5040 					return;
5041 				}
5042 				class_ce = argument->ptr;
5043 				break;
5044 			}
5045 			/* no break */
5046 		default:
5047 			zend_throw_exception_ex(reflection_exception_ptr, 0,
5048 					"Parameter one must either be a string or a ReflectionClass object");
5049 			return;
5050 	}
5051 
5052 	RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce)));
5053 }
5054 /* }}} */
5055 
5056 /* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
5057    Returns whether this class is a subclass of another class */
ZEND_METHOD(reflection_class,implementsInterface)5058 ZEND_METHOD(reflection_class, implementsInterface)
5059 {
5060 	reflection_object *intern, *argument;
5061 	zend_class_entry *ce, *interface_ce;
5062 	zval *interface;
5063 
5064 	GET_REFLECTION_OBJECT_PTR(ce);
5065 
5066 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &interface) == FAILURE) {
5067 		return;
5068 	}
5069 
5070 	switch (Z_TYPE_P(interface)) {
5071 		case IS_STRING:
5072 			if ((interface_ce = zend_lookup_class(Z_STR_P(interface))) == NULL) {
5073 				zend_throw_exception_ex(reflection_exception_ptr, 0,
5074 						"Interface %s does not exist", Z_STRVAL_P(interface));
5075 				return;
5076 			}
5077 			break;
5078 		case IS_OBJECT:
5079 			if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr)) {
5080 				argument = Z_REFLECTION_P(interface);
5081 				if (argument->ptr == NULL) {
5082 					zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5083 					return;
5084 				}
5085 				interface_ce = argument->ptr;
5086 				break;
5087 			}
5088 			/* no break */
5089 		default:
5090 			zend_throw_exception_ex(reflection_exception_ptr, 0,
5091 					"Parameter one must either be a string or a ReflectionClass object");
5092 			return;
5093 	}
5094 
5095 	if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
5096 		zend_throw_exception_ex(reflection_exception_ptr, 0,
5097 				"%s is not an interface", ZSTR_VAL(interface_ce->name));
5098 		return;
5099 	}
5100 	RETURN_BOOL(instanceof_function(ce, interface_ce));
5101 }
5102 /* }}} */
5103 
5104 /* {{{ proto public bool ReflectionClass::isIterable()
5105    Returns whether this class is iterable (can be used inside foreach) */
ZEND_METHOD(reflection_class,isIterable)5106 ZEND_METHOD(reflection_class, isIterable)
5107 {
5108 	reflection_object *intern;
5109 	zend_class_entry *ce;
5110 
5111 	if (zend_parse_parameters_none() == FAILURE) {
5112 		return;
5113 	}
5114 
5115 	GET_REFLECTION_OBJECT_PTR(ce);
5116 
5117 	if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS |
5118 	                    ZEND_ACC_TRAIT     | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
5119 		RETURN_FALSE;
5120 	}
5121 
5122 	RETURN_BOOL(ce->get_iterator || instanceof_function(ce, zend_ce_traversable));
5123 }
5124 /* }}} */
5125 
5126 /* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension()
5127    Returns NULL or the extension the class belongs to */
ZEND_METHOD(reflection_class,getExtension)5128 ZEND_METHOD(reflection_class, getExtension)
5129 {
5130 	reflection_object *intern;
5131 	zend_class_entry *ce;
5132 
5133 	if (zend_parse_parameters_none() == FAILURE) {
5134 		return;
5135 	}
5136 
5137 	GET_REFLECTION_OBJECT_PTR(ce);
5138 
5139 	if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5140 		reflection_extension_factory(return_value, ce->info.internal.module->name);
5141 	}
5142 }
5143 /* }}} */
5144 
5145 /* {{{ proto public string|false ReflectionClass::getExtensionName()
5146    Returns false or the name of the extension the class belongs to */
ZEND_METHOD(reflection_class,getExtensionName)5147 ZEND_METHOD(reflection_class, getExtensionName)
5148 {
5149 	reflection_object *intern;
5150 	zend_class_entry *ce;
5151 
5152 	if (zend_parse_parameters_none() == FAILURE) {
5153 		return;
5154 	}
5155 
5156 	GET_REFLECTION_OBJECT_PTR(ce);
5157 
5158 	if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5159 		RETURN_STRING(ce->info.internal.module->name);
5160 	} else {
5161 		RETURN_FALSE;
5162 	}
5163 }
5164 /* }}} */
5165 
5166 /* {{{ proto public bool ReflectionClass::inNamespace()
5167    Returns whether this class is defined in namespace */
ZEND_METHOD(reflection_class,inNamespace)5168 ZEND_METHOD(reflection_class, inNamespace)
5169 {
5170 	zval *name;
5171 	const char *backslash;
5172 
5173 	if (zend_parse_parameters_none() == FAILURE) {
5174 		return;
5175 	}
5176 	if ((name = _default_load_name(ZEND_THIS)) == NULL) {
5177 		RETURN_FALSE;
5178 	}
5179 	if (Z_TYPE_P(name) == IS_STRING
5180 		&& (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5181 		&& backslash > Z_STRVAL_P(name))
5182 	{
5183 		RETURN_TRUE;
5184 	}
5185 	RETURN_FALSE;
5186 }
5187 /* }}} */
5188 
5189 /* {{{ proto public string ReflectionClass::getNamespaceName()
5190    Returns the name of namespace where this class is defined */
ZEND_METHOD(reflection_class,getNamespaceName)5191 ZEND_METHOD(reflection_class, getNamespaceName)
5192 {
5193 	zval *name;
5194 	const char *backslash;
5195 
5196 	if (zend_parse_parameters_none() == FAILURE) {
5197 		return;
5198 	}
5199 	if ((name = _default_load_name(ZEND_THIS)) == NULL) {
5200 		RETURN_FALSE;
5201 	}
5202 	if (Z_TYPE_P(name) == IS_STRING
5203 		&& (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5204 		&& backslash > Z_STRVAL_P(name))
5205 	{
5206 		RETURN_STRINGL(Z_STRVAL_P(name), backslash - Z_STRVAL_P(name));
5207 	}
5208 	RETURN_EMPTY_STRING();
5209 }
5210 /* }}} */
5211 
5212 /* {{{ proto public string ReflectionClass::getShortName()
5213    Returns the short name of the class (without namespace part) */
ZEND_METHOD(reflection_class,getShortName)5214 ZEND_METHOD(reflection_class, getShortName)
5215 {
5216 	zval *name;
5217 	const char *backslash;
5218 
5219 	if (zend_parse_parameters_none() == FAILURE) {
5220 		return;
5221 	}
5222 	if ((name = _default_load_name(ZEND_THIS)) == NULL) {
5223 		RETURN_FALSE;
5224 	}
5225 	if (Z_TYPE_P(name) == IS_STRING
5226 		&& (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5227 		&& backslash > Z_STRVAL_P(name))
5228 	{
5229 		RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
5230 	}
5231 	ZVAL_COPY_DEREF(return_value, name);
5232 }
5233 /* }}} */
5234 
5235 /* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException
5236    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_object,export)5237 ZEND_METHOD(reflection_object, export)
5238 {
5239 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_object_ptr, 1);
5240 }
5241 /* }}} */
5242 
5243 /* {{{ proto public void ReflectionObject::__construct(mixed argument) throws ReflectionException
5244    Constructor. Takes an instance as an argument */
ZEND_METHOD(reflection_object,__construct)5245 ZEND_METHOD(reflection_object, __construct)
5246 {
5247 	reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
5248 }
5249 /* }}} */
5250 
5251 /* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException
5252    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_property,export)5253 ZEND_METHOD(reflection_property, export)
5254 {
5255 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_property_ptr, 2);
5256 }
5257 /* }}} */
5258 
5259 /* {{{ proto public static mixed ReflectionClassConstant::export(mixed class, string name [, bool return]) throws ReflectionException
5260    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class_constant,export)5261 ZEND_METHOD(reflection_class_constant, export)
5262 {
5263 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_constant_ptr, 2);
5264 }
5265 /* }}} */
5266 
5267 /* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
5268    Constructor. Throws an Exception in case the given property does not exist */
ZEND_METHOD(reflection_property,__construct)5269 ZEND_METHOD(reflection_property, __construct)
5270 {
5271 	zval *classname;
5272 	zend_string *name;
5273 	int dynam_prop = 0;
5274 	zval *object;
5275 	reflection_object *intern;
5276 	zend_class_entry *ce;
5277 	zend_property_info *property_info = NULL;
5278 	property_reference *reference;
5279 
5280 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zS", &classname, &name) == FAILURE) {
5281 		return;
5282 	}
5283 
5284 	object = ZEND_THIS;
5285 	intern = Z_REFLECTION_P(object);
5286 
5287 	/* Find the class entry */
5288 	switch (Z_TYPE_P(classname)) {
5289 		case IS_STRING:
5290 			if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
5291 				zend_throw_exception_ex(reflection_exception_ptr, 0,
5292 						"Class %s does not exist", Z_STRVAL_P(classname));
5293 				return;
5294 			}
5295 			break;
5296 
5297 		case IS_OBJECT:
5298 			ce = Z_OBJCE_P(classname);
5299 			break;
5300 
5301 		default:
5302 			_DO_THROW("The parameter class is expected to be either a string or an object");
5303 			return;
5304 	}
5305 
5306 	property_info = zend_hash_find_ptr(&ce->properties_info, name);
5307 	if (property_info == NULL
5308 	 || ((property_info->flags & ZEND_ACC_PRIVATE)
5309 	  && property_info->ce != ce)) {
5310 		/* Check for dynamic properties */
5311 		if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT) {
5312 			if (zend_hash_exists(Z_OBJ_HT_P(classname)->get_properties(classname), name)) {
5313 				dynam_prop = 1;
5314 			}
5315 		}
5316 		if (dynam_prop == 0) {
5317 			zend_throw_exception_ex(reflection_exception_ptr, 0, "Property %s::$%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
5318 			return;
5319 		}
5320 	}
5321 
5322 	if (dynam_prop == 0 && (property_info->flags & ZEND_ACC_PRIVATE) == 0) {
5323 		/* we have to search the class hierarchy for this (implicit) public or protected property */
5324 		zend_class_entry *tmp_ce = ce;
5325 		zend_property_info *tmp_info;
5326 
5327 		while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, name)) == NULL) {
5328 			ce = tmp_ce;
5329 			property_info = tmp_info;
5330 			tmp_ce = tmp_ce->parent;
5331 		}
5332 	}
5333 
5334 	ZVAL_STR_COPY(reflection_prop_name(object), name);
5335 	if (dynam_prop == 0) {
5336 		ZVAL_STR_COPY(reflection_prop_class(object), property_info->ce->name);
5337 	} else {
5338 		ZVAL_STR_COPY(reflection_prop_class(object), ce->name);
5339 	}
5340 
5341 	reference = (property_reference*) emalloc(sizeof(property_reference));
5342 	if (dynam_prop) {
5343 		reference->prop.flags = ZEND_ACC_PUBLIC;
5344 		reference->prop.name = name;
5345 		reference->prop.doc_comment = NULL;
5346 		reference->prop.ce = ce;
5347 		reference->prop.type = 0;
5348 		reference->dynamic = 1;
5349 	} else {
5350 		reference->prop = *property_info;
5351 		reference->dynamic = 0;
5352 
5353 		if (ZEND_TYPE_IS_NAME(reference->prop.type)) {
5354 			zend_string_addref(ZEND_TYPE_NAME(reference->prop.type));
5355 		}
5356 	}
5357 	reference->unmangled_name = zend_string_copy(name);
5358 	intern->ptr = reference;
5359 	intern->ref_type = REF_TYPE_PROPERTY;
5360 	intern->ce = ce;
5361 	intern->ignore_visibility = 0;
5362 }
5363 /* }}} */
5364 
5365 /* {{{ proto public string ReflectionProperty::__toString()
5366    Returns a string representation */
ZEND_METHOD(reflection_property,__toString)5367 ZEND_METHOD(reflection_property, __toString)
5368 {
5369 	reflection_object *intern;
5370 	property_reference *ref;
5371 	smart_str str = {0};
5372 
5373 	if (zend_parse_parameters_none() == FAILURE) {
5374 		return;
5375 	}
5376 	GET_REFLECTION_OBJECT_PTR(ref);
5377 	_property_string(&str, &ref->prop, ZSTR_VAL(ref->unmangled_name), "", ref->dynamic);
5378 	RETURN_STR(smart_str_extract(&str));
5379 }
5380 /* }}} */
5381 
5382 /* {{{ proto public string ReflectionProperty::getName()
5383    Returns the class' name */
ZEND_METHOD(reflection_property,getName)5384 ZEND_METHOD(reflection_property, getName)
5385 {
5386 	if (zend_parse_parameters_none() == FAILURE) {
5387 		return;
5388 	}
5389 	_default_get_name(ZEND_THIS, return_value);
5390 }
5391 /* }}} */
5392 
_property_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)5393 static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
5394 {
5395 	reflection_object *intern;
5396 	property_reference *ref;
5397 
5398 	if (zend_parse_parameters_none() == FAILURE) {
5399 		return;
5400 	}
5401 	GET_REFLECTION_OBJECT_PTR(ref);
5402 	RETURN_BOOL(ref->prop.flags & mask);
5403 }
5404 /* }}} */
5405 
5406 /* {{{ proto public bool ReflectionProperty::isPublic()
5407    Returns whether this property is public */
ZEND_METHOD(reflection_property,isPublic)5408 ZEND_METHOD(reflection_property, isPublic)
5409 {
5410 	_property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
5411 }
5412 /* }}} */
5413 
5414 /* {{{ proto public bool ReflectionProperty::isPrivate()
5415    Returns whether this property is private */
ZEND_METHOD(reflection_property,isPrivate)5416 ZEND_METHOD(reflection_property, isPrivate)
5417 {
5418 	_property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
5419 }
5420 /* }}} */
5421 
5422 /* {{{ proto public bool ReflectionProperty::isProtected()
5423    Returns whether this property is protected */
ZEND_METHOD(reflection_property,isProtected)5424 ZEND_METHOD(reflection_property, isProtected)
5425 {
5426 	_property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
5427 }
5428 /* }}} */
5429 
5430 /* {{{ proto public bool ReflectionProperty::isStatic()
5431    Returns whether this property is static */
ZEND_METHOD(reflection_property,isStatic)5432 ZEND_METHOD(reflection_property, isStatic)
5433 {
5434 	_property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
5435 }
5436 /* }}} */
5437 
5438 /* {{{ proto public bool ReflectionProperty::isDefault()
5439    Returns whether this property is default (declared at compilation time). */
ZEND_METHOD(reflection_property,isDefault)5440 ZEND_METHOD(reflection_property, isDefault)
5441 {
5442 	reflection_object *intern;
5443 	property_reference *ref;
5444 
5445 	if (zend_parse_parameters_none() == FAILURE) {
5446 		return;
5447 	}
5448 	GET_REFLECTION_OBJECT_PTR(ref);
5449 	RETURN_BOOL(!ref->dynamic);
5450 }
5451 /* }}} */
5452 
5453 /* {{{ proto public int ReflectionProperty::getModifiers()
5454    Returns a bitfield of the access modifiers for this property */
ZEND_METHOD(reflection_property,getModifiers)5455 ZEND_METHOD(reflection_property, getModifiers)
5456 {
5457 	reflection_object *intern;
5458 	property_reference *ref;
5459 	uint32_t keep_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
5460 
5461 	if (zend_parse_parameters_none() == FAILURE) {
5462 		return;
5463 	}
5464 	GET_REFLECTION_OBJECT_PTR(ref);
5465 
5466 	RETURN_LONG((ref->prop.flags & keep_flags));
5467 }
5468 /* }}} */
5469 
5470 /* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
5471    Returns this property's value */
ZEND_METHOD(reflection_property,getValue)5472 ZEND_METHOD(reflection_property, getValue)
5473 {
5474 	reflection_object *intern;
5475 	property_reference *ref;
5476 	zval *object, *name;
5477 	zval *member_p = NULL;
5478 
5479 	GET_REFLECTION_OBJECT_PTR(ref);
5480 
5481 	if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5482 		name = _default_load_name(ZEND_THIS);
5483 		zend_throw_exception_ex(reflection_exception_ptr, 0,
5484 			"Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5485 		return;
5486 	}
5487 
5488 	if (ref->prop.flags & ZEND_ACC_STATIC) {
5489 		member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 0);
5490 		if (member_p) {
5491 			ZVAL_COPY_DEREF(return_value, member_p);
5492 		}
5493 	} else {
5494 		zval rv;
5495 
5496 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
5497 			return;
5498 		}
5499 
5500 		if (!instanceof_function(Z_OBJCE_P(object), ref->prop.ce)) {
5501 			_DO_THROW("Given object is not an instance of the class this property was declared in");
5502 			return;
5503 		}
5504 
5505 		member_p = zend_read_property_ex(intern->ce, object, ref->unmangled_name, 0, &rv);
5506 		if (member_p != &rv) {
5507 			ZVAL_COPY_DEREF(return_value, member_p);
5508 		} else {
5509 			if (Z_ISREF_P(member_p)) {
5510 				zend_unwrap_reference(member_p);
5511 			}
5512 			ZVAL_COPY_VALUE(return_value, member_p);
5513 		}
5514 	}
5515 }
5516 /* }}} */
5517 
5518 /* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
5519    Sets this property's value */
ZEND_METHOD(reflection_property,setValue)5520 ZEND_METHOD(reflection_property, setValue)
5521 {
5522 	reflection_object *intern;
5523 	property_reference *ref;
5524 	zval *object, *name;
5525 	zval *value;
5526 	zval *tmp;
5527 
5528 	GET_REFLECTION_OBJECT_PTR(ref);
5529 
5530 	if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5531 		name = _default_load_name(ZEND_THIS);
5532 		zend_throw_exception_ex(reflection_exception_ptr, 0,
5533 			"Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5534 		return;
5535 	}
5536 
5537 	if (ref->prop.flags & ZEND_ACC_STATIC) {
5538 		if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
5539 			if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &tmp, &value) == FAILURE) {
5540 				return;
5541 			}
5542 		}
5543 
5544 		zend_update_static_property_ex(intern->ce, ref->unmangled_name, value);
5545 	} else {
5546 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "oz", &object, &value) == FAILURE) {
5547 			return;
5548 		}
5549 
5550 		zend_update_property_ex(intern->ce, object, ref->unmangled_name, value);
5551 	}
5552 }
5553 /* }}} */
5554 
5555 /* {{{ proto public mixed ReflectionProperty::isInitialized([stdclass object])
5556    Returns this property's value */
ZEND_METHOD(reflection_property,isInitialized)5557 ZEND_METHOD(reflection_property, isInitialized)
5558 {
5559 	reflection_object *intern;
5560 	property_reference *ref;
5561 	zval *object, *name;
5562 	zval *member_p = NULL;
5563 
5564 	GET_REFLECTION_OBJECT_PTR(ref);
5565 
5566 	if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5567 		name = _default_load_name(getThis());
5568 		zend_throw_exception_ex(reflection_exception_ptr, 0,
5569 			"Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5570 		return;
5571 	}
5572 
5573 	if (ref->prop.flags & ZEND_ACC_STATIC) {
5574 		member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 1);
5575 		if (member_p) {
5576 			RETURN_BOOL(!Z_ISUNDEF_P(member_p))
5577 		}
5578 		RETURN_FALSE;
5579 	} else {
5580 		zval name_zv;
5581 		zend_class_entry *old_scope;
5582 		int retval;
5583 
5584 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
5585 			return;
5586 		}
5587 
5588 		if (!instanceof_function(Z_OBJCE_P(object), ref->prop.ce)) {
5589 			_DO_THROW("Given object is not an instance of the class this property was declared in");
5590 			return;
5591 		}
5592 
5593 		old_scope = EG(fake_scope);
5594 		EG(fake_scope) = intern->ce;
5595 		ZVAL_STR(&name_zv, ref->unmangled_name);
5596 		retval = Z_OBJ_HT_P(object)->has_property(object, &name_zv, ZEND_PROPERTY_EXISTS, NULL);
5597 		EG(fake_scope) = old_scope;
5598 
5599 		RETVAL_BOOL(retval);
5600 	}
5601 }
5602 /* }}} */
5603 
5604 /* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
5605    Get the declaring class */
ZEND_METHOD(reflection_property,getDeclaringClass)5606 ZEND_METHOD(reflection_property, getDeclaringClass)
5607 {
5608 	reflection_object *intern;
5609 	property_reference *ref;
5610 	zend_class_entry *tmp_ce, *ce;
5611 	zend_property_info *tmp_info;
5612 
5613 	if (zend_parse_parameters_none() == FAILURE) {
5614 		return;
5615 	}
5616 	GET_REFLECTION_OBJECT_PTR(ref);
5617 
5618 	ce = tmp_ce = intern->ce;
5619 	while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, ref->unmangled_name)) != NULL) {
5620 		if (tmp_info->flags & ZEND_ACC_PRIVATE) {
5621 			/* it's a private property, so it can't be inherited */
5622 			break;
5623 		}
5624 		ce = tmp_ce;
5625 		if (tmp_ce == tmp_info->ce) {
5626 			/* declared in this class, done */
5627 			break;
5628 		}
5629 		tmp_ce = tmp_ce->parent;
5630 	}
5631 
5632 	zend_reflection_class_factory(ce, return_value);
5633 }
5634 /* }}} */
5635 
5636 /* {{{ proto public string ReflectionProperty::getDocComment()
5637    Returns the doc comment for this property */
ZEND_METHOD(reflection_property,getDocComment)5638 ZEND_METHOD(reflection_property, getDocComment)
5639 {
5640 	reflection_object *intern;
5641 	property_reference *ref;
5642 
5643 	if (zend_parse_parameters_none() == FAILURE) {
5644 		return;
5645 	}
5646 	GET_REFLECTION_OBJECT_PTR(ref);
5647 	if (ref->prop.doc_comment) {
5648 		RETURN_STR_COPY(ref->prop.doc_comment);
5649 	}
5650 	RETURN_FALSE;
5651 }
5652 /* }}} */
5653 
5654 /* {{{ proto public int ReflectionProperty::setAccessible(bool visible)
5655    Sets whether non-public properties can be requested */
ZEND_METHOD(reflection_property,setAccessible)5656 ZEND_METHOD(reflection_property, setAccessible)
5657 {
5658 	reflection_object *intern;
5659 	zend_bool visible;
5660 
5661 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
5662 		return;
5663 	}
5664 
5665 	intern = Z_REFLECTION_P(ZEND_THIS);
5666 
5667 	intern->ignore_visibility = visible;
5668 }
5669 /* }}} */
5670 
5671 /* {{{ proto public ReflectionType ReflectionProperty::getType()
5672    Returns the type associated with the property */
ZEND_METHOD(reflection_property,getType)5673 ZEND_METHOD(reflection_property, getType)
5674 {
5675 	reflection_object *intern;
5676 	property_reference *ref;
5677 
5678 	if (zend_parse_parameters_none() == FAILURE) {
5679 		return;
5680 	}
5681 
5682 	GET_REFLECTION_OBJECT_PTR(ref);
5683 
5684 	if (!ZEND_TYPE_IS_SET(ref->prop.type)) {
5685 		RETURN_NULL();
5686 	}
5687 
5688 	reflection_type_factory(ref->prop.type, return_value);
5689 }
5690 /* }}} */
5691 
5692 /* {{{ proto public bool ReflectionProperty::hasType()
5693    Returns whether property has a type */
ZEND_METHOD(reflection_property,hasType)5694 ZEND_METHOD(reflection_property, hasType)
5695 {
5696 	reflection_object *intern;
5697 	property_reference *ref;
5698 
5699 	if (zend_parse_parameters_none() == FAILURE) {
5700 		return;
5701 	}
5702 
5703 	GET_REFLECTION_OBJECT_PTR(ref);
5704 
5705 	RETVAL_BOOL(ZEND_TYPE_IS_SET(ref->prop.type));
5706 }
5707 /* }}} */
5708 
5709 /* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException
5710    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_extension,export)5711 ZEND_METHOD(reflection_extension, export)
5712 {
5713 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_extension_ptr, 1);
5714 }
5715 /* }}} */
5716 
5717 /* {{{ proto public void ReflectionExtension::__construct(string name)
5718    Constructor. Throws an Exception in case the given extension does not exist */
ZEND_METHOD(reflection_extension,__construct)5719 ZEND_METHOD(reflection_extension, __construct)
5720 {
5721 	zval *object;
5722 	char *lcname;
5723 	reflection_object *intern;
5724 	zend_module_entry *module;
5725 	char *name_str;
5726 	size_t name_len;
5727 	ALLOCA_FLAG(use_heap)
5728 
5729 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
5730 		return;
5731 	}
5732 
5733 	object = ZEND_THIS;
5734 	intern = Z_REFLECTION_P(object);
5735 	lcname = do_alloca(name_len + 1, use_heap);
5736 	zend_str_tolower_copy(lcname, name_str, name_len);
5737 	if ((module = zend_hash_str_find_ptr(&module_registry, lcname, name_len)) == NULL) {
5738 		free_alloca(lcname, use_heap);
5739 		zend_throw_exception_ex(reflection_exception_ptr, 0,
5740 			"Extension %s does not exist", name_str);
5741 		return;
5742 	}
5743 	free_alloca(lcname, use_heap);
5744 	ZVAL_STRING(reflection_prop_name(object), module->name);
5745 	intern->ptr = module;
5746 	intern->ref_type = REF_TYPE_OTHER;
5747 	intern->ce = NULL;
5748 }
5749 /* }}} */
5750 
5751 /* {{{ proto public string ReflectionExtension::__toString()
5752    Returns a string representation */
ZEND_METHOD(reflection_extension,__toString)5753 ZEND_METHOD(reflection_extension, __toString)
5754 {
5755 	reflection_object *intern;
5756 	zend_module_entry *module;
5757 	smart_str str = {0};
5758 
5759 	if (zend_parse_parameters_none() == FAILURE) {
5760 		return;
5761 	}
5762 	GET_REFLECTION_OBJECT_PTR(module);
5763 	_extension_string(&str, module, "");
5764 	RETURN_STR(smart_str_extract(&str));
5765 }
5766 /* }}} */
5767 
5768 /* {{{ proto public string ReflectionExtension::getName()
5769    Returns this extension's name */
ZEND_METHOD(reflection_extension,getName)5770 ZEND_METHOD(reflection_extension, getName)
5771 {
5772 	if (zend_parse_parameters_none() == FAILURE) {
5773 		return;
5774 	}
5775 	_default_get_name(ZEND_THIS, return_value);
5776 }
5777 /* }}} */
5778 
5779 /* {{{ proto public string ReflectionExtension::getVersion()
5780    Returns this extension's version */
ZEND_METHOD(reflection_extension,getVersion)5781 ZEND_METHOD(reflection_extension, getVersion)
5782 {
5783 	reflection_object *intern;
5784 	zend_module_entry *module;
5785 
5786 	if (zend_parse_parameters_none() == FAILURE) {
5787 		return;
5788 	}
5789 	GET_REFLECTION_OBJECT_PTR(module);
5790 
5791 	/* An extension does not necessarily have a version number */
5792 	if (module->version == NO_VERSION_YET) {
5793 		RETURN_NULL();
5794 	} else {
5795 		RETURN_STRING(module->version);
5796 	}
5797 }
5798 /* }}} */
5799 
5800 /* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions()
5801    Returns an array of this extension's functions */
ZEND_METHOD(reflection_extension,getFunctions)5802 ZEND_METHOD(reflection_extension, getFunctions)
5803 {
5804 	reflection_object *intern;
5805 	zend_module_entry *module;
5806 	zval function;
5807 	zend_function *fptr;
5808 
5809 	if (zend_parse_parameters_none() == FAILURE) {
5810 		return;
5811 	}
5812 	GET_REFLECTION_OBJECT_PTR(module);
5813 
5814 	array_init(return_value);
5815 	ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
5816 		if (fptr->common.type==ZEND_INTERNAL_FUNCTION
5817 			&& fptr->internal_function.module == module) {
5818 			reflection_function_factory(fptr, NULL, &function);
5819 			zend_hash_update(Z_ARRVAL_P(return_value), fptr->common.function_name, &function);
5820 		}
5821 	} ZEND_HASH_FOREACH_END();
5822 }
5823 /* }}} */
5824 
5825 /* {{{ proto public array ReflectionExtension::getConstants()
5826    Returns an associative array containing this extension's constants and their values */
ZEND_METHOD(reflection_extension,getConstants)5827 ZEND_METHOD(reflection_extension, getConstants)
5828 {
5829 	reflection_object *intern;
5830 	zend_module_entry *module;
5831 	zend_constant *constant;
5832 
5833 	if (zend_parse_parameters_none() == FAILURE) {
5834 		return;
5835 	}
5836 	GET_REFLECTION_OBJECT_PTR(module);
5837 
5838 	array_init(return_value);
5839 	ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) {
5840 		if (module->module_number == ZEND_CONSTANT_MODULE_NUMBER(constant)) {
5841 			zval const_val;
5842 			ZVAL_COPY_OR_DUP(&const_val, &constant->value);
5843 			zend_hash_update(Z_ARRVAL_P(return_value), constant->name, &const_val);
5844 		}
5845 	} ZEND_HASH_FOREACH_END();
5846 }
5847 /* }}} */
5848 
5849 /* {{{ _addinientry */
_addinientry(zend_ini_entry * ini_entry,zval * retval,int number)5850 static void _addinientry(zend_ini_entry *ini_entry, zval *retval, int number)
5851 {
5852 	if (number == ini_entry->module_number) {
5853 		zval zv;
5854 		if (ini_entry->value) {
5855 			ZVAL_STR_COPY(&zv, ini_entry->value);
5856 		} else {
5857 			ZVAL_NULL(&zv);
5858 		}
5859 		zend_symtable_update(Z_ARRVAL_P(retval), ini_entry->name, &zv);
5860 	}
5861 }
5862 /* }}} */
5863 
5864 /* {{{ proto public array ReflectionExtension::getINIEntries()
5865    Returns an associative array containing this extension's INI entries and their values */
ZEND_METHOD(reflection_extension,getINIEntries)5866 ZEND_METHOD(reflection_extension, getINIEntries)
5867 {
5868 	reflection_object *intern;
5869 	zend_module_entry *module;
5870 	zend_ini_entry *ini_entry;
5871 
5872 	if (zend_parse_parameters_none() == FAILURE) {
5873 		return;
5874 	}
5875 	GET_REFLECTION_OBJECT_PTR(module);
5876 
5877 	array_init(return_value);
5878 	ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) {
5879 		_addinientry(ini_entry, return_value, module->module_number);
5880 	} ZEND_HASH_FOREACH_END();
5881 }
5882 /* }}} */
5883 
5884 /* {{{ add_extension_class */
add_extension_class(zend_class_entry * ce,zend_string * key,zval * class_array,zend_module_entry * module,zend_bool add_reflection_class)5885 static void add_extension_class(zend_class_entry *ce, zend_string *key, zval *class_array, zend_module_entry *module, zend_bool add_reflection_class)
5886 {
5887 	if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
5888 		zend_string *name;
5889 
5890 		if (!zend_string_equals_ci(ce->name, key)) {
5891 			/* This is a class alias, use alias name */
5892 			name = key;
5893 		} else {
5894 			/* Use class name */
5895 			name = ce->name;
5896 		}
5897 		if (add_reflection_class) {
5898 			zval zclass;
5899 			zend_reflection_class_factory(ce, &zclass);
5900 			zend_hash_update(Z_ARRVAL_P(class_array), name, &zclass);
5901 		} else {
5902 			add_next_index_str(class_array, zend_string_copy(name));
5903 		}
5904 	}
5905 }
5906 /* }}} */
5907 
5908 /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses()
5909    Returns an array containing ReflectionClass objects for all classes of this extension */
ZEND_METHOD(reflection_extension,getClasses)5910 ZEND_METHOD(reflection_extension, getClasses)
5911 {
5912 	reflection_object *intern;
5913 	zend_module_entry *module;
5914 	zend_string *key;
5915 	zend_class_entry *ce;
5916 
5917 	if (zend_parse_parameters_none() == FAILURE) {
5918 		return;
5919 	}
5920 	GET_REFLECTION_OBJECT_PTR(module);
5921 
5922 	array_init(return_value);
5923 	ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
5924 		add_extension_class(ce, key, return_value, module, 1);
5925 	} ZEND_HASH_FOREACH_END();
5926 }
5927 /* }}} */
5928 
5929 /* {{{ proto public array ReflectionExtension::getClassNames()
5930    Returns an array containing all names of all classes of this extension */
ZEND_METHOD(reflection_extension,getClassNames)5931 ZEND_METHOD(reflection_extension, getClassNames)
5932 {
5933 	reflection_object *intern;
5934 	zend_module_entry *module;
5935 	zend_string *key;
5936 	zend_class_entry *ce;
5937 
5938 	if (zend_parse_parameters_none() == FAILURE) {
5939 		return;
5940 	}
5941 	GET_REFLECTION_OBJECT_PTR(module);
5942 
5943 	array_init(return_value);
5944 	ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
5945 		add_extension_class(ce, key, return_value, module, 0);
5946 	} ZEND_HASH_FOREACH_END();
5947 }
5948 /* }}} */
5949 
5950 /* {{{ proto public array ReflectionExtension::getDependencies()
5951    Returns an array containing all names of all extensions this extension depends on */
ZEND_METHOD(reflection_extension,getDependencies)5952 ZEND_METHOD(reflection_extension, getDependencies)
5953 {
5954 	reflection_object *intern;
5955 	zend_module_entry *module;
5956 	const zend_module_dep *dep;
5957 
5958 	if (zend_parse_parameters_none() == FAILURE) {
5959 		return;
5960 	}
5961 	GET_REFLECTION_OBJECT_PTR(module);
5962 
5963 	dep = module->deps;
5964 
5965 	if (!dep)
5966 	{
5967 		RETURN_EMPTY_ARRAY();
5968 	}
5969 
5970 	array_init(return_value);
5971 	while(dep->name) {
5972 		zend_string *relation;
5973 		char *rel_type;
5974 		size_t len = 0;
5975 
5976 		switch(dep->type) {
5977 			case MODULE_DEP_REQUIRED:
5978 				rel_type = "Required";
5979 				len += sizeof("Required") - 1;
5980 				break;
5981 			case MODULE_DEP_CONFLICTS:
5982 				rel_type = "Conflicts";
5983 				len += sizeof("Conflicts") - 1;
5984 				break;
5985 			case MODULE_DEP_OPTIONAL:
5986 				rel_type = "Optional";
5987 				len += sizeof("Optional") - 1;
5988 				break;
5989 			default:
5990 				rel_type = "Error"; /* shouldn't happen */
5991 				len += sizeof("Error") - 1;
5992 				break;
5993 		}
5994 
5995 		if (dep->rel) {
5996 			len += strlen(dep->rel) + 1;
5997 		}
5998 
5999 		if (dep->version) {
6000 			len += strlen(dep->version) + 1;
6001 		}
6002 
6003 		relation = zend_string_alloc(len, 0);
6004 		snprintf(ZSTR_VAL(relation), ZSTR_LEN(relation) + 1, "%s%s%s%s%s",
6005 						rel_type,
6006 						dep->rel ? " " : "",
6007 						dep->rel ? dep->rel : "",
6008 						dep->version ? " " : "",
6009 						dep->version ? dep->version : "");
6010 		add_assoc_str(return_value, dep->name, relation);
6011 		dep++;
6012 	}
6013 }
6014 /* }}} */
6015 
6016 /* {{{ proto public void ReflectionExtension::info()
6017        Prints phpinfo block for the extension */
ZEND_METHOD(reflection_extension,info)6018 ZEND_METHOD(reflection_extension, info)
6019 {
6020 	reflection_object *intern;
6021 	zend_module_entry *module;
6022 
6023 	if (zend_parse_parameters_none() == FAILURE) {
6024 		return;
6025 	}
6026 	GET_REFLECTION_OBJECT_PTR(module);
6027 
6028 	php_info_print_module(module);
6029 }
6030 /* }}} */
6031 
6032 /* {{{ proto public bool ReflectionExtension::isPersistent()
6033        Returns whether this extension is persistent */
ZEND_METHOD(reflection_extension,isPersistent)6034 ZEND_METHOD(reflection_extension, isPersistent)
6035 {
6036 	reflection_object *intern;
6037     zend_module_entry *module;
6038 
6039     if (zend_parse_parameters_none() == FAILURE) {
6040 		return;
6041 	}
6042 	GET_REFLECTION_OBJECT_PTR(module);
6043 
6044 	RETURN_BOOL(module->type == MODULE_PERSISTENT);
6045 }
6046 /* }}} */
6047 
6048 /* {{{ proto public bool ReflectionExtension::isTemporary()
6049        Returns whether this extension is temporary */
ZEND_METHOD(reflection_extension,isTemporary)6050 ZEND_METHOD(reflection_extension, isTemporary)
6051 {
6052 	reflection_object *intern;
6053 	zend_module_entry *module;
6054 
6055 	if (zend_parse_parameters_none() == FAILURE) {
6056 		return;
6057 	}
6058 	GET_REFLECTION_OBJECT_PTR(module);
6059 
6060 	RETURN_BOOL(module->type == MODULE_TEMPORARY);
6061 }
6062 /* }}} */
6063 
6064 /* {{{ proto public static mixed ReflectionZendExtension::export(string name [, bool return]) throws ReflectionException
6065  *    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_zend_extension,export)6066 ZEND_METHOD(reflection_zend_extension, export)
6067 {
6068 	_reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_zend_extension_ptr, 1);
6069 }
6070 /* }}} */
6071 
6072 /* {{{ proto public void ReflectionZendExtension::__construct(string name)
6073        Constructor. Throws an Exception in case the given Zend extension does not exist */
ZEND_METHOD(reflection_zend_extension,__construct)6074 ZEND_METHOD(reflection_zend_extension, __construct)
6075 {
6076 	zval *object;
6077 	reflection_object *intern;
6078 	zend_extension *extension;
6079 	char *name_str;
6080 	size_t name_len;
6081 
6082 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
6083 		return;
6084 	}
6085 
6086 	object = ZEND_THIS;
6087 	intern = Z_REFLECTION_P(object);
6088 
6089 	extension = zend_get_extension(name_str);
6090 	if (!extension) {
6091 		zend_throw_exception_ex(reflection_exception_ptr, 0,
6092 				"Zend Extension %s does not exist", name_str);
6093 		return;
6094 	}
6095 	ZVAL_STRING(reflection_prop_name(object), extension->name);
6096 	intern->ptr = extension;
6097 	intern->ref_type = REF_TYPE_OTHER;
6098 	intern->ce = NULL;
6099 }
6100 /* }}} */
6101 
6102 /* {{{ proto public string ReflectionZendExtension::__toString()
6103        Returns a string representation */
ZEND_METHOD(reflection_zend_extension,__toString)6104 ZEND_METHOD(reflection_zend_extension, __toString)
6105 {
6106 	reflection_object *intern;
6107 	zend_extension *extension;
6108 	smart_str str = {0};
6109 
6110 	if (zend_parse_parameters_none() == FAILURE) {
6111 		return;
6112 	}
6113 	GET_REFLECTION_OBJECT_PTR(extension);
6114 	_zend_extension_string(&str, extension, "");
6115 	RETURN_STR(smart_str_extract(&str));
6116 }
6117 /* }}} */
6118 
6119 /* {{{ proto public string ReflectionZendExtension::getName()
6120        Returns the name of this Zend extension */
ZEND_METHOD(reflection_zend_extension,getName)6121 ZEND_METHOD(reflection_zend_extension, getName)
6122 {
6123 	reflection_object *intern;
6124 	zend_extension *extension;
6125 
6126 	if (zend_parse_parameters_none() == FAILURE) {
6127 		return;
6128 	}
6129 	GET_REFLECTION_OBJECT_PTR(extension);
6130 
6131 	RETURN_STRING(extension->name);
6132 }
6133 /* }}} */
6134 
6135 /* {{{ proto public string ReflectionZendExtension::getVersion()
6136        Returns the version information of this Zend extension */
ZEND_METHOD(reflection_zend_extension,getVersion)6137 ZEND_METHOD(reflection_zend_extension, getVersion)
6138 {
6139 	reflection_object *intern;
6140 	zend_extension *extension;
6141 
6142 	if (zend_parse_parameters_none() == FAILURE) {
6143 		return;
6144 	}
6145 	GET_REFLECTION_OBJECT_PTR(extension);
6146 
6147 	if (extension->version) {
6148 		RETURN_STRING(extension->version);
6149 	} else {
6150 		RETURN_EMPTY_STRING();
6151 	}
6152 }
6153 /* }}} */
6154 
6155 /* {{{ proto public void ReflectionZendExtension::getAuthor()
6156  * Returns the name of this Zend extension's author */
ZEND_METHOD(reflection_zend_extension,getAuthor)6157 ZEND_METHOD(reflection_zend_extension, getAuthor)
6158 {
6159 	reflection_object *intern;
6160 	zend_extension *extension;
6161 
6162 	if (zend_parse_parameters_none() == FAILURE) {
6163 		return;
6164 	}
6165 	GET_REFLECTION_OBJECT_PTR(extension);
6166 
6167 	if (extension->author) {
6168 		RETURN_STRING(extension->author);
6169 	} else {
6170 		RETURN_EMPTY_STRING();
6171 	}
6172 }
6173 /* }}} */
6174 
6175 /* {{{ proto public void ReflectionZendExtension::getURL()
6176        Returns this Zend extension's URL*/
ZEND_METHOD(reflection_zend_extension,getURL)6177 ZEND_METHOD(reflection_zend_extension, getURL)
6178 {
6179 	reflection_object *intern;
6180 	zend_extension *extension;
6181 
6182 	if (zend_parse_parameters_none() == FAILURE) {
6183 		return;
6184 	}
6185 	GET_REFLECTION_OBJECT_PTR(extension);
6186 
6187 	if (extension->URL) {
6188 		RETURN_STRING(extension->URL);
6189 	} else {
6190 		RETURN_EMPTY_STRING();
6191 	}
6192 }
6193 /* }}} */
6194 
6195 /* {{{ proto public void ReflectionZendExtension::getCopyright()
6196        Returns this Zend extension's copyright information */
ZEND_METHOD(reflection_zend_extension,getCopyright)6197 ZEND_METHOD(reflection_zend_extension, getCopyright)
6198 {
6199 	reflection_object *intern;
6200 	zend_extension *extension;
6201 
6202 	if (zend_parse_parameters_none() == FAILURE) {
6203 		return;
6204 	}
6205 	GET_REFLECTION_OBJECT_PTR(extension);
6206 
6207 	if (extension->copyright) {
6208 		RETURN_STRING(extension->copyright);
6209 	} else {
6210 		RETURN_EMPTY_STRING();
6211 	}
6212 }
6213 /* }}} */
6214 
6215 /* {{{ proto public ReflectionReference::__construct()
6216  *     Dummy constructor -- always throws ReflectionExceptions. */
ZEND_METHOD(reflection_reference,__construct)6217 ZEND_METHOD(reflection_reference, __construct)
6218 {
6219 	_DO_THROW(
6220 		"Cannot directly instantiate ReflectionReference. "
6221 		"Use ReflectionReference::fromArrayElement() instead"
6222 	);
6223 }
6224 /* }}} */
6225 
is_ignorable_reference(HashTable * ht,zval * ref)6226 static zend_bool is_ignorable_reference(HashTable *ht, zval *ref) {
6227 	if (Z_REFCOUNT_P(ref) != 1) {
6228 		return 0;
6229 	}
6230 
6231 	/* Directly self-referential arrays are treated as proper references
6232 	 * in zend_array_dup() despite rc=1. */
6233 	return Z_TYPE_P(Z_REFVAL_P(ref)) != IS_ARRAY || Z_ARRVAL_P(Z_REFVAL_P(ref)) != ht;
6234 }
6235 
6236 /* {{{ proto public ReflectionReference|null ReflectionReference::fromArrayElement(array array, mixed key)
6237  *     Create ReflectionReference for array item. Returns null if not a reference. */
ZEND_METHOD(reflection_reference,fromArrayElement)6238 ZEND_METHOD(reflection_reference, fromArrayElement)
6239 {
6240 	HashTable *ht;
6241 	zval *key, *item;
6242 	reflection_object *intern;
6243 
6244 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "hz", &ht, &key) == FAILURE) {
6245 		return;
6246 	}
6247 
6248 	if (Z_TYPE_P(key) == IS_LONG) {
6249 		item = zend_hash_index_find(ht, Z_LVAL_P(key));
6250 	} else if (Z_TYPE_P(key) == IS_STRING) {
6251 		item = zend_symtable_find(ht, Z_STR_P(key));
6252 	} else {
6253 		zend_type_error("Key must be array or string");
6254 		return;
6255 	}
6256 
6257 	if (!item) {
6258 		_DO_THROW("Array key not found");
6259 		return;
6260 	}
6261 
6262 	if (Z_TYPE_P(item) != IS_REFERENCE || is_ignorable_reference(ht, item)) {
6263 		RETURN_NULL();
6264 	}
6265 
6266 	object_init_ex(return_value, reflection_reference_ptr);
6267 	intern = Z_REFLECTION_P(return_value);
6268 	ZVAL_COPY(&intern->obj, item);
6269 	intern->ref_type = REF_TYPE_OTHER;
6270 }
6271 /* }}} */
6272 
6273 /* {{{ proto public int|string ReflectionReference::getId()
6274  *     Returns a unique identifier for the reference.
6275  *     The format of the return value is unspecified and may change. */
ZEND_METHOD(reflection_reference,getId)6276 ZEND_METHOD(reflection_reference, getId)
6277 {
6278 	reflection_object *intern;
6279 	unsigned char digest[20];
6280 	PHP_SHA1_CTX context;
6281 
6282 	if (zend_parse_parameters_none() == FAILURE) {
6283 		return;
6284 	}
6285 
6286 	intern = Z_REFLECTION_P(getThis());
6287 	if (Z_TYPE(intern->obj) != IS_REFERENCE) {
6288 		_DO_THROW("Corrupted ReflectionReference object");
6289 		return;
6290 	}
6291 
6292 	if (!REFLECTION_G(key_initialized)) {
6293 		if (php_random_bytes_throw(&REFLECTION_G(key_initialized), 16) == FAILURE) {
6294 			return;
6295 		}
6296 
6297 		REFLECTION_G(key_initialized) = 1;
6298 	}
6299 
6300 	/* SHA1(ref || key) to avoid directly exposing memory addresses. */
6301 	PHP_SHA1Init(&context);
6302 	PHP_SHA1Update(&context, (unsigned char *) &Z_REF(intern->obj), sizeof(zend_reference *));
6303 	PHP_SHA1Update(&context, REFLECTION_G(key), REFLECTION_KEY_LEN);
6304 	PHP_SHA1Final(digest, &context);
6305 
6306 	RETURN_STRINGL((char *) digest, sizeof(digest));
6307 }
6308 /* }}} */
6309 
6310 /* {{{ method tables */
6311 static const zend_function_entry reflection_exception_functions[] = {
6312 	PHP_FE_END
6313 };
6314 
6315 ZEND_BEGIN_ARG_INFO(arginfo_reflection__void, 0)
6316 ZEND_END_ARG_INFO()
6317 
6318 
6319 ZEND_BEGIN_ARG_INFO(arginfo_reflection_getModifierNames, 0)
6320 	ZEND_ARG_INFO(0, modifiers)
6321 ZEND_END_ARG_INFO()
6322 
6323 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_export, 0, 0, 1)
6324 	ZEND_ARG_OBJ_INFO(0, reflector, Reflector, 0)
6325 	ZEND_ARG_INFO(0, return)
6326 ZEND_END_ARG_INFO()
6327 
6328 static const zend_function_entry reflection_functions[] = {
6329 	ZEND_ME(reflection, getModifierNames, arginfo_reflection_getModifierNames, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6330 	ZEND_DEP_ME(reflection, export, arginfo_reflection_export, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6331 	PHP_FE_END
6332 };
6333 
6334 static const zend_function_entry reflector_functions[] = {
6335 	ZEND_ABSTRACT_ME(reflector, __toString, arginfo_reflection__void)
6336 	PHP_FE_END
6337 };
6338 
6339 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_export, 0, 0, 1)
6340 	ZEND_ARG_INFO(0, name)
6341 	ZEND_ARG_INFO(0, return)
6342 ZEND_END_ARG_INFO()
6343 
6344 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function___construct, 0)
6345 	ZEND_ARG_INFO(0, name)
6346 ZEND_END_ARG_INFO()
6347 
6348 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_invoke, 0, 0, 0)
6349 	ZEND_ARG_INFO(0, args)
6350 ZEND_END_ARG_INFO()
6351 
6352 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function_invokeArgs, 0)
6353 	ZEND_ARG_ARRAY_INFO(0, args, 0)
6354 ZEND_END_ARG_INFO()
6355 
6356 static const zend_function_entry reflection_function_abstract_functions[] = {
6357 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6358 	ZEND_ME(reflection_function, inNamespace, arginfo_reflection__void, 0)
6359 	ZEND_ME(reflection_function, isClosure, arginfo_reflection__void, 0)
6360 	ZEND_ME(reflection_function, isDeprecated, arginfo_reflection__void, 0)
6361 	ZEND_ME(reflection_function, isInternal, arginfo_reflection__void, 0)
6362 	ZEND_ME(reflection_function, isUserDefined, arginfo_reflection__void, 0)
6363 	ZEND_ME(reflection_function, isGenerator, arginfo_reflection__void, 0)
6364 	ZEND_ME(reflection_function, isVariadic, arginfo_reflection__void, 0)
6365 	ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0)
6366 	ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0)
6367 	ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0)
6368 	ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0)
6369 	ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0)
6370 	ZEND_ME(reflection_function, getExtensionName, arginfo_reflection__void, 0)
6371 	ZEND_ME(reflection_function, getFileName, arginfo_reflection__void, 0)
6372 	ZEND_ME(reflection_function, getName, arginfo_reflection__void, 0)
6373 	ZEND_ME(reflection_function, getNamespaceName, arginfo_reflection__void, 0)
6374 	ZEND_ME(reflection_function, getNumberOfParameters, arginfo_reflection__void, 0)
6375 	ZEND_ME(reflection_function, getNumberOfRequiredParameters, arginfo_reflection__void, 0)
6376 	ZEND_ME(reflection_function, getParameters, arginfo_reflection__void, 0)
6377 	ZEND_ME(reflection_function, getShortName, arginfo_reflection__void, 0)
6378 	ZEND_ME(reflection_function, getStartLine, arginfo_reflection__void, 0)
6379 	ZEND_ME(reflection_function, getStaticVariables, arginfo_reflection__void, 0)
6380 	ZEND_ME(reflection_function, returnsReference, arginfo_reflection__void, 0)
6381 	ZEND_ME(reflection_function, hasReturnType, arginfo_reflection__void, 0)
6382 	ZEND_ME(reflection_function, getReturnType, arginfo_reflection__void, 0)
6383 	PHP_FE_END
6384 };
6385 
6386 static const zend_function_entry reflection_function_functions[] = {
6387 	ZEND_ME(reflection_function, __construct, arginfo_reflection_function___construct, 0)
6388 	ZEND_ME(reflection_function, __toString, arginfo_reflection__void, 0)
6389 	ZEND_DEP_ME(reflection_function, export, arginfo_reflection_function_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6390 	ZEND_ME(reflection_function, isDisabled, arginfo_reflection__void, 0)
6391 	ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
6392 	ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
6393 	ZEND_ME(reflection_function, getClosure, arginfo_reflection__void, 0)
6394 	PHP_FE_END
6395 };
6396 
6397 ZEND_BEGIN_ARG_INFO(arginfo_reflection_generator___construct, 0)
6398 	ZEND_ARG_INFO(0, generator)
6399 ZEND_END_ARG_INFO()
6400 
6401 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_generator_trace, 0, 0, 0)
6402 	ZEND_ARG_INFO(0, options)
6403 ZEND_END_ARG_INFO()
6404 
6405 static const zend_function_entry reflection_generator_functions[] = {
6406 	ZEND_ME(reflection_generator, __construct, arginfo_reflection_generator___construct, 0)
6407 	ZEND_ME(reflection_generator, getExecutingLine, arginfo_reflection__void, 0)
6408 	ZEND_ME(reflection_generator, getExecutingFile, arginfo_reflection__void, 0)
6409 	ZEND_ME(reflection_generator, getTrace, arginfo_reflection_generator_trace, 0)
6410 	ZEND_ME(reflection_generator, getFunction, arginfo_reflection__void, 0)
6411 	ZEND_ME(reflection_generator, getThis, arginfo_reflection__void, 0)
6412 	ZEND_ME(reflection_generator, getExecutingGenerator, arginfo_reflection__void, 0)
6413 	PHP_FE_END
6414 };
6415 
6416 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method_export, 0, 0, 2)
6417 	ZEND_ARG_INFO(0, class)
6418 	ZEND_ARG_INFO(0, name)
6419 	ZEND_ARG_INFO(0, return)
6420 ZEND_END_ARG_INFO()
6421 
6422 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method___construct, 0, 0, 1)
6423 	ZEND_ARG_INFO(0, class_or_method)
6424 	ZEND_ARG_INFO(0, name)
6425 ZEND_END_ARG_INFO()
6426 
6427 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invoke, 0)
6428 	ZEND_ARG_INFO(0, object)
6429 	ZEND_ARG_INFO(0, args)
6430 ZEND_END_ARG_INFO()
6431 
6432 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invokeArgs, 0)
6433 	ZEND_ARG_INFO(0, object)
6434 	ZEND_ARG_ARRAY_INFO(0, args, 0)
6435 ZEND_END_ARG_INFO()
6436 
6437 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
6438 	ZEND_ARG_INFO(0, value)
6439 ZEND_END_ARG_INFO()
6440 
6441 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method_getClosure, 0, 0, 0)
6442 	ZEND_ARG_INFO(0, object)
6443 ZEND_END_ARG_INFO()
6444 
6445 static const zend_function_entry reflection_method_functions[] = {
6446 	ZEND_DEP_ME(reflection_method, export, arginfo_reflection_method_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6447 	ZEND_ME(reflection_method, __construct, arginfo_reflection_method___construct, 0)
6448 	ZEND_ME(reflection_method, __toString, arginfo_reflection__void, 0)
6449 	ZEND_ME(reflection_method, isPublic, arginfo_reflection__void, 0)
6450 	ZEND_ME(reflection_method, isPrivate, arginfo_reflection__void, 0)
6451 	ZEND_ME(reflection_method, isProtected, arginfo_reflection__void, 0)
6452 	ZEND_ME(reflection_method, isAbstract, arginfo_reflection__void, 0)
6453 	ZEND_ME(reflection_method, isFinal, arginfo_reflection__void, 0)
6454 	ZEND_ME(reflection_method, isStatic, arginfo_reflection__void, 0)
6455 	ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
6456 	ZEND_ME(reflection_method, isDestructor, arginfo_reflection__void, 0)
6457 	ZEND_ME(reflection_method, getClosure, arginfo_reflection_method_getClosure, 0)
6458 	ZEND_ME(reflection_method, getModifiers, arginfo_reflection__void, 0)
6459 	ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
6460 	ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
6461 	ZEND_ME(reflection_method, getDeclaringClass, arginfo_reflection__void, 0)
6462 	ZEND_ME(reflection_method, getPrototype, arginfo_reflection__void, 0)
6463 	ZEND_ME(reflection_method, setAccessible, arginfo_reflection_method_setAccessible, 0)
6464 	PHP_FE_END
6465 };
6466 
6467 
6468 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_export, 0, 0, 1)
6469 	ZEND_ARG_INFO(0, argument)
6470 	ZEND_ARG_INFO(0, return)
6471 ZEND_END_ARG_INFO()
6472 
6473 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class___construct, 0)
6474 	ZEND_ARG_INFO(0, argument)
6475 ZEND_END_ARG_INFO()
6476 
6477 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getStaticPropertyValue, 0, 0, 1)
6478 	ZEND_ARG_INFO(0, name)
6479 	ZEND_ARG_INFO(0, default)
6480 ZEND_END_ARG_INFO()
6481 
6482 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_setStaticPropertyValue, 0)
6483 	ZEND_ARG_INFO(0, name)
6484 	ZEND_ARG_INFO(0, value)
6485 ZEND_END_ARG_INFO()
6486 
6487 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasMethod, 0)
6488 	ZEND_ARG_INFO(0, name)
6489 ZEND_END_ARG_INFO()
6490 
6491 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getMethod, 0)
6492 	ZEND_ARG_INFO(0, name)
6493 ZEND_END_ARG_INFO()
6494 
6495 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getMethods, 0, 0, 0)
6496 	ZEND_ARG_INFO(0, filter)
6497 ZEND_END_ARG_INFO()
6498 
6499 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasProperty, 0)
6500 	ZEND_ARG_INFO(0, name)
6501 ZEND_END_ARG_INFO()
6502 
6503 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getProperty, 0)
6504 	ZEND_ARG_INFO(0, name)
6505 ZEND_END_ARG_INFO()
6506 
6507 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getProperties, 0, 0, 0)
6508 	ZEND_ARG_INFO(0, filter)
6509 ZEND_END_ARG_INFO()
6510 
6511 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasConstant, 0)
6512 	ZEND_ARG_INFO(0, name)
6513 ZEND_END_ARG_INFO()
6514 
6515 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getConstant, 0)
6516 	ZEND_ARG_INFO(0, name)
6517 ZEND_END_ARG_INFO()
6518 
6519 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isInstance, 0)
6520 	ZEND_ARG_INFO(0, object)
6521 ZEND_END_ARG_INFO()
6522 
6523 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
6524 	ZEND_ARG_INFO(0, args)
6525 ZEND_END_ARG_INFO()
6526 
6527 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstanceWithoutConstructor, 0)
6528 ZEND_END_ARG_INFO()
6529 
6530 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_newInstanceArgs, 0, 0, 0)
6531 	ZEND_ARG_ARRAY_INFO(0, args, 0)
6532 ZEND_END_ARG_INFO()
6533 
6534 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isSubclassOf, 0)
6535 	ZEND_ARG_INFO(0, class)
6536 ZEND_END_ARG_INFO()
6537 
6538 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_implementsInterface, 0)
6539 	ZEND_ARG_INFO(0, interface)
6540 ZEND_END_ARG_INFO()
6541 
6542 static const zend_function_entry reflection_class_functions[] = {
6543 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6544 	ZEND_DEP_ME(reflection_class, export, arginfo_reflection_class_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6545 	ZEND_ME(reflection_class, __construct, arginfo_reflection_class___construct, 0)
6546 	ZEND_ME(reflection_class, __toString, arginfo_reflection__void, 0)
6547 	ZEND_ME(reflection_class, getName, arginfo_reflection__void, 0)
6548 	ZEND_ME(reflection_class, isInternal, arginfo_reflection__void, 0)
6549 	ZEND_ME(reflection_class, isUserDefined, arginfo_reflection__void, 0)
6550 	ZEND_ME(reflection_class, isAnonymous, arginfo_reflection__void, 0)
6551 	ZEND_ME(reflection_class, isInstantiable, arginfo_reflection__void, 0)
6552 	ZEND_ME(reflection_class, isCloneable, arginfo_reflection__void, 0)
6553 	ZEND_ME(reflection_class, getFileName, arginfo_reflection__void, 0)
6554 	ZEND_ME(reflection_class, getStartLine, arginfo_reflection__void, 0)
6555 	ZEND_ME(reflection_class, getEndLine, arginfo_reflection__void, 0)
6556 	ZEND_ME(reflection_class, getDocComment, arginfo_reflection__void, 0)
6557 	ZEND_ME(reflection_class, getConstructor, arginfo_reflection__void, 0)
6558 	ZEND_ME(reflection_class, hasMethod, arginfo_reflection_class_hasMethod, 0)
6559 	ZEND_ME(reflection_class, getMethod, arginfo_reflection_class_getMethod, 0)
6560 	ZEND_ME(reflection_class, getMethods, arginfo_reflection_class_getMethods, 0)
6561 	ZEND_ME(reflection_class, hasProperty, arginfo_reflection_class_hasProperty, 0)
6562 	ZEND_ME(reflection_class, getProperty, arginfo_reflection_class_getProperty, 0)
6563 	ZEND_ME(reflection_class, getProperties, arginfo_reflection_class_getProperties, 0)
6564 	ZEND_ME(reflection_class, hasConstant, arginfo_reflection_class_hasConstant, 0)
6565 	ZEND_ME(reflection_class, getConstants, arginfo_reflection__void, 0)
6566 	ZEND_ME(reflection_class, getReflectionConstants, arginfo_reflection__void, 0)
6567 	ZEND_ME(reflection_class, getConstant, arginfo_reflection_class_getConstant, 0)
6568 	ZEND_ME(reflection_class, getReflectionConstant, arginfo_reflection_class_getConstant, 0)
6569 	ZEND_ME(reflection_class, getInterfaces, arginfo_reflection__void, 0)
6570 	ZEND_ME(reflection_class, getInterfaceNames, arginfo_reflection__void, 0)
6571 	ZEND_ME(reflection_class, isInterface, arginfo_reflection__void, 0)
6572 	ZEND_ME(reflection_class, getTraits, arginfo_reflection__void, 0)
6573 	ZEND_ME(reflection_class, getTraitNames, arginfo_reflection__void, 0)
6574 	ZEND_ME(reflection_class, getTraitAliases, arginfo_reflection__void, 0)
6575 	ZEND_ME(reflection_class, isTrait, arginfo_reflection__void, 0)
6576 	ZEND_ME(reflection_class, isAbstract, arginfo_reflection__void, 0)
6577 	ZEND_ME(reflection_class, isFinal, arginfo_reflection__void, 0)
6578 	ZEND_ME(reflection_class, getModifiers, arginfo_reflection__void, 0)
6579 	ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
6580 	ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
6581 	ZEND_ME(reflection_class, newInstanceWithoutConstructor, arginfo_reflection_class_newInstanceWithoutConstructor, 0)
6582 	ZEND_ME(reflection_class, newInstanceArgs, arginfo_reflection_class_newInstanceArgs, 0)
6583 	ZEND_ME(reflection_class, getParentClass, arginfo_reflection__void, 0)
6584 	ZEND_ME(reflection_class, isSubclassOf, arginfo_reflection_class_isSubclassOf, 0)
6585 	ZEND_ME(reflection_class, getStaticProperties, arginfo_reflection__void, 0)
6586 	ZEND_ME(reflection_class, getStaticPropertyValue, arginfo_reflection_class_getStaticPropertyValue, 0)
6587 	ZEND_ME(reflection_class, setStaticPropertyValue, arginfo_reflection_class_setStaticPropertyValue, 0)
6588 	ZEND_ME(reflection_class, getDefaultProperties, arginfo_reflection__void, 0)
6589 	ZEND_ME(reflection_class, isIterable, arginfo_reflection__void, 0)
6590 	ZEND_MALIAS(reflection_class, isIterateable, isIterable, arginfo_reflection__void, 0)
6591 	ZEND_ME(reflection_class, implementsInterface, arginfo_reflection_class_implementsInterface, 0)
6592 	ZEND_ME(reflection_class, getExtension, arginfo_reflection__void, 0)
6593 	ZEND_ME(reflection_class, getExtensionName, arginfo_reflection__void, 0)
6594 	ZEND_ME(reflection_class, inNamespace, arginfo_reflection__void, 0)
6595 	ZEND_ME(reflection_class, getNamespaceName, arginfo_reflection__void, 0)
6596 	ZEND_ME(reflection_class, getShortName, arginfo_reflection__void, 0)
6597 	PHP_FE_END
6598 };
6599 
6600 
6601 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_object_export, 0, 0, 1)
6602 	ZEND_ARG_INFO(0, argument)
6603 	ZEND_ARG_INFO(0, return)
6604 ZEND_END_ARG_INFO()
6605 
6606 ZEND_BEGIN_ARG_INFO(arginfo_reflection_object___construct, 0)
6607 	ZEND_ARG_INFO(0, argument)
6608 ZEND_END_ARG_INFO()
6609 
6610 static const zend_function_entry reflection_object_functions[] = {
6611 	ZEND_DEP_ME(reflection_object, export, arginfo_reflection_object_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6612 	ZEND_ME(reflection_object, __construct, arginfo_reflection_object___construct, 0)
6613 	PHP_FE_END
6614 };
6615 
6616 
6617 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_export, 0, 0, 2)
6618 	ZEND_ARG_INFO(0, class)
6619 	ZEND_ARG_INFO(0, name)
6620 	ZEND_ARG_INFO(0, return)
6621 ZEND_END_ARG_INFO()
6622 
6623 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property___construct, 0, 0, 2)
6624 	ZEND_ARG_INFO(0, class)
6625 	ZEND_ARG_INFO(0, name)
6626 ZEND_END_ARG_INFO()
6627 
6628 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_getValue, 0, 0, 0)
6629 	ZEND_ARG_INFO(0, object)
6630 ZEND_END_ARG_INFO()
6631 
6632 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_setValue, 0, 0, 1)
6633 	ZEND_ARG_INFO(0, object)
6634 	ZEND_ARG_INFO(0, value)
6635 ZEND_END_ARG_INFO()
6636 
6637 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_isInitialized, 0, 0, 0)
6638 	ZEND_ARG_INFO(0, object)
6639 ZEND_END_ARG_INFO()
6640 
6641 ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setAccessible, 0)
6642 	ZEND_ARG_INFO(0, visible)
6643 ZEND_END_ARG_INFO()
6644 
6645 static const zend_function_entry reflection_property_functions[] = {
6646 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6647 	ZEND_DEP_ME(reflection_property, export, arginfo_reflection_property_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6648 	ZEND_ME(reflection_property, __construct, arginfo_reflection_property___construct, 0)
6649 	ZEND_ME(reflection_property, __toString, arginfo_reflection__void, 0)
6650 	ZEND_ME(reflection_property, getName, arginfo_reflection__void, 0)
6651 	ZEND_ME(reflection_property, getValue, arginfo_reflection_property_getValue, 0)
6652 	ZEND_ME(reflection_property, setValue, arginfo_reflection_property_setValue, 0)
6653 	ZEND_ME(reflection_property, isInitialized, arginfo_reflection_property_isInitialized, 0)
6654 	ZEND_ME(reflection_property, isPublic, arginfo_reflection__void, 0)
6655 	ZEND_ME(reflection_property, isPrivate, arginfo_reflection__void, 0)
6656 	ZEND_ME(reflection_property, isProtected, arginfo_reflection__void, 0)
6657 	ZEND_ME(reflection_property, isStatic, arginfo_reflection__void, 0)
6658 	ZEND_ME(reflection_property, isDefault, arginfo_reflection__void, 0)
6659 	ZEND_ME(reflection_property, getModifiers, arginfo_reflection__void, 0)
6660 	ZEND_ME(reflection_property, getDeclaringClass, arginfo_reflection__void, 0)
6661 	ZEND_ME(reflection_property, getDocComment, arginfo_reflection__void, 0)
6662 	ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0)
6663 	ZEND_ME(reflection_property, getType, arginfo_reflection__void, 0)
6664 	ZEND_ME(reflection_property, hasType, arginfo_reflection__void, 0)
6665 	PHP_FE_END
6666 };
6667 
6668 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant_export, 0, 0, 2)
6669 	ZEND_ARG_INFO(0, class)
6670 	ZEND_ARG_INFO(0, name)
6671 	ZEND_ARG_INFO(0, return)
6672 ZEND_END_ARG_INFO()
6673 
6674 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant___construct, 0, 0, 2)
6675 	ZEND_ARG_INFO(0, class)
6676 	ZEND_ARG_INFO(0, name)
6677 ZEND_END_ARG_INFO()
6678 
6679 static const zend_function_entry reflection_class_constant_functions[] = {
6680 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6681 	ZEND_DEP_ME(reflection_class_constant, export, arginfo_reflection_class_constant_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6682 	ZEND_ME(reflection_class_constant, __construct, arginfo_reflection_class_constant___construct, 0)
6683 	ZEND_ME(reflection_class_constant, __toString, arginfo_reflection__void, 0)
6684 	ZEND_ME(reflection_class_constant, getName, arginfo_reflection__void, 0)
6685 	ZEND_ME(reflection_class_constant, getValue, arginfo_reflection__void, 0)
6686 	ZEND_ME(reflection_class_constant, isPublic, arginfo_reflection__void, 0)
6687 	ZEND_ME(reflection_class_constant, isPrivate, arginfo_reflection__void, 0)
6688 	ZEND_ME(reflection_class_constant, isProtected, arginfo_reflection__void, 0)
6689 	ZEND_ME(reflection_class_constant, getModifiers, arginfo_reflection__void, 0)
6690 	ZEND_ME(reflection_class_constant, getDeclaringClass, arginfo_reflection__void, 0)
6691 	ZEND_ME(reflection_class_constant, getDocComment, arginfo_reflection__void, 0)
6692 	PHP_FE_END
6693 };
6694 
6695 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_parameter_export, 0, 0, 2)
6696 	ZEND_ARG_INFO(0, function)
6697 	ZEND_ARG_INFO(0, parameter)
6698 	ZEND_ARG_INFO(0, return)
6699 ZEND_END_ARG_INFO()
6700 
6701 ZEND_BEGIN_ARG_INFO(arginfo_reflection_parameter___construct, 0)
6702 	ZEND_ARG_INFO(0, function)
6703 	ZEND_ARG_INFO(0, parameter)
6704 ZEND_END_ARG_INFO()
6705 
6706 static const zend_function_entry reflection_parameter_functions[] = {
6707 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6708 	ZEND_DEP_ME(reflection_parameter, export, arginfo_reflection_parameter_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6709 	ZEND_ME(reflection_parameter, __construct, arginfo_reflection_parameter___construct, 0)
6710 	ZEND_ME(reflection_parameter, __toString, arginfo_reflection__void, 0)
6711 	ZEND_ME(reflection_parameter, getName, arginfo_reflection__void, 0)
6712 	ZEND_ME(reflection_parameter, isPassedByReference, arginfo_reflection__void, 0)
6713 	ZEND_ME(reflection_parameter, canBePassedByValue, arginfo_reflection__void, 0)
6714 	ZEND_ME(reflection_parameter, getDeclaringFunction, arginfo_reflection__void, 0)
6715 	ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
6716 	ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
6717 	ZEND_ME(reflection_parameter, hasType, arginfo_reflection__void, 0)
6718 	ZEND_ME(reflection_parameter, getType, arginfo_reflection__void, 0)
6719 	ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
6720 	ZEND_ME(reflection_parameter, isCallable, arginfo_reflection__void, 0)
6721 	ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
6722 	ZEND_ME(reflection_parameter, getPosition, arginfo_reflection__void, 0)
6723 	ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
6724 	ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_reflection__void, 0)
6725 	ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0)
6726 	ZEND_ME(reflection_parameter, isDefaultValueConstant, arginfo_reflection__void, 0)
6727 	ZEND_ME(reflection_parameter, getDefaultValueConstantName, arginfo_reflection__void, 0)
6728 	ZEND_ME(reflection_parameter, isVariadic, arginfo_reflection__void, 0)
6729 	PHP_FE_END
6730 };
6731 
6732 static const zend_function_entry reflection_type_functions[] = {
6733 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6734 	ZEND_ME(reflection_type, allowsNull, arginfo_reflection__void, 0)
6735 	ZEND_ME(reflection_type, isBuiltin, arginfo_reflection__void, 0)
6736 	ZEND_ME(reflection_type, __toString, arginfo_reflection__void, ZEND_ACC_DEPRECATED)
6737 	PHP_FE_END
6738 };
6739 
6740 static const zend_function_entry reflection_named_type_functions[] = {
6741 	ZEND_ME(reflection_named_type, getName, arginfo_reflection__void, 0)
6742 	PHP_FE_END
6743 };
6744 
6745 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
6746 	ZEND_ARG_INFO(0, name)
6747 	ZEND_ARG_INFO(0, return)
6748 ZEND_END_ARG_INFO()
6749 
6750 ZEND_BEGIN_ARG_INFO(arginfo_reflection_extension___construct, 0)
6751 	ZEND_ARG_INFO(0, name)
6752 ZEND_END_ARG_INFO()
6753 
6754 static const zend_function_entry reflection_extension_functions[] = {
6755 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6756 	ZEND_DEP_ME(reflection_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6757 	ZEND_ME(reflection_extension, __construct, arginfo_reflection_extension___construct, 0)
6758 	ZEND_ME(reflection_extension, __toString, arginfo_reflection__void, 0)
6759 	ZEND_ME(reflection_extension, getName, arginfo_reflection__void, 0)
6760 	ZEND_ME(reflection_extension, getVersion, arginfo_reflection__void, 0)
6761 	ZEND_ME(reflection_extension, getFunctions, arginfo_reflection__void, 0)
6762 	ZEND_ME(reflection_extension, getConstants, arginfo_reflection__void, 0)
6763 	ZEND_ME(reflection_extension, getINIEntries, arginfo_reflection__void, 0)
6764 	ZEND_ME(reflection_extension, getClasses, arginfo_reflection__void, 0)
6765 	ZEND_ME(reflection_extension, getClassNames, arginfo_reflection__void, 0)
6766 	ZEND_ME(reflection_extension, getDependencies, arginfo_reflection__void, 0)
6767 	ZEND_ME(reflection_extension, info, arginfo_reflection__void, 0)
6768 	ZEND_ME(reflection_extension, isPersistent, arginfo_reflection__void, 0)
6769 	ZEND_ME(reflection_extension, isTemporary, arginfo_reflection__void, 0)
6770 	PHP_FE_END
6771 };
6772 
6773 ZEND_BEGIN_ARG_INFO(arginfo_reflection_zend_extension___construct, 0)
6774 	ZEND_ARG_INFO(0, name)
6775 ZEND_END_ARG_INFO()
6776 
6777 static const zend_function_entry reflection_zend_extension_functions[] = {
6778 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6779 	ZEND_DEP_ME(reflection_zend_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6780 	ZEND_ME(reflection_zend_extension, __construct, arginfo_reflection_zend_extension___construct, 0)
6781 	ZEND_ME(reflection_zend_extension, __toString, arginfo_reflection__void, 0)
6782 	ZEND_ME(reflection_zend_extension, getName, arginfo_reflection__void, 0)
6783 	ZEND_ME(reflection_zend_extension, getVersion, arginfo_reflection__void, 0)
6784 	ZEND_ME(reflection_zend_extension, getAuthor, arginfo_reflection__void, 0)
6785 	ZEND_ME(reflection_zend_extension, getURL, arginfo_reflection__void, 0)
6786 	ZEND_ME(reflection_zend_extension, getCopyright, arginfo_reflection__void, 0)
6787 	PHP_FE_END
6788 };
6789 
6790 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_reference_fromArrayElement, 0, 0, 2)
6791 	ZEND_ARG_INFO(0, array)
6792 	ZEND_ARG_INFO(0, key)
6793 ZEND_END_ARG_INFO()
6794 
6795 static const zend_function_entry reflection_reference_functions[] = {
6796 	ZEND_ME(reflection_reference, fromArrayElement, arginfo_reflection_reference_fromArrayElement, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6797 	ZEND_ME(reflection_reference, getId, arginfo_reflection__void, ZEND_ACC_PUBLIC)
6798 
6799 	/* Always throwing dummy methods */
6800 	ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE)
6801 	ZEND_ME(reflection_reference, __construct, arginfo_reflection__void, ZEND_ACC_PRIVATE)
6802 	PHP_FE_END
6803 };
6804 /* }}} */
6805 
6806 static const zend_function_entry reflection_ext_functions[] = { /* {{{ */
6807 	PHP_FE_END
6808 }; /* }}} */
6809 
6810 /* {{{ _reflection_write_property */
_reflection_write_property(zval * object,zval * member,zval * value,void ** cache_slot)6811 static zval *_reflection_write_property(zval *object, zval *member, zval *value, void **cache_slot)
6812 {
6813 	if ((Z_TYPE_P(member) == IS_STRING)
6814 		&& zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STR_P(member))
6815 		&& ((Z_STRLEN_P(member) == sizeof("name") - 1  && !memcmp(Z_STRVAL_P(member), "name",  sizeof("name")))
6816 			|| (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
6817 	{
6818 		zend_throw_exception_ex(reflection_exception_ptr, 0,
6819 			"Cannot set read-only property %s::$%s", ZSTR_VAL(Z_OBJCE_P(object)->name), Z_STRVAL_P(member));
6820 		return &EG(uninitialized_zval);
6821 	}
6822 	else
6823 	{
6824 		return zend_std_write_property(object, member, value, cache_slot);
6825 	}
6826 }
6827 /* }}} */
6828 
reflection_init_class_handlers(zend_class_entry * ce)6829 static void reflection_init_class_handlers(zend_class_entry *ce) {
6830 	ce->create_object = reflection_objects_new;
6831 	ce->serialize = zend_class_serialize_deny;
6832 	ce->unserialize = zend_class_unserialize_deny;
6833 }
6834 
PHP_MINIT_FUNCTION(reflection)6835 PHP_MINIT_FUNCTION(reflection) /* {{{ */
6836 {
6837 	zend_class_entry _reflection_entry;
6838 
6839 	memcpy(&reflection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
6840 	reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo);
6841 	reflection_object_handlers.free_obj = reflection_free_objects_storage;
6842 	reflection_object_handlers.clone_obj = NULL;
6843 	reflection_object_handlers.write_property = _reflection_write_property;
6844 	reflection_object_handlers.get_gc = reflection_get_gc;
6845 
6846 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", reflection_exception_functions);
6847 	reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_ce_exception);
6848 
6849 	INIT_CLASS_ENTRY(_reflection_entry, "Reflection", reflection_functions);
6850 	reflection_ptr = zend_register_internal_class(&_reflection_entry);
6851 
6852 	INIT_CLASS_ENTRY(_reflection_entry, "Reflector", reflector_functions);
6853 	reflector_ptr = zend_register_internal_interface(&_reflection_entry);
6854 
6855 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", reflection_function_abstract_functions);
6856 	reflection_init_class_handlers(&_reflection_entry);
6857 	reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry);
6858 	zend_class_implements(reflection_function_abstract_ptr, 1, reflector_ptr);
6859 	zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT);
6860 
6861 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", reflection_function_functions);
6862 	reflection_init_class_handlers(&_reflection_entry);
6863 	reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
6864 	zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6865 
6866 	REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
6867 
6868 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionGenerator", reflection_generator_functions);
6869 	reflection_init_class_handlers(&_reflection_entry);
6870 	reflection_generator_ptr = zend_register_internal_class(&_reflection_entry);
6871 
6872 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions);
6873 	reflection_init_class_handlers(&_reflection_entry);
6874 	reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry);
6875 	zend_class_implements(reflection_parameter_ptr, 1, reflector_ptr);
6876 	zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6877 
6878 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", reflection_type_functions);
6879 	reflection_init_class_handlers(&_reflection_entry);
6880 	reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
6881 
6882 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", reflection_named_type_functions);
6883 	reflection_init_class_handlers(&_reflection_entry);
6884 	reflection_named_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
6885 
6886 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
6887 	reflection_init_class_handlers(&_reflection_entry);
6888 	reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
6889 	zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6890 	zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6891 
6892 	REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_STATIC", ZEND_ACC_STATIC);
6893 	REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PUBLIC", ZEND_ACC_PUBLIC);
6894 	REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PROTECTED", ZEND_ACC_PROTECTED);
6895 	REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PRIVATE", ZEND_ACC_PRIVATE);
6896 	REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_ABSTRACT", ZEND_ACC_ABSTRACT);
6897 	REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
6898 
6899 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions);
6900 	reflection_init_class_handlers(&_reflection_entry);
6901 	reflection_class_ptr = zend_register_internal_class(&_reflection_entry);
6902 	zend_class_implements(reflection_class_ptr, 1, reflector_ptr);
6903 	zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6904 
6905 	/* IS_IMPLICIT_ABSTRACT is not longer used */
6906 	REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_IMPLICIT_ABSTRACT", ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
6907 	REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_EXPLICIT_ABSTRACT", ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
6908 	REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL);
6909 
6910 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions);
6911 	reflection_init_class_handlers(&_reflection_entry);
6912 	reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr);
6913 
6914 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", reflection_property_functions);
6915 	reflection_init_class_handlers(&_reflection_entry);
6916 	reflection_property_ptr = zend_register_internal_class(&_reflection_entry);
6917 	zend_class_implements(reflection_property_ptr, 1, reflector_ptr);
6918 	zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6919 	zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6920 
6921 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", reflection_class_constant_functions);
6922 	reflection_init_class_handlers(&_reflection_entry);
6923 	reflection_class_constant_ptr = zend_register_internal_class(&_reflection_entry);
6924 	zend_class_implements(reflection_class_constant_ptr, 1, reflector_ptr);
6925 	zend_declare_property_string(reflection_class_constant_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6926 	zend_declare_property_string(reflection_class_constant_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6927 
6928 	REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
6929 	REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
6930 	REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
6931 	REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
6932 
6933 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions);
6934 	reflection_init_class_handlers(&_reflection_entry);
6935 	reflection_extension_ptr = zend_register_internal_class(&_reflection_entry);
6936 	zend_class_implements(reflection_extension_ptr, 1, reflector_ptr);
6937 	zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6938 
6939 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", reflection_zend_extension_functions);
6940 	reflection_init_class_handlers(&_reflection_entry);
6941 	reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry);
6942 	zend_class_implements(reflection_zend_extension_ptr, 1, reflector_ptr);
6943 	zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6944 
6945 	INIT_CLASS_ENTRY(_reflection_entry, "ReflectionReference", reflection_reference_functions);
6946 	reflection_init_class_handlers(&_reflection_entry);
6947 	_reflection_entry.ce_flags |= ZEND_ACC_FINAL;
6948 	reflection_reference_ptr = zend_register_internal_class(&_reflection_entry);
6949 
6950 	REFLECTION_G(key_initialized) = 0;
6951 
6952 	return SUCCESS;
6953 } /* }}} */
6954 
PHP_MINFO_FUNCTION(reflection)6955 PHP_MINFO_FUNCTION(reflection) /* {{{ */
6956 {
6957 	php_info_print_table_start();
6958 	php_info_print_table_row(2, "Reflection", "enabled");
6959 	php_info_print_table_end();
6960 } /* }}} */
6961 
6962 zend_module_entry reflection_module_entry = { /* {{{ */
6963 	STANDARD_MODULE_HEADER,
6964 	"Reflection",
6965 	reflection_ext_functions,
6966 	PHP_MINIT(reflection),
6967 	NULL,
6968 	NULL,
6969 	NULL,
6970 	PHP_MINFO(reflection),
6971 	PHP_REFLECTION_VERSION,
6972 	ZEND_MODULE_GLOBALS(reflection),
6973 	NULL,
6974 	NULL,
6975 	NULL,
6976 	STANDARD_MODULE_PROPERTIES_EX
6977 }; /* }}} */
6978