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