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