php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
php_reflection.c
Go to the documentation of this file.
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#include "zend_compile.h"
22#include "zend_execute.h"
23#include "zend_lazy_objects.h"
25#include "zend_type_info.h"
26#include "zend_types.h"
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31#include "php.h"
32#include "php_ini.h"
33#include "php_reflection.h"
34#include "ext/standard/info.h"
35#include "ext/standard/sha1.h"
37
38#include "zend.h"
39#include "zend_API.h"
40#include "zend_ast.h"
41#include "zend_attributes.h"
42#include "zend_exceptions.h"
43#include "zend_operators.h"
44#include "zend_constants.h"
45#include "zend_ini.h"
46#include "zend_interfaces.h"
47#include "zend_closures.h"
48#include "zend_generators.h"
49#include "zend_extensions.h"
51#include "zend_smart_str.h"
52#include "zend_enum.h"
53#include "zend_fibers.h"
54
55#define REFLECTION_ATTRIBUTE_IS_INSTANCEOF (1 << 1)
56
58
59/* Key used to avoid leaking addresses in ReflectionProperty::getId() */
60#define REFLECTION_KEY_LEN 16
63 unsigned char key[REFLECTION_KEY_LEN];
66
67#define REFLECTION_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(reflection, v)
68
69static zend_always_inline zval *reflection_prop_name(zval *object) {
70 /* $name is always in the first property slot. */
71 ZEND_ASSERT(Z_OBJCE_P(object)->default_properties_count >= 1);
72 return &Z_OBJ_P(object)->properties_table[0];
73}
74
75static zend_always_inline zval *reflection_prop_class(zval *object) {
76 /* $class is always in the second property slot. */
77 ZEND_ASSERT(Z_OBJCE_P(object)->default_properties_count >= 2);
78 return &Z_OBJ_P(object)->properties_table[1];
79}
80
81/* Class entry pointers */
108
109/* Exception throwing macro */
110#define _DO_THROW(msg) \
111 zend_throw_exception(reflection_exception_ptr, msg, 0);
112
113#define GET_REFLECTION_OBJECT() do { \
114 intern = Z_REFLECTION_P(ZEND_THIS); \
115 if (intern->ptr == NULL) { \
116 if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) { \
117 RETURN_THROWS(); \
118 } \
119 zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object"); \
120 RETURN_THROWS(); \
121 } \
122} while (0)
123
124#define GET_REFLECTION_OBJECT_PTR(target) do { \
125 GET_REFLECTION_OBJECT(); \
126 target = intern->ptr; \
127} while (0)
128
129/* {{{ Object structure */
130
131/* Struct for properties */
136
137/* Struct for parameters */
144
145/* Struct for type hints */
146typedef struct _type_reference {
148 /* Whether to use backwards compatible null representation */
151
152/* Struct for attributes */
160
172
173/* Struct for reflection objects */
181
182static inline reflection_object *reflection_object_from_obj(zend_object *obj) {
183 return (reflection_object*)((char*)(obj) - XtOffsetOf(reflection_object, zo));
184}
185
186#define Z_REFLECTION_P(zv) reflection_object_from_obj(Z_OBJ_P((zv)))
187/* }}} */
188
189static zend_object_handlers reflection_object_handlers;
190
191static zend_always_inline uint32_t prop_get_flags(const property_reference *ref) {
192 return ref->prop ? ref->prop->flags : ZEND_ACC_PUBLIC;
193}
194
195static inline bool is_closure_invoke(const zend_class_entry *ce, const zend_string *lcname) {
196 return ce == zend_ce_closure
198}
199
200static zend_function *_copy_function(zend_function *fptr) /* {{{ */
201{
202 if (fptr
204 {
205 zend_function *copy_fptr;
206 copy_fptr = emalloc(sizeof(zend_function));
207 memcpy(copy_fptr, fptr, sizeof(zend_function));
208 copy_fptr->internal_function.function_name = zend_string_copy(fptr->internal_function.function_name);
209 return copy_fptr;
210 } else {
211 /* no copy needed */
212 return fptr;
213 }
214}
215/* }}} */
216
217static void _free_function(zend_function *fptr) /* {{{ */
218{
219 if (fptr
221 {
224 }
225}
226/* }}} */
227
228static void reflection_free_property_reference(property_reference *reference)
229{
231 efree(reference);
232}
233
234static void reflection_free_parameter_reference(parameter_reference *reference)
235{
236 _free_function(reference->fptr);
237 efree(reference);
238}
239
240static void reflection_free_objects_storage(zend_object *object) /* {{{ */
241{
242 reflection_object *intern = reflection_object_from_obj(object);
243
244 if (intern->ptr) {
245 switch (intern->ref_type) {
247 reflection_free_parameter_reference(intern->ptr);
248 break;
249 case REF_TYPE_TYPE:
250 {
251 type_reference *type_ref = intern->ptr;
252 if (ZEND_TYPE_HAS_NAME(type_ref->type)) {
253 zend_string_release(ZEND_TYPE_NAME(type_ref->type));
254 }
255 efree(type_ref);
256 break;
257 }
259 _free_function(intern->ptr);
260 break;
262 reflection_free_property_reference(intern->ptr);
263 break;
264 case REF_TYPE_ATTRIBUTE: {
265 attribute_reference *attr_ref = intern->ptr;
266 if (attr_ref->filename) {
267 zend_string_release(attr_ref->filename);
268 }
269 efree(intern->ptr);
270 break;
271 }
273 case REF_TYPE_FIBER:
275 case REF_TYPE_OTHER:
276 break;
277 }
278 }
279 intern->ptr = NULL;
280 zval_ptr_dtor(&intern->obj);
281 zend_object_std_dtor(object);
282}
283/* }}} */
284
285static HashTable *reflection_get_gc(zend_object *obj, zval **gc_data, int *gc_data_count) /* {{{ */
286{
287 reflection_object *intern = reflection_object_from_obj(obj);
288 *gc_data = &intern->obj;
289 *gc_data_count = 1;
290 return zend_std_get_properties(obj);
291}
292/* }}} */
293
294static zend_object *reflection_objects_new(zend_class_entry *class_type) /* {{{ */
295{
296 reflection_object *intern = zend_object_alloc(sizeof(reflection_object), class_type);
297
298 zend_object_std_init(&intern->zo, class_type);
299 object_properties_init(&intern->zo, class_type);
300 return &intern->zo;
301}
302/* }}} */
303
304static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{ */
305{
306 object_init_ex(object, pce);
307 return object;
308}
309/* }}} */
310
311static void _const_string(smart_str *str, const char *name, zval *value, const char *indent);
312static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, const char* indent);
313static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, const char* indent);
314static void _class_const_string(smart_str *str, const zend_string *name, zend_class_constant *c, const char* indent);
315static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const char *indent);
316static void _extension_string(smart_str *str, const zend_module_entry *module, const char *indent);
317static void _zend_extension_string(smart_str *str, const zend_extension *extension, const char *indent);
318
319/* {{{ _class_string */
320static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const char *indent)
321{
322 int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
323 zend_string *sub_indent = strpprintf(0, "%s ", indent);
324
325 /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
326 if (ce->doc_comment) {
327 smart_str_append_printf(str, "%s%s", indent, ZSTR_VAL(ce->doc_comment));
328 smart_str_appendc(str, '\n');
329 }
330
331 if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
332 smart_str_append_printf(str, "%sObject of class [ ", indent);
333 } else {
334 char *kind = "Class";
335 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
336 kind = "Interface";
337 } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
338 kind = "Trait";
339 }
340 smart_str_append_printf(str, "%s%s [ ", indent, kind);
341 }
342 smart_str_append_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
343 if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
345 }
346 smart_str_append_printf(str, "> ");
347 if (ce->get_iterator != NULL) {
348 smart_str_append_printf(str, "<iterateable> ");
349 }
350 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
351 smart_str_append_printf(str, "interface ");
352 } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
353 smart_str_append_printf(str, "trait ");
354 } else {
356 smart_str_append_printf(str, "abstract ");
357 }
358 if (ce->ce_flags & ZEND_ACC_FINAL) {
359 smart_str_append_printf(str, "final ");
360 }
362 smart_str_append_printf(str, "readonly ");
363 }
364 smart_str_append_printf(str, "class ");
365 }
366 smart_str_append_printf(str, "%s", ZSTR_VAL(ce->name));
367 if (ce->parent) {
368 smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name));
369 }
370
371 if (ce->num_interfaces) {
372 uint32_t i;
373
375 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
376 smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->interfaces[0]->name));
377 } else {
378 smart_str_append_printf(str, " implements %s", ZSTR_VAL(ce->interfaces[0]->name));
379 }
380 for (i = 1; i < ce->num_interfaces; ++i) {
381 smart_str_append_printf(str, ", %s", ZSTR_VAL(ce->interfaces[i]->name));
382 }
383 }
384 smart_str_append_printf(str, " ] {\n");
385
386 /* The information where a class is declared is only available for user classes */
387 if (ce->type == ZEND_USER_CLASS) {
388 smart_str_append_printf(str, "%s @@ %s %d-%d\n", indent, ZSTR_VAL(ce->info.user.filename),
390 }
391
392 /* Constants */
393 smart_str_append_printf(str, "\n");
394 count = zend_hash_num_elements(&ce->constants_table);
395 smart_str_append_printf(str, "%s - Constants [%d] {\n", indent, count);
396 if (count > 0) {
399
401 _class_const_string(str, key, c, ZSTR_VAL(sub_indent));
402 if (UNEXPECTED(EG(exception))) {
403 zend_string_release(sub_indent);
404 return;
405 }
407 }
408 smart_str_append_printf(str, "%s }\n", indent);
409
410 /* Static properties */
411 /* counting static properties */
412 count = zend_hash_num_elements(&ce->properties_info);
413 if (count > 0) {
414 zend_property_info *prop;
415
417 if ((prop->flags & ZEND_ACC_PRIVATE) && prop->ce != ce) {
418 count_shadow_props++;
419 } else if (prop->flags & ZEND_ACC_STATIC) {
420 count_static_props++;
421 }
423 }
424
425 /* static properties */
426 smart_str_append_printf(str, "\n%s - Static properties [%d] {\n", indent, count_static_props);
427 if (count_static_props > 0) {
428 zend_property_info *prop;
429
431 if ((prop->flags & ZEND_ACC_STATIC) && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
432 _property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
433 }
435 }
436 smart_str_append_printf(str, "%s }\n", indent);
437
438 /* Static methods */
439 /* counting static methods */
440 count = zend_hash_num_elements(&ce->function_table);
441 if (count > 0) {
442 zend_function *mptr;
443
445 if ((mptr->common.fn_flags & ZEND_ACC_STATIC)
446 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
447 {
448 count_static_funcs++;
449 }
451 }
452
453 /* static methods */
454 smart_str_append_printf(str, "\n%s - Static methods [%d] {", indent, count_static_funcs);
455 if (count_static_funcs > 0) {
456 zend_function *mptr;
457
459 if ((mptr->common.fn_flags & ZEND_ACC_STATIC)
460 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
461 {
462 smart_str_append_printf(str, "\n");
463 _function_string(str, mptr, ce, ZSTR_VAL(sub_indent));
464 }
466 } else {
467 smart_str_append_printf(str, "\n");
468 }
469 smart_str_append_printf(str, "%s }\n", indent);
470
471 /* Default/Implicit properties */
472 count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
473 smart_str_append_printf(str, "\n%s - Properties [%d] {\n", indent, count);
474 if (count > 0) {
475 zend_property_info *prop;
476
478 if (!(prop->flags & ZEND_ACC_STATIC)
479 && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
480 _property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
481 }
483 }
484 smart_str_append_printf(str, "%s }\n", indent);
485
486 if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
488 zend_string *prop_name;
489 smart_str prop_str = {0};
490
491 count = 0;
492 if (properties && zend_hash_num_elements(properties)) {
493 ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) {
494 if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */
495 if (!zend_hash_exists(&ce->properties_info, prop_name)) {
496 count++;
497 _property_string(&prop_str, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent));
498 }
499 }
501 }
502
503 smart_str_append_printf(str, "\n%s - Dynamic properties [%d] {\n", indent, count);
504 smart_str_append_smart_str(str, &prop_str);
505 smart_str_append_printf(str, "%s }\n", indent);
506 smart_str_free(&prop_str);
507 }
508
509 /* Non static methods */
510 count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
511 if (count > 0) {
512 zend_function *mptr;
513 smart_str method_str = {0};
514
515 count = 0;
517 if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
518 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
519 {
520 zend_function *closure;
521 /* see if this is a closure */
522 if (obj && is_closure_invoke(ce, mptr->common.function_name)
523 && (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
524 {
525 mptr = closure;
526 } else {
527 closure = NULL;
528 }
529 smart_str_appendc(&method_str, '\n');
530 _function_string(&method_str, mptr, ce, ZSTR_VAL(sub_indent));
531 count++;
532 _free_function(closure);
533 }
535 smart_str_append_printf(str, "\n%s - Methods [%d] {", indent, count);
536 smart_str_append_smart_str(str, &method_str);
537 if (!count) {
538 smart_str_append_printf(str, "\n");
539 }
540 smart_str_free(&method_str);
541 } else {
542 smart_str_append_printf(str, "\n%s - Methods [0] {\n", indent);
543 }
544 smart_str_append_printf(str, "%s }\n", indent);
545
546 smart_str_append_printf(str, "%s}\n", indent);
547 zend_string_release_ex(sub_indent, 0);
548}
549/* }}} */
550
551/* {{{ _const_string */
552static void _const_string(smart_str *str, const char *name, zval *value, const char *indent)
553{
554 const char *type = zend_zval_type_name(value);
555 uint32_t flags = Z_CONSTANT_FLAGS_P(value);
556
557 smart_str_appends(str, indent);
558 smart_str_appends(str, "Constant [ ");
559
561 bool first = true;
562 smart_str_appends(str, "<");
563
564#define DUMP_CONST_FLAG(flag, output) \
565 do { \
566 if (flags & flag) { \
567 if (!first) smart_str_appends(str, ", "); \
568 smart_str_appends(str, output); \
569 first = false; \
570 } \
571 } while (0)
572 DUMP_CONST_FLAG(CONST_PERSISTENT, "persistent");
573 DUMP_CONST_FLAG(CONST_NO_FILE_CACHE, "no_file_cache");
574 DUMP_CONST_FLAG(CONST_DEPRECATED, "deprecated");
575#undef DUMP_CONST_FLAG
576
577 smart_str_appends(str, "> ");
578 }
579
580 smart_str_appends(str, type);
581 smart_str_appendc(str, ' ');
582 smart_str_appends(str, name);
583 smart_str_appends(str, " ] { ");
584
585 if (Z_TYPE_P(value) == IS_ARRAY) {
586 smart_str_append(str, ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED));
587 } else if (Z_TYPE_P(value) == IS_STRING) {
588 smart_str_appends(str, Z_STRVAL_P(value));
589 } else {
590 zend_string *tmp_value_str;
591 zend_string *value_str = zval_get_tmp_string(value, &tmp_value_str);
592 smart_str_append(str, value_str);
593 zend_tmp_string_release(tmp_value_str);
594 }
595
596 smart_str_appends(str, " }\n");
597}
598/* }}} */
599
600/* {{{ _class_const_string */
601static void _class_const_string(smart_str *str, const zend_string *name, zend_class_constant *c, const char *indent)
602{
604 return;
605 }
606
607 const char *visibility = zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c));
608 const char *final = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_FINAL ? "final " : "";
610 const char *type = type_str ? ZSTR_VAL(type_str) : zend_zval_type_name(&c->value);
611
612 if (c->doc_comment) {
613 smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(c->doc_comment));
614 }
615 smart_str_append_printf(str, "%sConstant [ %s%s %s %s ] { ",
616 indent, final, visibility, type, ZSTR_VAL(name));
617 if (Z_TYPE(c->value) == IS_ARRAY) {
618 smart_str_appends(str, "Array");
619 } else if (Z_TYPE(c->value) == IS_OBJECT) {
620 smart_str_appends(str, "Object");
621 } else {
622 zend_string *tmp_value_str;
623 zend_string *value_str = zval_get_tmp_string(&c->value, &tmp_value_str);
624 smart_str_append(str, value_str);
625 zend_tmp_string_release(tmp_value_str);
626 }
627 smart_str_appends(str, " }\n");
628
629 if (type_str) {
630 zend_string_release(type_str);
631 }
632}
633/* }}} */
634
635static zend_op *get_recv_op(const zend_op_array *op_array, uint32_t offset)
636{
637 zend_op *op = op_array->opcodes;
638 const zend_op *end = op + op_array->last;
639
640 ++offset;
641 while (op < end) {
642 if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT
643 || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == offset)
644 {
645 return op;
646 }
647 ++op;
648 }
649 ZEND_ASSERT(0 && "Failed to find op");
650 return NULL;
651}
652
653static zval *get_default_from_recv(zend_op_array *op_array, uint32_t offset) {
654 zend_op *recv = get_recv_op(op_array, offset);
655 if (!recv || recv->opcode != ZEND_RECV_INIT) {
656 return NULL;
657 }
658
659 return RT_CONSTANT(recv, recv->op2);
660}
661
662static int format_default_value(smart_str *str, zval *value) {
664 /* Nothing to do. */
665 } else if (Z_TYPE_P(value) == IS_ARRAY) {
666 zend_string *str_key;
667 zend_long num_key;
668 zval *zv;
669 bool is_list = zend_array_is_list(Z_ARRVAL_P(value));
670 bool first = true;
671 smart_str_appendc(str, '[');
672 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(value), num_key, str_key, zv) {
673 if (!first) {
674 smart_str_appends(str, ", ");
675 }
676 first = false;
677
678 if (!is_list) {
679 if (str_key) {
680 smart_str_appendc(str, '\'');
681 smart_str_append_escaped(str, ZSTR_VAL(str_key), ZSTR_LEN(str_key));
682 smart_str_appendc(str, '\'');
683 } else {
684 smart_str_append_long(str, num_key);
685 }
686 smart_str_appends(str, " => ");
687 }
688 format_default_value(str, zv);
690 smart_str_appendc(str, ']');
691 } else if (Z_TYPE_P(value) == IS_OBJECT) {
692 /* This branch is reached if the constant AST was already evaluated and
693 * resulted in an object; enums are already handled in smart_str_append_zval()
694 * (GH-15902) */
695 zend_object *obj = Z_OBJ_P(value);
696 zend_class_entry *class = obj->ce;
697 ZEND_ASSERT(!(class->ce_flags & ZEND_ACC_ENUM));
698 smart_str_appends(str, "object(");
699 smart_str_append(str, class->name);
700 smart_str_appends(str, ")");
701 } else {
703 zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), "");
704 smart_str_append(str, ast_str);
705 zend_string_release(ast_str);
706 }
707 return SUCCESS;
708}
709
710static inline bool has_internal_arg_info(const zend_function *fptr) {
711 return fptr->type == ZEND_INTERNAL_FUNCTION
713}
714
715/* {{{ _parameter_string */
716static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, bool required, char* indent)
717{
718 smart_str_append_printf(str, "Parameter #%d [ ", offset);
719 if (!required) {
720 smart_str_append_printf(str, "<optional> ");
721 } else {
722 smart_str_append_printf(str, "<required> ");
723 }
724 if (ZEND_TYPE_IS_SET(arg_info->type)) {
725 zend_string *type_str = zend_type_to_string(arg_info->type);
726 smart_str_append(str, type_str);
727 smart_str_appendc(str, ' ');
728 zend_string_release(type_str);
729 }
730 if (ZEND_ARG_SEND_MODE(arg_info)) {
731 smart_str_appendc(str, '&');
732 }
733 if (ZEND_ARG_IS_VARIADIC(arg_info)) {
734 smart_str_appends(str, "...");
735 }
736 smart_str_append_printf(str, "$%s", has_internal_arg_info(fptr)
737 ? ((zend_internal_arg_info*)arg_info)->name : ZSTR_VAL(arg_info->name));
738
739 if (!required && !ZEND_ARG_IS_VARIADIC(arg_info)) {
740 if (fptr->type == ZEND_INTERNAL_FUNCTION) {
741 smart_str_appends(str, " = ");
742 /* TODO: We don't have a way to fetch the default value for an internal function
743 * with userland arg info. */
744 if (has_internal_arg_info(fptr)
745 && ((zend_internal_arg_info*)arg_info)->default_value) {
746 smart_str_appends(str, ((zend_internal_arg_info*)arg_info)->default_value);
747 } else {
748 smart_str_appends(str, "<default>");
749 }
750 } else {
751 zval *default_value = get_default_from_recv((zend_op_array*)fptr, offset);
752 if (default_value) {
753 smart_str_appends(str, " = ");
754 if (format_default_value(str, default_value) == FAILURE) {
755 return;
756 }
757 }
758 }
759 }
760 smart_str_appends(str, " ]");
761}
762/* }}} */
763
764/* {{{ _function_parameter_string */
765static void _function_parameter_string(smart_str *str, zend_function *fptr, char* indent)
766{
767 struct _zend_arg_info *arg_info = fptr->common.arg_info;
768 uint32_t i, num_args, num_required = fptr->common.required_num_args;
769
770 if (!arg_info) {
771 return;
772 }
773
774 num_args = fptr->common.num_args;
775 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
776 num_args++;
777 }
778 smart_str_appendc(str, '\n');
779 smart_str_append_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
780 for (i = 0; i < num_args; i++) {
781 smart_str_append_printf(str, "%s ", indent);
782 _parameter_string(str, fptr, arg_info, i, i < num_required, indent);
783 smart_str_appendc(str, '\n');
784 arg_info++;
785 }
786 smart_str_append_printf(str, "%s}\n", indent);
787}
788/* }}} */
789
790/* {{{ _function_closure_string */
791static void _function_closure_string(smart_str *str, const zend_function *fptr, const char* indent)
792{
793 uint32_t i, count;
794 const zend_string *key;
795 const HashTable *static_variables;
796
797 if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
798 return;
799 }
800
801 static_variables = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
802 count = zend_hash_num_elements(static_variables);
803
804 if (!count) {
805 return;
806 }
807
808 smart_str_append_printf(str, "\n");
809 smart_str_append_printf(str, "%s- Bound Variables [%u] {\n", indent, count);
810 i = 0;
811 ZEND_HASH_MAP_FOREACH_STR_KEY(static_variables, key) {
812 smart_str_append_printf(str, "%s Variable #%d [ $%s ]\n", indent, i++, ZSTR_VAL(key));
814 smart_str_append_printf(str, "%s}\n", indent);
815}
816/* }}} */
817
818/* {{{ _function_string */
819static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, const char* indent)
820{
821 smart_str param_indent = {0};
822 zend_function *overwrites;
823 zend_string *lc_name;
824
825 /* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
826 * What's "wrong" is that any whitespace before the doc comment start is
827 * swallowed, leading to an unaligned comment.
828 */
829 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
830 smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(fptr->op_array.doc_comment));
831 } else if (fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.doc_comment) {
832 smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(fptr->internal_function.doc_comment));
833 }
834
835 smart_str_appendl(str, indent, strlen(indent));
836 smart_str_append_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
837 smart_str_append_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
838 if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
839 smart_str_appends(str, ", deprecated");
840 }
841 if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
842 smart_str_append_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
843 }
844
845 if (scope && fptr->common.scope) {
846 if (fptr->common.scope != scope) {
847 smart_str_append_printf(str, ", inherits %s", ZSTR_VAL(fptr->common.scope->name));
848 } else if (fptr->common.scope->parent) {
849 lc_name = zend_string_tolower(fptr->common.function_name);
850 if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) {
851 if (fptr->common.scope != overwrites->common.scope && !(overwrites->common.fn_flags & ZEND_ACC_PRIVATE)) {
852 smart_str_append_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name));
853 }
854 }
855 zend_string_release_ex(lc_name, 0);
856 }
857 }
858 if (fptr->common.prototype && fptr->common.prototype->common.scope) {
859 smart_str_append_printf(str, ", prototype %s", ZSTR_VAL(fptr->common.prototype->common.scope->name));
860 }
861 if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
862 smart_str_appends(str, ", ctor");
863 }
864 smart_str_appends(str, "> ");
865
866 if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
867 smart_str_appends(str, "abstract ");
868 }
869 if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
870 smart_str_appends(str, "final ");
871 }
872 if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
873 smart_str_appends(str, "static ");
874 }
875
876 if (fptr->common.scope) {
877 /* These are mutually exclusive */
878 switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
879 case ZEND_ACC_PUBLIC:
880 smart_str_appends(str, "public ");
881 break;
882 case ZEND_ACC_PRIVATE:
883 smart_str_appends(str, "private ");
884 break;
886 smart_str_appends(str, "protected ");
887 break;
888 default:
889 smart_str_appends(str, "<visibility error> ");
890 break;
891 }
892 smart_str_appends(str, "method ");
893 } else {
894 smart_str_appends(str, "function ");
895 }
896
897 if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
898 smart_str_appendc(str, '&');
899 }
900 smart_str_append_printf(str, "%s ] {\n", ZSTR_VAL(fptr->common.function_name));
901 /* The information where a function is declared is only available for user classes */
902 if (fptr->type == ZEND_USER_FUNCTION) {
903 smart_str_append_printf(str, "%s @@ %s %d - %d\n", indent,
904 ZSTR_VAL(fptr->op_array.filename),
905 fptr->op_array.line_start,
906 fptr->op_array.line_end);
907 }
908 smart_str_append_printf(&param_indent, "%s ", indent);
909 smart_str_0(&param_indent);
910 if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
911 _function_closure_string(str, fptr, ZSTR_VAL(param_indent.s));
912 }
913 _function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
914 smart_str_free(&param_indent);
915 if ((fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
916 smart_str_append_printf(str, " %s- %s [ ", indent, ZEND_ARG_TYPE_IS_TENTATIVE(&fptr->common.arg_info[-1]) ? "Tentative return" : "Return");
917 if (ZEND_TYPE_IS_SET(fptr->common.arg_info[-1].type)) {
918 zend_string *type_str = zend_type_to_string(fptr->common.arg_info[-1].type);
919 smart_str_append_printf(str, "%s ", ZSTR_VAL(type_str));
920 zend_string_release(type_str);
921 }
922 smart_str_appends(str, "]\n");
923 }
924 smart_str_append_printf(str, "%s}\n", indent);
925}
926/* }}} */
927
928static zval *property_get_default(zend_property_info *prop_info) {
929 zend_class_entry *ce = prop_info->ce;
930 if (prop_info->flags & ZEND_ACC_STATIC) {
931 zval *prop = &ce->default_static_members_table[prop_info->offset];
932 ZVAL_DEINDIRECT(prop);
933 return prop;
934 } else if (prop_info->flags & ZEND_ACC_VIRTUAL) {
935 return NULL;
936 } else {
938 }
939}
940
941/* {{{ _property_string */
942static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, const char* indent)
943{
944 if (prop && prop->doc_comment) {
945 smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(prop->doc_comment));
946 }
947 smart_str_append_printf(str, "%sProperty [ ", indent);
948 if (!prop) {
949 smart_str_append_printf(str, "<dynamic> public $%s", prop_name);
950 } else {
951 if (prop->flags & ZEND_ACC_ABSTRACT) {
952 smart_str_appends(str, "abstract ");
953 }
954 if (prop->flags & ZEND_ACC_FINAL) {
955 smart_str_appends(str, "final ");
956 }
957 /* These are mutually exclusive */
958 switch (prop->flags & ZEND_ACC_PPP_MASK) {
959 case ZEND_ACC_PUBLIC:
960 smart_str_appends(str, "public ");
961 break;
962 case ZEND_ACC_PRIVATE:
963 smart_str_appends(str, "private ");
964 break;
966 smart_str_appends(str, "protected ");
967 break;
968 }
969 switch (prop->flags & ZEND_ACC_PPP_SET_MASK) {
971 smart_str_appends(str, "private(set) ");
972 break;
974 smart_str_appends(str, "protected(set) ");
975 break;
978 break;
979 }
980 if (prop->flags & ZEND_ACC_STATIC) {
981 smart_str_appends(str, "static ");
982 }
983 if (prop->flags & ZEND_ACC_READONLY) {
984 smart_str_appends(str, "readonly ");
985 }
986 if (ZEND_TYPE_IS_SET(prop->type)) {
987 zend_string *type_str = zend_type_to_string(prop->type);
988 smart_str_append(str, type_str);
989 smart_str_appendc(str, ' ');
990 zend_string_release(type_str);
991 }
992 if (!prop_name) {
993 const char *class_name;
994 zend_unmangle_property_name(prop->name, &class_name, &prop_name);
995 }
996 smart_str_append_printf(str, "$%s", prop_name);
997
998 zval *default_value = property_get_default(prop);
1000 smart_str_appends(str, " = ");
1001 if (format_default_value(str, default_value) == FAILURE) {
1002 return;
1003 }
1004 }
1005 }
1006
1007 smart_str_appends(str, " ]\n");
1008}
1009/* }}} */
1010
1011static void _extension_ini_string(const zend_ini_entry *ini_entry, smart_str *str, const char *indent, int number) /* {{{ */
1012{
1013 char *comma = "";
1014
1015 if (number == ini_entry->module_number) {
1016 smart_str_append_printf(str, " %sEntry [ %s <", indent, ZSTR_VAL(ini_entry->name));
1017 if (ini_entry->modifiable == ZEND_INI_ALL) {
1018 smart_str_appends(str, "ALL");
1019 } else {
1020 if (ini_entry->modifiable & ZEND_INI_USER) {
1021 smart_str_appends(str, "USER");
1022 comma = ",";
1023 }
1024 if (ini_entry->modifiable & ZEND_INI_PERDIR) {
1025 smart_str_append_printf(str, "%sPERDIR", comma);
1026 comma = ",";
1027 }
1028 if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
1029 smart_str_append_printf(str, "%sSYSTEM", comma);
1030 }
1031 }
1032
1033 smart_str_appends(str, "> ]\n");
1034 smart_str_append_printf(str, " %s Current = '%s'\n", indent, ini_entry->value ? ZSTR_VAL(ini_entry->value) : "");
1035 if (ini_entry->modified) {
1036 smart_str_append_printf(str, " %s Default = '%s'\n", indent, ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : "");
1037 }
1038 smart_str_append_printf(str, " %s}\n", indent);
1039 }
1040}
1041/* }}} */
1042
1043static void _extension_class_string(zend_class_entry *ce, zend_string *key, smart_str *str, const char *indent, const zend_module_entry *module, int *num_classes) /* {{{ */
1044{
1045 if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
1046 /* dump class if it is not an alias */
1047 if (zend_string_equals_ci(ce->name, key)) {
1048 smart_str_append_printf(str, "\n");
1049 _class_string(str, ce, NULL, indent);
1050 (*num_classes)++;
1051 }
1052 }
1053}
1054/* }}} */
1055
1056static void _extension_string(smart_str *str, const zend_module_entry *module, const char *indent) /* {{{ */
1057{
1058 smart_str_append_printf(str, "%sExtension [ ", indent);
1059 if (module->type == MODULE_PERSISTENT) {
1060 smart_str_appends(str, "<persistent>");
1061 }
1062 if (module->type == MODULE_TEMPORARY) {
1063 smart_str_appends(str, "<temporary>" );
1064 }
1065 smart_str_append_printf(str, " extension #%d %s version %s ] {\n",
1066 module->module_number, module->name,
1067 (module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
1068
1069 if (module->deps) {
1070 const zend_module_dep* dep = module->deps;
1071
1072 smart_str_appends(str, "\n - Dependencies {\n");
1073
1074 while(dep->name) {
1075 smart_str_append_printf(str, "%s Dependency [ %s (", indent, dep->name);
1076
1077 switch(dep->type) {
1079 smart_str_appends(str, "Required");
1080 break;
1082 smart_str_appends(str, "Conflicts");
1083 break;
1085 smart_str_appends(str, "Optional");
1086 break;
1087 default:
1088 smart_str_appends(str, "Error"); /* shouldn't happen */
1089 break;
1090 }
1091
1092 if (dep->rel) {
1093 smart_str_append_printf(str, " %s", dep->rel);
1094 }
1095 if (dep->version) {
1096 smart_str_append_printf(str, " %s", dep->version);
1097 }
1098 smart_str_appends(str, ") ]\n");
1099 dep++;
1100 }
1101 smart_str_append_printf(str, "%s }\n", indent);
1102 }
1103
1104 {
1105 smart_str str_ini = {0};
1106 zend_ini_entry *ini_entry;
1107 ZEND_HASH_MAP_FOREACH_PTR(EG(ini_directives), ini_entry) {
1108 _extension_ini_string(ini_entry, &str_ini, indent, module->module_number);
1110 if (smart_str_get_len(&str_ini) > 0) {
1111 smart_str_append_printf(str, "\n - INI {\n");
1112 smart_str_append_smart_str(str, &str_ini);
1113 smart_str_append_printf(str, "%s }\n", indent);
1114 }
1115 smart_str_free(&str_ini);
1116 }
1117
1118 {
1119 smart_str str_constants = {0};
1121 int num_constants = 0;
1122
1123 ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) {
1124 if (ZEND_CONSTANT_MODULE_NUMBER(constant) == module->module_number) {
1125 _const_string(&str_constants, ZSTR_VAL(constant->name), &constant->value, " ");
1126 num_constants++;
1127 }
1129
1130 if (num_constants) {
1131 smart_str_append_printf(str, "\n - Constants [%d] {\n", num_constants);
1132 smart_str_append_smart_str(str, &str_constants);
1133 smart_str_append_printf(str, "%s }\n", indent);
1134 }
1135 smart_str_free(&str_constants);
1136 }
1137
1138 {
1139 zend_function *fptr;
1140 int first = 1;
1141
1142 ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), fptr) {
1144 && fptr->internal_function.module == module) {
1145 if (first) {
1146 smart_str_append_printf(str, "\n - Functions {\n");
1147 first = 0;
1148 }
1149 _function_string(str, fptr, NULL, " ");
1150 }
1152 if (!first) {
1153 smart_str_append_printf(str, "%s }\n", indent);
1154 }
1155 }
1156
1157 {
1158 zend_string *sub_indent = strpprintf(0, "%s ", indent);
1159 smart_str str_classes = {0};
1161 zend_class_entry *ce;
1162 int num_classes = 0;
1163
1164 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
1165 _extension_class_string(ce, key, &str_classes, ZSTR_VAL(sub_indent), module, &num_classes);
1167 if (num_classes) {
1168 smart_str_append_printf(str, "\n - Classes [%d] {", num_classes);
1169 smart_str_append_smart_str(str, &str_classes);
1170 smart_str_append_printf(str, "%s }\n", indent);
1171 }
1172 smart_str_free(&str_classes);
1173 zend_string_release_ex(sub_indent, 0);
1174 }
1175
1176 smart_str_append_printf(str, "%s}\n", indent);
1177}
1178/* }}} */
1179
1180/* {{{ reflection_attribute_factory */
1181static void reflection_attribute_factory(zval *object, HashTable *attributes, zend_attribute *data,
1182 zend_class_entry *scope, uint32_t target, zend_string *filename)
1183{
1184 reflection_object *intern;
1185 attribute_reference *reference;
1186
1187 reflection_instantiate(reflection_attribute_ptr, object);
1188 intern = Z_REFLECTION_P(object);
1189 reference = (attribute_reference*) emalloc(sizeof(attribute_reference));
1190 reference->attributes = attributes;
1191 reference->data = data;
1192 reference->scope = scope;
1193 reference->filename = filename ? zend_string_copy(filename) : NULL;
1194 reference->target = target;
1195 intern->ptr = reference;
1196 intern->ref_type = REF_TYPE_ATTRIBUTE;
1197 ZVAL_STR_COPY(reflection_prop_name(object), data->name);
1198}
1199/* }}} */
1200
1201static int read_attributes(zval *ret, HashTable *attributes, zend_class_entry *scope,
1202 uint32_t offset, uint32_t target, zend_string *name, zend_class_entry *base, zend_string *filename) /* {{{ */
1203{
1204 ZEND_ASSERT(attributes != NULL);
1205
1207 zval tmp;
1208
1209 if (name) {
1210 // Name based filtering using lowercased key.
1211 zend_string *filter = zend_string_tolower(name);
1212
1213 ZEND_HASH_PACKED_FOREACH_PTR(attributes, attr) {
1214 if (attr->offset == offset && zend_string_equals(attr->lcname, filter)) {
1215 reflection_attribute_factory(&tmp, attributes, attr, scope, target, filename);
1216 add_next_index_zval(ret, &tmp);
1217 }
1219
1220 zend_string_release(filter);
1221 return SUCCESS;
1222 }
1223
1224 ZEND_HASH_PACKED_FOREACH_PTR(attributes, attr) {
1225 if (attr->offset != offset) {
1226 continue;
1227 }
1228
1229 if (base) {
1230 // Base type filtering.
1231 zend_class_entry *ce = zend_lookup_class_ex(attr->name, attr->lcname, 0);
1232
1233 if (ce == NULL) {
1234 // Bailout on error, otherwise ignore unavailable class.
1235 if (EG(exception)) {
1236 return FAILURE;
1237 }
1238
1239 continue;
1240 }
1241
1242 if (!instanceof_function(ce, base)) {
1243 continue;
1244 }
1245 }
1246
1247 reflection_attribute_factory(&tmp, attributes, attr, scope, target, filename);
1248 add_next_index_zval(ret, &tmp);
1250
1251 return SUCCESS;
1252}
1253/* }}} */
1254
1255static void reflect_attributes(INTERNAL_FUNCTION_PARAMETERS, HashTable *attributes,
1256 uint32_t offset, zend_class_entry *scope, uint32_t target, zend_string *filename) /* {{{ */
1257{
1259 zend_long flags = 0;
1260 zend_class_entry *base = NULL;
1261
1262 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!l", &name, &flags) == FAILURE) {
1263 RETURN_THROWS();
1264 }
1265
1267 zend_argument_value_error(2, "must be a valid attribute filter flag");
1268 RETURN_THROWS();
1269 }
1270
1272 if (NULL == (base = zend_lookup_class(name))) {
1273 if (!EG(exception)) {
1274 zend_throw_error(NULL, "Class \"%s\" not found", ZSTR_VAL(name));
1275 }
1276
1277 RETURN_THROWS();
1278 }
1279
1280 name = NULL;
1281 }
1282
1283 if (!attributes) {
1285 }
1286
1288
1289 if (FAILURE == read_attributes(return_value, attributes, scope, offset, target, name, base, filename)) {
1290 RETURN_THROWS();
1291 }
1292}
1293/* }}} */
1294
1295static void _zend_extension_string(smart_str *str, const zend_extension *extension, const char *indent) /* {{{ */
1296{
1297 smart_str_append_printf(str, "%sZend Extension [ %s ", indent, extension->name);
1298
1299 if (extension->version) {
1300 smart_str_append_printf(str, "%s ", extension->version);
1301 }
1302 if (extension->copyright) {
1303 smart_str_append_printf(str, "%s ", extension->copyright);
1304 }
1305 if (extension->author) {
1306 smart_str_append_printf(str, "by %s ", extension->author);
1307 }
1308 if (extension->URL) {
1309 smart_str_append_printf(str, "<%s> ", extension->URL);
1310 }
1311
1312 smart_str_appends(str, "]\n");
1313}
1314/* }}} */
1315
1316/* {{{ _function_check_flag */
1317static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
1318{
1319 reflection_object *intern;
1320 zend_function *mptr;
1321
1323 RETURN_THROWS();
1324 }
1326 RETURN_BOOL(mptr->common.fn_flags & mask);
1327}
1328/* }}} */
1329
1330/* {{{ zend_reflection_class_factory */
1332{
1333 reflection_object *intern;
1334
1335 zend_class_entry *reflection_ce =
1337 reflection_instantiate(reflection_ce, object);
1338 intern = Z_REFLECTION_P(object);
1339 intern->ptr = ce;
1340 intern->ref_type = REF_TYPE_OTHER;
1341 intern->ce = ce;
1342 ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
1343}
1344/* }}} */
1345
1346/* {{{ reflection_extension_factory */
1347static void reflection_extension_factory(zval *object, const char *name_str)
1348{
1349 reflection_object *intern;
1350 size_t name_len = strlen(name_str);
1352 struct _zend_module_entry *module;
1353
1354 lcname = zend_string_alloc(name_len, 0);
1355 zend_str_tolower_copy(ZSTR_VAL(lcname), name_str, name_len);
1356 module = zend_hash_find_ptr(&module_registry, lcname);
1357 zend_string_efree(lcname);
1358 if (!module) {
1359 return;
1360 }
1361
1362 reflection_instantiate(reflection_extension_ptr, object);
1363 intern = Z_REFLECTION_P(object);
1364 intern->ptr = module;
1365 intern->ref_type = REF_TYPE_OTHER;
1366 intern->ce = NULL;
1367 ZVAL_STRINGL(reflection_prop_name(object), module->name, name_len);
1368}
1369/* }}} */
1370
1371/* {{{ reflection_parameter_factory */
1372static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, uint32_t offset, bool required, zval *object)
1373{
1374 reflection_object *intern;
1375 parameter_reference *reference;
1376 zval *prop_name;
1377
1378 reflection_instantiate(reflection_parameter_ptr, object);
1379 intern = Z_REFLECTION_P(object);
1380 reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
1381 reference->arg_info = arg_info;
1382 reference->offset = offset;
1383 reference->required = required;
1384 reference->fptr = fptr;
1385 intern->ptr = reference;
1386 intern->ref_type = REF_TYPE_PARAMETER;
1387 intern->ce = fptr->common.scope;
1388 if (closure_object) {
1389 ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(closure_object));
1390 }
1391
1392 prop_name = reflection_prop_name(object);
1393 if (has_internal_arg_info(fptr)) {
1394 ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)->name);
1395 } else {
1396 ZVAL_STR_COPY(prop_name, arg_info->name);
1397 }
1398}
1399/* }}} */
1400
1406
1407/* For backwards compatibility reasons, we need to return T|null style unions
1408 * and transformation from iterable to Traversable|array
1409 * as a ReflectionNamedType. Here we determine what counts as a union type and
1410 * what doesn't. */
1411static reflection_type_kind get_type_kind(zend_type type) {
1412 uint32_t type_mask_without_null = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(type);
1413
1414 if (ZEND_TYPE_HAS_LIST(type)) {
1416 return INTERSECTION_TYPE;
1417 }
1419 return UNION_TYPE;
1420 }
1421
1423 /* BC support for 'iterable' type */
1425 return NAMED_TYPE;
1426 }
1427 if (type_mask_without_null != 0) {
1428 return UNION_TYPE;
1429 }
1430 return NAMED_TYPE;
1431 }
1432 if (type_mask_without_null == MAY_BE_BOOL || ZEND_TYPE_PURE_MASK(type) == MAY_BE_ANY) {
1433 return NAMED_TYPE;
1434 }
1435 /* Check that only one bit is set. */
1436 if ((type_mask_without_null & (type_mask_without_null - 1)) != 0) {
1437 return UNION_TYPE;
1438 }
1439 return NAMED_TYPE;
1440}
1441
1442/* {{{ reflection_type_factory */
1443static void reflection_type_factory(zend_type type, zval *object, bool legacy_behavior)
1444{
1445 reflection_object *intern;
1446 type_reference *reference;
1447 reflection_type_kind type_kind = get_type_kind(type);
1448 bool is_mixed = ZEND_TYPE_PURE_MASK(type) == MAY_BE_ANY;
1449 bool is_only_null = (ZEND_TYPE_PURE_MASK(type) == MAY_BE_NULL && !ZEND_TYPE_IS_COMPLEX(type));
1450
1451 switch (type_kind) {
1452 case INTERSECTION_TYPE:
1453 reflection_instantiate(reflection_intersection_type_ptr, object);
1454 break;
1455 case UNION_TYPE:
1456 reflection_instantiate(reflection_union_type_ptr, object);
1457 break;
1458 case NAMED_TYPE:
1459 reflection_instantiate(reflection_named_type_ptr, object);
1460 break;
1462 }
1463
1464 intern = Z_REFLECTION_P(object);
1465 reference = (type_reference*) emalloc(sizeof(type_reference));
1466 reference->type = type;
1467 reference->legacy_behavior = legacy_behavior && type_kind == NAMED_TYPE && !is_mixed && !is_only_null;
1468 intern->ptr = reference;
1469 intern->ref_type = REF_TYPE_TYPE;
1470
1471 /* Property types may be resolved during the lifetime of the ReflectionType.
1472 * If we reference a string, make sure it doesn't get released. However, only
1473 * do this for the top-level type, as resolutions inside type lists will be
1474 * fully visible to us (we'd have to do a fully copy of the type if we wanted
1475 * to prevent that). */
1476 if (ZEND_TYPE_HAS_NAME(type)) {
1477 zend_string_addref(ZEND_TYPE_NAME(type));
1478 }
1479}
1480/* }}} */
1481
1482/* {{{ reflection_function_factory */
1483static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object)
1484{
1485 reflection_object *intern;
1486 reflection_instantiate(reflection_function_ptr, object);
1487 intern = Z_REFLECTION_P(object);
1488 intern->ptr = function;
1489 intern->ref_type = REF_TYPE_FUNCTION;
1490 intern->ce = NULL;
1491 if (closure_object) {
1492 ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(closure_object));
1493 }
1494 ZVAL_STR_COPY(reflection_prop_name(object), function->common.function_name);
1495}
1496/* }}} */
1497
1498/* {{{ reflection_method_factory */
1499static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object)
1500{
1501 reflection_object *intern;
1502
1503 reflection_instantiate(reflection_method_ptr, object);
1504 intern = Z_REFLECTION_P(object);
1505 intern->ptr = method;
1506 intern->ref_type = REF_TYPE_FUNCTION;
1507 intern->ce = ce;
1508 if (closure_object) {
1509 ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(closure_object));
1510 }
1511
1512 ZVAL_STR_COPY(reflection_prop_name(object), method->common.function_name);
1513 ZVAL_STR_COPY(reflection_prop_class(object), method->common.scope->name);
1514}
1515/* }}} */
1516
1517/* {{{ reflection_property_factory */
1518static void reflection_property_factory(zend_class_entry *ce, zend_string *name, zend_property_info *prop, zval *object)
1519{
1520 reflection_object *intern;
1521 property_reference *reference;
1522
1523 reflection_instantiate(reflection_property_ptr, object);
1524 intern = Z_REFLECTION_P(object);
1525 reference = (property_reference*) emalloc(sizeof(property_reference));
1526 reference->prop = prop;
1527 reference->unmangled_name = zend_string_copy(name);
1528 intern->ptr = reference;
1529 intern->ref_type = REF_TYPE_PROPERTY;
1530 intern->ce = ce;
1531 ZVAL_STR_COPY(reflection_prop_name(object), name);
1532 ZVAL_STR_COPY(reflection_prop_class(object), prop ? prop->ce->name : ce->name);
1533}
1534/* }}} */
1535
1536static void reflection_property_factory_str(zend_class_entry *ce, const char *name_str, size_t name_len, zend_property_info *prop, zval *object)
1537{
1538 zend_string *name = zend_string_init(name_str, name_len, 0);
1539 reflection_property_factory(ce, name, prop, object);
1540 zend_string_release(name);
1541}
1542
1543/* {{{ reflection_class_constant_factory */
1544static void reflection_class_constant_factory(zend_string *name_str, zend_class_constant *constant, zval *object)
1545{
1546 reflection_object *intern;
1547
1548 reflection_instantiate(reflection_class_constant_ptr, object);
1549 intern = Z_REFLECTION_P(object);
1550 intern->ptr = constant;
1552 intern->ce = constant->ce;
1553
1554 ZVAL_STR_COPY(reflection_prop_name(object), name_str);
1555 ZVAL_STR_COPY(reflection_prop_class(object), constant->ce->name);
1556}
1557/* }}} */
1558
1559static void reflection_enum_case_factory(zend_class_entry *ce, zend_string *name_str, zend_class_constant *constant, zval *object)
1560{
1561 reflection_object *intern;
1562
1563 zend_class_entry *case_reflection_class = ce->enum_backing_type == IS_UNDEF
1566 reflection_instantiate(case_reflection_class, object);
1567 intern = Z_REFLECTION_P(object);
1568 intern->ptr = constant;
1570 intern->ce = constant->ce;
1571
1572 ZVAL_STR_COPY(reflection_prop_name(object), name_str);
1573 ZVAL_STR_COPY(reflection_prop_class(object), constant->ce->name);
1574}
1575
1576static int get_parameter_default(zval *result, parameter_reference *param) {
1577 if (param->fptr->type == ZEND_INTERNAL_FUNCTION) {
1579 /* We don't have a way to determine the default value for this case right now. */
1580 return FAILURE;
1581 }
1584 } else {
1585 zval *default_value = get_default_from_recv((zend_op_array *) param->fptr, param->offset);
1586 if (!default_value) {
1587 return FAILURE;
1588 }
1589
1590 ZVAL_COPY(result, default_value);
1591 return SUCCESS;
1592 }
1593}
1594
1595/* {{{ Preventing __clone from being called */
1597{
1598 /* __clone() is private but this is reachable with reflection */
1599 _DO_THROW("Cannot clone object using __clone()");
1600}
1601/* }}} */
1602
1603/* {{{ Returns an array of modifier names */
1604ZEND_METHOD(Reflection, getModifierNames)
1605{
1606 zend_long modifiers;
1607
1608 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &modifiers) == FAILURE) {
1609 RETURN_THROWS();
1610 }
1611
1613
1615 add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1);
1616 }
1617 if (modifiers & ZEND_ACC_FINAL) {
1618 add_next_index_stringl(return_value, "final", sizeof("final")-1);
1619 }
1620 if (modifiers & ZEND_ACC_VIRTUAL) {
1621 add_next_index_stringl(return_value, "virtual", sizeof("virtual")-1);
1622 }
1623
1624 /* These are mutually exclusive */
1625 switch (modifiers & ZEND_ACC_PPP_MASK) {
1626 case ZEND_ACC_PUBLIC:
1627 add_next_index_stringl(return_value, "public", sizeof("public")-1);
1628 break;
1629 case ZEND_ACC_PRIVATE:
1630 add_next_index_stringl(return_value, "private", sizeof("private")-1);
1631 break;
1632 case ZEND_ACC_PROTECTED:
1633 add_next_index_stringl(return_value, "protected", sizeof("protected")-1);
1634 break;
1635 }
1636
1637 if (modifiers & ZEND_ACC_STATIC) {
1638 add_next_index_str(return_value, ZSTR_KNOWN(ZEND_STR_STATIC));
1639 }
1640
1641 if (modifiers & (ZEND_ACC_READONLY | ZEND_ACC_READONLY_CLASS)) {
1642 add_next_index_stringl(return_value, "readonly", sizeof("readonly")-1);
1643 }
1644}
1645/* }}} */
1646
1647/* {{{ Constructor. Throws an Exception in case the given function does not exist */
1649{
1650 zval *object;
1651 zend_object *closure_obj = NULL;
1652 reflection_object *intern;
1653 zend_function *fptr;
1654 zend_string *fname, *lcname;
1655
1656 object = ZEND_THIS;
1657 intern = Z_REFLECTION_P(object);
1658
1660 Z_PARAM_OBJ_OF_CLASS_OR_STR(closure_obj, zend_ce_closure, fname)
1662
1663 if (closure_obj) {
1664 fptr = (zend_function*)zend_get_closure_method_def(closure_obj);
1665 } else {
1666 if (UNEXPECTED(ZSTR_VAL(fname)[0] == '\\')) {
1667 /* Ignore leading "\" */
1668 ALLOCA_FLAG(use_heap)
1669 ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
1670 zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
1672 ZSTR_ALLOCA_FREE(lcname, use_heap);
1673 } else {
1674 lcname = zend_string_tolower(fname);
1676 zend_string_release(lcname);
1677 }
1678
1679 if (fptr == NULL) {
1681 "Function %s() does not exist", ZSTR_VAL(fname));
1682 RETURN_THROWS();
1683 }
1684 }
1685
1686 if (intern->ptr) {
1687 zval_ptr_dtor(&intern->obj);
1688 zval_ptr_dtor(reflection_prop_name(object));
1689 }
1690
1691 ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name);
1692 intern->ptr = fptr;
1693 intern->ref_type = REF_TYPE_FUNCTION;
1694 if (closure_obj) {
1695 ZVAL_OBJ_COPY(&intern->obj, closure_obj);
1696 } else {
1697 ZVAL_UNDEF(&intern->obj);
1698 }
1699 intern->ce = NULL;
1700}
1701/* }}} */
1702
1703/* {{{ Returns a string representation */
1705{
1706 reflection_object *intern;
1707 zend_function *fptr;
1708 smart_str str = {0};
1709
1711 RETURN_THROWS();
1712 }
1714 _function_string(&str, fptr, intern->ce, "");
1715 RETURN_STR(smart_str_extract(&str));
1716}
1717/* }}} */
1718
1719/* {{{ Returns this function's name */
1721{
1722 reflection_object *intern;
1723 zend_function *fptr;
1724
1726 RETURN_THROWS();
1727 }
1728
1731}
1732/* }}} */
1733
1734/* {{{ Returns whether this is a closure */
1736{
1737 reflection_object *intern;
1738 zend_function *fptr;
1739
1741 RETURN_THROWS();
1742 }
1745}
1746/* }}} */
1747
1748/* {{{ Returns this pointer bound to closure */
1750{
1751 reflection_object *intern;
1752 zval* closure_this;
1753
1755 RETURN_THROWS();
1756 }
1758 if (!Z_ISUNDEF(intern->obj)) {
1759 closure_this = zend_get_closure_this_ptr(&intern->obj);
1760 if (!Z_ISUNDEF_P(closure_this)) {
1761 RETURN_OBJ_COPY(Z_OBJ_P(closure_this));
1762 }
1763 }
1764}
1765/* }}} */
1766
1767/* {{{ Returns the scope associated to the closure */
1769{
1770 reflection_object *intern;
1771 const zend_function *closure_func;
1772
1774 RETURN_THROWS();
1775 }
1777 if (!Z_ISUNDEF(intern->obj)) {
1778 closure_func = zend_get_closure_method_def(Z_OBJ(intern->obj));
1779 if (closure_func && closure_func->common.scope) {
1781 }
1782 }
1783}
1784/* }}} */
1785
1786/* {{{ Returns the called scope associated to the closure */
1788{
1789 reflection_object *intern;
1790
1792 RETURN_THROWS();
1793 }
1795 if (!Z_ISUNDEF(intern->obj)) {
1796 zend_class_entry *called_scope;
1797 zend_function *closure_func;
1799 if (Z_OBJ_HANDLER(intern->obj, get_closure)
1800 && Z_OBJ_HANDLER(intern->obj, get_closure)(Z_OBJ(intern->obj), &called_scope, &closure_func, &object, 1) == SUCCESS
1801 && closure_func && (called_scope || closure_func->common.scope)) {
1802 zend_reflection_class_factory(called_scope ? (zend_class_entry *) called_scope : closure_func->common.scope, return_value);
1803 }
1804 }
1805}
1806/* }}} */
1807
1808/* {{{ Returns an associative array containing the closures lexical scope variables */
1810{
1811 reflection_object *intern;
1812 const zend_function *closure_func;
1813
1815 RETURN_THROWS();
1816 }
1818
1820 if (!Z_ISUNDEF(intern->obj)) {
1821 closure_func = zend_get_closure_method_def(Z_OBJ(intern->obj));
1822 if (closure_func == NULL ||
1823 closure_func->type != ZEND_USER_FUNCTION ||
1824 closure_func->op_array.static_variables == NULL) {
1825 return;
1826 }
1827
1828 const zend_op_array *ops = &closure_func->op_array;
1829
1830 HashTable *static_variables = ZEND_MAP_PTR_GET(ops->static_variables_ptr);
1831
1832 if (!static_variables) {
1833 return;
1834 }
1835
1836 zend_op *opline = ops->opcodes + ops->num_args;
1837 if (ops->fn_flags & ZEND_ACC_VARIADIC) {
1838 opline++;
1839 }
1840
1841 for (; opline->opcode == ZEND_BIND_STATIC; opline++) {
1843 continue;
1844 }
1845
1846 Bucket *bucket = (Bucket*)
1847 (((char*)static_variables->arData) +
1849
1850 if (Z_ISUNDEF(bucket->val)) {
1851 continue;
1852 }
1853
1854 zend_hash_add_new(Z_ARRVAL_P(return_value), bucket->key, &bucket->val);
1855 Z_TRY_ADDREF(bucket->val);
1856 }
1857 }
1858} /* }}} */
1859
1860/* {{{ Returns a dynamically created closure for the function */
1862{
1863 reflection_object *intern;
1864 zend_function *fptr;
1865
1867 RETURN_THROWS();
1868 }
1870
1871 if (!Z_ISUNDEF(intern->obj)) {
1872 /* Closures are immutable objects */
1873 RETURN_OBJ_COPY(Z_OBJ(intern->obj));
1874 } else {
1876 }
1877}
1878/* }}} */
1879
1880/* {{{ Returns whether this is an internal function */
1882{
1883 reflection_object *intern;
1884 zend_function *fptr;
1885
1887 RETURN_THROWS();
1888 }
1891}
1892/* }}} */
1893
1894/* {{{ Returns whether this is a user-defined function */
1896{
1897 reflection_object *intern;
1898 zend_function *fptr;
1899
1901 RETURN_THROWS();
1902 }
1905}
1906/* }}} */
1907
1908/* {{{ Returns whether this function is an anonymous closure or not */
1919/* }}} */
1920
1921/* {{{ Returns whether this function has been disabled or not */
1923{
1925 RETURN_THROWS();
1926 }
1927
1928 /* A disabled function cannot be queried using Reflection. */
1930}
1931/* }}} */
1932
1933/* {{{ Returns the filename of the file this function was declared in */
1935{
1936 reflection_object *intern;
1937 zend_function *fptr;
1938
1940 RETURN_THROWS();
1941 }
1943 if (fptr->type == ZEND_USER_FUNCTION) {
1945 }
1947}
1948/* }}} */
1949
1950/* {{{ Returns the line this function's declaration starts at */
1952{
1953 reflection_object *intern;
1954 zend_function *fptr;
1955
1957 RETURN_THROWS();
1958 }
1960 if (fptr->type == ZEND_USER_FUNCTION) {
1962 }
1964}
1965/* }}} */
1966
1967/* {{{ Returns the line this function's declaration ends at */
1969{
1970 reflection_object *intern;
1971 zend_function *fptr;
1972
1974 RETURN_THROWS();
1975 }
1977 if (fptr->type == ZEND_USER_FUNCTION) {
1979 }
1981}
1982/* }}} */
1983
1984/* {{{ Returns the doc comment for this function */
1986{
1987 reflection_object *intern;
1988 zend_function *fptr;
1989
1991 RETURN_THROWS();
1992 }
1993
1995
1996 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
1998 }
1999
2000 if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function *) fptr)->doc_comment) {
2001 RETURN_STR_COPY(((zend_internal_function *) fptr)->doc_comment);
2002 }
2003
2005}
2006/* }}} */
2007
2008/* {{{ Returns the attributes of this function */
2010{
2011 reflection_object *intern;
2012 zend_function *fptr;
2013 uint32_t target;
2014
2016
2019 } else {
2021 }
2022
2023 reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU,
2024 fptr->common.attributes, 0, fptr->common.scope, target,
2025 fptr->type == ZEND_USER_FUNCTION ? fptr->op_array.filename : NULL);
2026}
2027/* }}} */
2028
2029/* {{{ Returns an associative array containing this function's static variables and their values */
2031{
2032 reflection_object *intern;
2033 zend_function *fptr;
2034
2036 RETURN_THROWS();
2037 }
2039
2040 /* Return an empty array in case no static variables exist */
2041 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
2042 HashTable *ht;
2043
2045 ht = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
2046 if (!ht) {
2048 ZEND_MAP_PTR_SET(fptr->op_array.static_variables_ptr, ht);
2049 }
2051 } else {
2053 }
2054}
2055/* }}} */
2056
2057/* {{{ Invokes the function */
2059{
2060 zval retval;
2061 zval *params;
2062 uint32_t num_args;
2063 HashTable *named_params;
2065 reflection_object *intern;
2066 zend_function *fptr;
2067
2069 Z_PARAM_VARIADIC_WITH_NAMED(params, num_args, named_params)
2071
2073
2074 fcc.function_handler = fptr;
2075 fcc.called_scope = NULL;
2076 fcc.object = NULL;
2077
2078 if (!Z_ISUNDEF(intern->obj)) {
2079 Z_OBJ_HT(intern->obj)->get_closure(
2080 Z_OBJ(intern->obj), &fcc.called_scope, &fcc.function_handler, &fcc.object, 0);
2081 }
2082
2083 zend_call_known_fcc(&fcc, &retval, num_args, params, named_params);
2084
2085 if (Z_TYPE(retval) == IS_UNDEF && !EG(exception)) {
2087 "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
2088 RETURN_THROWS();
2089 }
2090
2091 if (Z_ISREF(retval)) {
2092 zend_unwrap_reference(&retval);
2093 }
2095}
2096/* }}} */
2097
2098/* {{{ Invokes the function and pass its arguments as array. */
2100{
2101 zval retval;
2103 reflection_object *intern;
2104 zend_function *fptr;
2105 HashTable *params;
2106
2107 if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", &params) == FAILURE) {
2108 RETURN_THROWS();
2109 }
2110
2112
2113 fcc.function_handler = fptr;
2114 fcc.called_scope = NULL;
2115 fcc.object = NULL;
2116
2117 if (!Z_ISUNDEF(intern->obj)) {
2118 Z_OBJ_HT(intern->obj)->get_closure(
2119 Z_OBJ(intern->obj), &fcc.called_scope, &fcc.function_handler, &fcc.object, 0);
2120 }
2121
2122 zend_call_known_fcc(&fcc, &retval, /* num_params */ 0, /* params */ NULL, params);
2123
2124 if (Z_TYPE(retval) == IS_UNDEF && !EG(exception)) {
2126 "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
2127 RETURN_THROWS();
2128 }
2129
2130 if (Z_ISREF(retval)) {
2131 zend_unwrap_reference(&retval);
2132 }
2134}
2135/* }}} */
2136
2137/* {{{ Gets whether this function returns a reference */
2139{
2140 reflection_object *intern;
2141 zend_function *fptr;
2142
2144 RETURN_THROWS();
2145 }
2146
2148
2150}
2151/* }}} */
2152
2153/* {{{ Gets the number of parameters */
2155{
2156 reflection_object *intern;
2157 zend_function *fptr;
2158 uint32_t num_args;
2159
2161 RETURN_THROWS();
2162 }
2163
2165
2166 num_args = fptr->common.num_args;
2167 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2168 num_args++;
2169 }
2170
2172}
2173/* }}} */
2174
2175/* {{{ Gets the number of required parameters */
2176ZEND_METHOD(ReflectionFunctionAbstract, getNumberOfRequiredParameters)
2177{
2178 reflection_object *intern;
2179 zend_function *fptr;
2180
2182 RETURN_THROWS();
2183 }
2184
2186
2188}
2189/* }}} */
2190
2191/* {{{ Returns an array of parameter objects for this function */
2193{
2194 reflection_object *intern;
2195 zend_function *fptr;
2196 uint32_t i, num_args;
2197 struct _zend_arg_info *arg_info;
2198
2200 RETURN_THROWS();
2201 }
2202
2204
2205 arg_info= fptr->common.arg_info;
2206 num_args = fptr->common.num_args;
2207 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2208 num_args++;
2209 }
2210
2211 if (!num_args) {
2213 }
2214
2216 for (i = 0; i < num_args; i++) {
2217 zval parameter;
2218
2219 reflection_parameter_factory(
2220 _copy_function(fptr),
2221 Z_ISUNDEF(intern->obj) ? NULL : &intern->obj,
2222 arg_info,
2223 i,
2224 i < fptr->common.required_num_args,
2225 &parameter
2226 );
2228
2229 arg_info++;
2230 }
2231}
2232/* }}} */
2233
2234/* {{{ Returns NULL or the extension the function belongs to */
2236{
2237 reflection_object *intern;
2238 zend_function *fptr;
2239 zend_internal_function *internal;
2240
2242 RETURN_THROWS();
2243 }
2244
2246
2247 if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2248 RETURN_NULL();
2249 }
2250
2251 internal = (zend_internal_function *)fptr;
2252 if (internal->module) {
2253 reflection_extension_factory(return_value, internal->module->name);
2254 } else {
2255 RETURN_NULL();
2256 }
2257}
2258/* }}} */
2259
2260/* {{{ Returns false or the name of the extension the function belongs to */
2262{
2263 reflection_object *intern;
2264 zend_function *fptr;
2265 zend_internal_function *internal;
2266
2268 RETURN_THROWS();
2269 }
2270
2272
2273 if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2275 }
2276
2277 internal = (zend_internal_function *)fptr;
2278 if (internal->module) {
2279 RETURN_STRING(internal->module->name);
2280 } else {
2282 }
2283}
2284/* }}} */
2285
2286/* {{{ */
2288{
2290 reflection_object *intern;
2291
2292 object = ZEND_THIS;
2293 intern = Z_REFLECTION_P(object);
2294
2296 RETURN_THROWS();
2297 }
2298
2299 if (intern->ce) {
2300 zval_ptr_dtor(&intern->obj);
2301 }
2302
2303 intern->ref_type = REF_TYPE_GENERATOR;
2304 ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(generator));
2305 intern->ce = zend_ce_generator;
2306}
2307/* }}} */
2308
2309#define REFLECTION_CHECK_VALID_GENERATOR(ex) \
2310 if (!ex) { \
2311 _DO_THROW("Cannot fetch information from a closed Generator"); \
2312 RETURN_THROWS(); \
2313 }
2314
2315/* {{{ */
2317{
2320 zend_generator *root_generator;
2321 zend_execute_data *ex_backup = EG(current_execute_data);
2322 zend_execute_data *ex = generator->execute_data;
2323 zend_execute_data *root_prev = NULL, *cur_prev;
2324
2326 RETURN_THROWS();
2327 }
2328
2330
2331 root_generator = zend_generator_get_current(generator);
2332
2333 cur_prev = generator->execute_data->prev_execute_data;
2334 if (generator == root_generator) {
2335 generator->execute_data->prev_execute_data = NULL;
2336 } else {
2337 root_prev = root_generator->execute_data->prev_execute_data;
2338 generator->execute_fake.prev_execute_data = NULL;
2339 root_generator->execute_data->prev_execute_data = &generator->execute_fake;
2340 }
2341
2342 EG(current_execute_data) = root_generator->execute_data;
2344 EG(current_execute_data) = ex_backup;
2345
2346 root_generator->execute_data->prev_execute_data = root_prev;
2347 generator->execute_data->prev_execute_data = cur_prev;
2348}
2349/* }}} */
2350
2351/* {{{ */
2353{
2355 zend_execute_data *ex = generator->execute_data;
2356
2358 RETURN_THROWS();
2359 }
2360
2362
2363 ZVAL_LONG(return_value, ex->opline->lineno);
2364}
2365/* }}} */
2366
2367/* {{{ */
2369{
2371 zend_execute_data *ex = generator->execute_data;
2372
2374 RETURN_THROWS();
2375 }
2376
2378
2379 ZVAL_STR_COPY(return_value, ex->func->op_array.filename);
2380}
2381/* }}} */
2382
2383/* {{{ */
2385{
2387 zend_function *func = generator->func;
2388
2390 RETURN_THROWS();
2391 }
2392
2393 if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
2394 zval closure;
2395 ZVAL_OBJ(&closure, ZEND_CLOSURE_OBJECT(func));
2396 reflection_function_factory(func, &closure, return_value);
2397 } else if (func->op_array.scope) {
2398 reflection_method_factory(func->op_array.scope, func, NULL, return_value);
2399 } else {
2400 reflection_function_factory(func, NULL, return_value);
2401 }
2402}
2403/* }}} */
2404
2405/* {{{ */
2407{
2409 zend_execute_data *ex = generator->execute_data;
2410
2412 RETURN_THROWS();
2413 }
2414
2416
2417 if (Z_TYPE(ex->This) == IS_OBJECT) {
2418 RETURN_OBJ_COPY(Z_OBJ(ex->This));
2419 } else {
2420 RETURN_NULL();
2421 }
2422}
2423/* }}} */
2424
2425/* {{{ */
2426ZEND_METHOD(ReflectionGenerator, getExecutingGenerator)
2427{
2429 zend_execute_data *ex = generator->execute_data;
2431
2433 RETURN_THROWS();
2434 }
2435
2437
2438 current = zend_generator_get_current(generator);
2439 RETURN_OBJ_COPY(&current->std);
2440}
2441/* }}} */
2442
2444{
2446 zend_execute_data *ex = generator->execute_data;
2447
2449 RETURN_THROWS();
2450 }
2451
2452 RETURN_BOOL(ex == NULL);
2453}
2454
2455/* {{{ Constructor. Throws an Exception in case the given method does not exist */
2457{
2459 zval *reference;
2460 zend_string *arg_name = NULL;
2461 zend_long position;
2462 zval *object;
2463 zval *prop_name;
2464 reflection_object *intern;
2465 zend_function *fptr;
2466 struct _zend_arg_info *arg_info;
2467 uint32_t num_args;
2468 zend_class_entry *ce = NULL;
2469 bool is_closure = 0;
2470
2472 Z_PARAM_ZVAL(reference)
2473 Z_PARAM_STR_OR_LONG(arg_name, position)
2475
2476 object = ZEND_THIS;
2477 intern = Z_REFLECTION_P(object);
2478
2479 /* First, find the function */
2480 switch (Z_TYPE_P(reference)) {
2481 case IS_STRING:
2482 {
2483 zend_string *lcname = zend_string_tolower(Z_STR_P(reference));
2484 fptr = zend_hash_find_ptr(EG(function_table), lcname);
2485 zend_string_release(lcname);
2486 if (!fptr) {
2488 "Function %s() does not exist", Z_STRVAL_P(reference));
2489 RETURN_THROWS();
2490 }
2491 ce = fptr->common.scope;
2492 }
2493 break;
2494
2495 case IS_ARRAY: {
2496 zval *classref;
2497 zval *method;
2499
2500 if (((classref = zend_hash_index_find(Z_ARRVAL_P(reference), 0)) == NULL)
2501 || ((method = zend_hash_index_find(Z_ARRVAL_P(reference), 1)) == NULL))
2502 {
2503 _DO_THROW("Expected array($object, $method) or array($classname, $method)");
2504 RETURN_THROWS();
2505 }
2506
2507 if (Z_TYPE_P(classref) == IS_OBJECT) {
2508 ce = Z_OBJCE_P(classref);
2509 } else {
2510 name = zval_try_get_string(classref);
2511 if (UNEXPECTED(!name)) {
2512 return;
2513 }
2514 if ((ce = zend_lookup_class(name)) == NULL) {
2516 "Class \"%s\" does not exist", ZSTR_VAL(name));
2517 zend_string_release(name);
2518 RETURN_THROWS();
2519 }
2520 zend_string_release(name);
2521 }
2522
2523 name = zval_try_get_string(method);
2524 if (UNEXPECTED(!name)) {
2525 return;
2526 }
2527
2528 lcname = zend_string_tolower(name);
2529 if (Z_TYPE_P(classref) == IS_OBJECT && is_closure_invoke(ce, lcname)
2530 && (fptr = zend_get_closure_invoke_method(Z_OBJ_P(classref))) != NULL)
2531 {
2532 /* nothing to do. don't set is_closure since is the invoke handler,
2533 not the closure itself */
2534 } else if ((fptr = zend_hash_find_ptr(&ce->function_table, lcname)) == NULL) {
2536 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
2537 zend_string_release(name);
2538 zend_string_release(lcname);
2539 RETURN_THROWS();
2540 }
2541 zend_string_release(name);
2542 zend_string_release(lcname);
2543 }
2544 break;
2545
2546 case IS_OBJECT: {
2547 ce = Z_OBJCE_P(reference);
2548
2549 if (instanceof_function(ce, zend_ce_closure)) {
2551 Z_ADDREF_P(reference);
2552 is_closure = 1;
2553 } else if ((fptr = zend_hash_find_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE))) == NULL) {
2555 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZEND_INVOKE_FUNC_NAME);
2556 RETURN_THROWS();
2557 }
2558 }
2559 break;
2560
2561 default:
2562 zend_argument_error(reflection_exception_ptr, 1, "must be a string, an array(class, method), or a callable object, %s given", zend_zval_value_name(reference));
2563 RETURN_THROWS();
2564 }
2565
2566 /* Now, search for the parameter */
2567 arg_info = fptr->common.arg_info;
2568 num_args = fptr->common.num_args;
2569 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2570 num_args++;
2571 }
2572 if (arg_name != NULL) {
2573 uint32_t i;
2574 position = -1;
2575
2576 if (has_internal_arg_info(fptr)) {
2577 for (i = 0; i < num_args; i++) {
2578 if (arg_info[i].name) {
2579 if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, ZSTR_VAL(arg_name)) == 0) {
2580 position = i;
2581 break;
2582 }
2583 }
2584 }
2585 } else {
2586 for (i = 0; i < num_args; i++) {
2587 if (arg_info[i].name) {
2588 if (zend_string_equals(arg_name, arg_info[i].name)) {
2589 position = i;
2590 break;
2591 }
2592 }
2593 }
2594 }
2595 if (position == -1) {
2596 _DO_THROW("The parameter specified by its name could not be found");
2597 goto failure;
2598 }
2599 } else {
2600 if (position < 0) {
2601 zend_argument_value_error(2, "must be greater than or equal to 0");
2602 goto failure;
2603 }
2604 if (position >= num_args) {
2605 _DO_THROW("The parameter specified by its offset could not be found");
2606 goto failure;
2607 }
2608 }
2609
2610 if (intern->ptr) {
2611 reflection_free_parameter_reference(intern->ptr);
2612 }
2613
2615 ref->arg_info = &arg_info[position];
2616 ref->offset = (uint32_t)position;
2617 ref->required = (uint32_t)position < fptr->common.required_num_args;
2618 ref->fptr = fptr;
2619 /* TODO: copy fptr */
2620 intern->ptr = ref;
2621 intern->ref_type = REF_TYPE_PARAMETER;
2622 intern->ce = ce;
2623 zval_ptr_dtor(&intern->obj);
2624 if (reference && is_closure) {
2625 ZVAL_COPY_VALUE(&intern->obj, reference);
2626 } else {
2627 ZVAL_UNDEF(&intern->obj);
2628 }
2629
2630 prop_name = reflection_prop_name(object);
2631 zval_ptr_dtor(prop_name);
2632 if (has_internal_arg_info(fptr)) {
2633 ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)[position].name);
2634 } else {
2635 ZVAL_STR_COPY(prop_name, arg_info[position].name);
2636 }
2637 return;
2638
2639failure:
2643 }
2644 if (is_closure) {
2645 zval_ptr_dtor(reference);
2646 }
2647 RETURN_THROWS();
2648}
2649/* }}} */
2650
2651/* {{{ Returns a string representation */
2653{
2654 reflection_object *intern;
2655 parameter_reference *param;
2656 smart_str str = {0};
2657
2659 RETURN_THROWS();
2660 }
2662 _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "");
2663 RETURN_STR(smart_str_extract(&str));
2664}
2665
2666/* }}} */
2667
2668/* {{{ Returns this parameters's name */
2670{
2671 reflection_object *intern;
2672 parameter_reference *param;
2673
2675 RETURN_THROWS();
2676 }
2677
2679 if (has_internal_arg_info(param->fptr)) {
2680 RETURN_STRING(((zend_internal_arg_info *) param->arg_info)->name);
2681 } else {
2682 RETURN_STR_COPY(param->arg_info->name);
2683 }
2684}
2685/* }}} */
2686
2687/* {{{ Returns the ReflectionFunction for the function of this parameter */
2688ZEND_METHOD(ReflectionParameter, getDeclaringFunction)
2689{
2690 reflection_object *intern;
2691 parameter_reference *param;
2692
2694 RETURN_THROWS();
2695 }
2697
2698 if (!param->fptr->common.scope) {
2699 reflection_function_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2700 } else {
2701 reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2702 }
2703}
2704/* }}} */
2705
2706/* {{{ Returns in which class this parameter is defined (not the type of the parameter) */
2708{
2709 reflection_object *intern;
2710 parameter_reference *param;
2711
2713 RETURN_THROWS();
2714 }
2716
2717 if (param->fptr->common.scope) {
2719 }
2720}
2721/* }}} */
2722
2723/* {{{ Returns this parameters's class hint or NULL if there is none */
2725{
2726 reflection_object *intern;
2727 parameter_reference *param;
2728 zend_class_entry *ce;
2729
2731 RETURN_THROWS();
2732 }
2734
2735 // TODO: This is going to return null for union types, which is rather odd.
2736 if (ZEND_TYPE_HAS_NAME(param->arg_info->type)) {
2737 /* Class name is stored as a string, we might also get "self" or "parent"
2738 * - For "self", simply use the function scope. If scope is NULL then
2739 * the function is global and thus self does not make any sense
2740 *
2741 * - For "parent", use the function scope's parent. If scope is NULL then
2742 * the function is global and thus parent does not make any sense.
2743 * If the parent is NULL then the class does not extend anything and
2744 * thus parent does not make any sense, either.
2745 *
2746 * TODO: Think about moving these checks to the compiler or some sort of
2747 * lint-mode.
2748 */
2749 zend_string *class_name;
2750
2751 class_name = ZEND_TYPE_NAME(param->arg_info->type);
2752 if (zend_string_equals_literal_ci(class_name, "self")) {
2753 ce = param->fptr->common.scope;
2754 if (!ce) {
2756 "Parameter uses \"self\" as type but function is not a class member");
2757 RETURN_THROWS();
2758 }
2759 } else if (zend_string_equals_literal_ci(class_name, "parent")) {
2760 ce = param->fptr->common.scope;
2761 if (!ce) {
2763 "Parameter uses \"parent\" as type but function is not a class member");
2764 RETURN_THROWS();
2765 }
2766 if (!ce->parent) {
2768 "Parameter uses \"parent\" as type although class does not have a parent");
2769 RETURN_THROWS();
2770 }
2771 ce = ce->parent;
2772 } else {
2773 ce = zend_lookup_class(class_name);
2774 if (!ce) {
2776 "Class \"%s\" does not exist", ZSTR_VAL(class_name));
2777 RETURN_THROWS();
2778 }
2779 }
2781 }
2782}
2783/* }}} */
2784
2785/* {{{ Returns whether parameter has a type */
2787{
2788 reflection_object *intern;
2789 parameter_reference *param;
2790
2792 RETURN_THROWS();
2793 }
2795
2797}
2798/* }}} */
2799
2800/* {{{ Returns the type associated with the parameter */
2802{
2803 reflection_object *intern;
2804 parameter_reference *param;
2805
2807 RETURN_THROWS();
2808 }
2810
2811 if (!ZEND_TYPE_IS_SET(param->arg_info->type)) {
2812 RETURN_NULL();
2813 }
2814 reflection_type_factory(param->arg_info->type, return_value, 1);
2815}
2816/* }}} */
2817
2818/* {{{ Returns whether parameter MUST be an array */
2820{
2821 reflection_object *intern;
2822 parameter_reference *param;
2823 uint32_t type_mask;
2824
2826 RETURN_THROWS();
2827 }
2829
2830 /* BC For iterable */
2833 }
2834
2835 type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(param->arg_info->type);
2836 RETVAL_BOOL(type_mask == MAY_BE_ARRAY);
2837}
2838/* }}} */
2839
2840/* {{{ Returns whether parameter MUST be callable */
2842{
2843 reflection_object *intern;
2844 parameter_reference *param;
2845 uint32_t type_mask;
2846
2848 RETURN_THROWS();
2849 }
2851
2852 type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(param->arg_info->type);
2853 RETVAL_BOOL(type_mask == MAY_BE_CALLABLE);
2854}
2855/* }}} */
2856
2857/* {{{ Returns whether NULL is allowed as this parameters's value */
2859{
2860 reflection_object *intern;
2861 parameter_reference *param;
2862
2864 RETURN_THROWS();
2865 }
2867
2869 || ZEND_TYPE_ALLOW_NULL(param->arg_info->type));
2870}
2871/* }}} */
2872
2873/* {{{ Returns whether this parameters is passed to by reference */
2875{
2876 reflection_object *intern;
2877 parameter_reference *param;
2878
2880 RETURN_THROWS();
2881 }
2883
2885}
2886/* }}} */
2887
2888/* {{{ Returns whether this parameter can be passed by value */
2890{
2891 reflection_object *intern;
2892 parameter_reference *param;
2893
2895 RETURN_THROWS();
2896 }
2898
2899 /* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */
2901}
2902/* }}} */
2903
2904/* {{{ Get parameter attributes. */
2906{
2907 reflection_object *intern;
2908 parameter_reference *param;
2909
2911
2912 HashTable *attributes = param->fptr->common.attributes;
2914
2915 reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU,
2916 attributes, param->offset + 1, scope, ZEND_ATTRIBUTE_TARGET_PARAMETER,
2917 param->fptr->type == ZEND_USER_FUNCTION ? param->fptr->op_array.filename : NULL);
2918}
2919
2920/* {{{ Returns whether this parameter is an optional parameter */
2922{
2923 reflection_object *intern;
2924 parameter_reference *param;
2925
2927 RETURN_THROWS();
2928 }
2930
2931 RETVAL_LONG(param->offset);
2932}
2933/* }}} */
2934
2935/* {{{ Returns whether this parameter is an optional parameter */
2937{
2938 reflection_object *intern;
2939 parameter_reference *param;
2940
2942 RETURN_THROWS();
2943 }
2945
2946 RETVAL_BOOL(!param->required);
2947}
2948/* }}} */
2949
2950/* {{{ Returns whether the default value of this parameter is available */
2951ZEND_METHOD(ReflectionParameter, isDefaultValueAvailable)
2952{
2953 reflection_object *intern;
2954 parameter_reference *param;
2955
2957 RETURN_THROWS();
2958 }
2959
2961
2962 if (param->fptr->type == ZEND_INTERNAL_FUNCTION) {
2964 && ((zend_internal_arg_info*) (param->arg_info))->default_value);
2965 } else {
2966 zval *default_value = get_default_from_recv((zend_op_array *)param->fptr, param->offset);
2968 }
2969}
2970/* }}} */
2971
2972/* {{{ Returns the default value of this parameter or throws an exception */
2974{
2975 reflection_object *intern;
2976 parameter_reference *param;
2977
2979 RETURN_THROWS();
2980 }
2981
2983
2984 if (get_parameter_default(return_value, param) == FAILURE) {
2986 "Internal error: Failed to retrieve the default value");
2987 RETURN_THROWS();
2988 }
2989
2992 }
2993}
2994/* }}} */
2995
2996/* {{{ Returns whether the default value of this parameter is constant */
2997ZEND_METHOD(ReflectionParameter, isDefaultValueConstant)
2998{
2999 reflection_object *intern;
3000 parameter_reference *param;
3001
3003 RETURN_THROWS();
3004 }
3005
3007
3009 if (get_parameter_default(&default_value, param) == FAILURE) {
3011 "Internal error: Failed to retrieve the default value");
3012 RETURN_THROWS();
3013 }
3014
3018 || ast->kind == ZEND_AST_CONSTANT_CLASS
3019 || ast->kind == ZEND_AST_CLASS_CONST);
3020 } else {
3022 }
3023
3024 zval_ptr_dtor_nogc(&default_value);
3025}
3026/* }}} */
3027
3028/* {{{ Returns the default value's constant name if default value is constant or null */
3029ZEND_METHOD(ReflectionParameter, getDefaultValueConstantName)
3030{
3031 reflection_object *intern;
3032 parameter_reference *param;
3033
3035 RETURN_THROWS();
3036 }
3037
3039
3041 if (get_parameter_default(&default_value, param) == FAILURE) {
3043 "Internal error: Failed to retrieve the default value");
3044 RETURN_THROWS();
3045 }
3046
3048 zval_ptr_dtor_nogc(&default_value);
3049 RETURN_NULL();
3050 }
3051
3053 if (ast->kind == ZEND_AST_CONSTANT) {
3054 RETVAL_STR_COPY(zend_ast_get_constant_name(ast));
3055 } else if (ast->kind == ZEND_AST_CONSTANT_CLASS) {
3056 RETVAL_STRINGL("__CLASS__", sizeof("__CLASS__")-1);
3057 } else if (ast->kind == ZEND_AST_CLASS_CONST) {
3058 zend_string *class_name = zend_ast_get_str(ast->child[0]);
3059 zend_string *const_name = zend_ast_get_str(ast->child[1]);
3061 ZSTR_VAL(class_name), ZSTR_LEN(class_name),
3062 "::", sizeof("::")-1,
3063 ZSTR_VAL(const_name), ZSTR_LEN(const_name)));
3064 } else {
3065 RETVAL_NULL();
3066 }
3067 zval_ptr_dtor_nogc(&default_value);
3068}
3069
3070/* {{{ Returns whether this parameter is a variadic parameter */
3072{
3073 reflection_object *intern;
3074 parameter_reference *param;
3075
3077 RETURN_THROWS();
3078 }
3080
3082}
3083/* }}} */
3084
3085/* {{{ Returns this constructor parameter has been promoted to a property */
3087{
3088 reflection_object *intern;
3089 parameter_reference *param;
3090
3092 RETURN_THROWS();
3093 }
3095
3097}
3098/* }}} */
3099
3100/* {{{ Returns whether parameter MAY be null */
3102{
3103 reflection_object *intern;
3104 type_reference *param;
3105
3107 RETURN_THROWS();
3108 }
3110
3112}
3113/* }}} */
3114
3115/* For BC with iterable for named types */
3116static zend_string *zend_named_reflection_type_to_string(zend_type type) {
3118 zend_string *iterable = ZSTR_KNOWN(ZEND_STR_ITERABLE);
3120 return zend_string_concat2("?", strlen("?"), ZSTR_VAL(iterable), ZSTR_LEN(iterable));
3121 }
3122 return iterable;
3123 }
3124 return zend_type_to_string(type);
3125}
3126
3127static zend_string *zend_type_to_string_without_null(zend_type type) {
3129 return zend_named_reflection_type_to_string(type);
3130}
3131
3132/* {{{ Return the text of the type hint */
3134{
3135 reflection_object *intern;
3136 type_reference *param;
3137
3139 RETURN_THROWS();
3140 }
3142
3143 RETURN_STR(zend_named_reflection_type_to_string(param->type));
3144}
3145/* }}} */
3146
3147/* {{{ Return the name of the type */
3149{
3150 reflection_object *intern;
3151 type_reference *param;
3152
3154 RETURN_THROWS();
3155 }
3157
3158 if (param->legacy_behavior) {
3159 RETURN_STR(zend_type_to_string_without_null(param->type));
3160 }
3161 RETURN_STR(zend_named_reflection_type_to_string(param->type));
3162}
3163/* }}} */
3164
3165/* {{{ Returns whether type is a builtin type */
3167{
3168 reflection_object *intern;
3169 type_reference *param;
3170
3172 RETURN_THROWS();
3173 }
3175
3178 }
3179
3180 /* Treat "static" as a class type for the purposes of reflection. */
3182 && !(ZEND_TYPE_FULL_MASK(param->type) & MAY_BE_STATIC));
3183}
3184/* }}} */
3185
3186static void append_type(zval *return_value, zend_type type) {
3187 zval reflection_type;
3188 /* Drop iterable BC bit for type list */
3191 }
3192
3193 reflection_type_factory(type, &reflection_type, 0);
3195}
3196
3197static void append_type_mask(zval *return_value, uint32_t type_mask) {
3198 append_type(return_value, (zend_type) ZEND_TYPE_INIT_MASK(type_mask));
3199}
3200
3201/* {{{ Returns the types that are part of this union type */
3203{
3204 reflection_object *intern;
3205 type_reference *param;
3206 uint32_t type_mask;
3207
3209 RETURN_THROWS();
3210 }
3212
3214 if (ZEND_TYPE_HAS_LIST(param->type)) {
3215 zend_type *list_type;
3216 ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(param->type), list_type) {
3217 append_type(return_value, *list_type);
3219 } else if (ZEND_TYPE_HAS_NAME(param->type)) {
3221 append_type(return_value, (zend_type) ZEND_TYPE_INIT_CLASS(name, 0, 0));
3222 }
3223
3224 type_mask = ZEND_TYPE_PURE_MASK(param->type);
3225 ZEND_ASSERT(!(type_mask & MAY_BE_VOID));
3226 ZEND_ASSERT(!(type_mask & MAY_BE_NEVER));
3227 if (type_mask & MAY_BE_STATIC) {
3228 append_type_mask(return_value, MAY_BE_STATIC);
3229 }
3230 if (type_mask & MAY_BE_CALLABLE) {
3231 append_type_mask(return_value, MAY_BE_CALLABLE);
3232 }
3233 if (type_mask & MAY_BE_OBJECT) {
3234 append_type_mask(return_value, MAY_BE_OBJECT);
3235 }
3236 if (type_mask & MAY_BE_ARRAY) {
3237 append_type_mask(return_value, MAY_BE_ARRAY);
3238 }
3239 if (type_mask & MAY_BE_STRING) {
3240 append_type_mask(return_value, MAY_BE_STRING);
3241 }
3242 if (type_mask & MAY_BE_LONG) {
3243 append_type_mask(return_value, MAY_BE_LONG);
3244 }
3245 if (type_mask & MAY_BE_DOUBLE) {
3246 append_type_mask(return_value, MAY_BE_DOUBLE);
3247 }
3248 if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) {
3249 append_type_mask(return_value, MAY_BE_BOOL);
3250 } else if (type_mask & MAY_BE_TRUE) {
3251 append_type_mask(return_value, MAY_BE_TRUE);
3252 } else if (type_mask & MAY_BE_FALSE) {
3253 append_type_mask(return_value, MAY_BE_FALSE);
3254 }
3255 if (type_mask & MAY_BE_NULL) {
3256 append_type_mask(return_value, MAY_BE_NULL);
3257 }
3258}
3259/* }}} */
3260
3261/* {{{ Returns the types that are part of this intersection type */
3263{
3264 reflection_object *intern;
3265 type_reference *param;
3266 zend_type *list_type;
3267
3269 RETURN_THROWS();
3270 }
3272
3274
3276 ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(param->type), list_type) {
3277 append_type(return_value, *list_type);
3279}
3280/* }}} */
3281
3282/* {{{ Constructor. Throws an Exception in case the given method does not exist */
3283static void instantiate_reflection_method(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
3284{
3285 zend_object *arg1_obj = NULL;
3286 zend_string *arg1_str;
3287 zend_string *arg2_str = NULL;
3288
3289 zend_object *orig_obj = NULL;
3290 zend_class_entry *ce = NULL;
3291 zend_string *class_name = NULL;
3292 char *method_name;
3293 size_t method_name_len;
3294 char *lcname;
3295
3296 zval *object;
3297 reflection_object *intern;
3298 zend_function *mptr;
3299
3300 if (is_constructor) {
3301 if (ZEND_NUM_ARGS() == 1) {
3302 zend_error(E_DEPRECATED, "Calling ReflectionMethod::__construct() with 1 argument is deprecated, "
3303 "use ReflectionMethod::createFromMethodName() instead");
3304 if (UNEXPECTED(EG(exception))) {
3305 RETURN_THROWS();
3306 }
3307 }
3308
3310 Z_PARAM_OBJ_OR_STR(arg1_obj, arg1_str)
3312 Z_PARAM_STR_OR_NULL(arg2_str)
3314 } else {
3316 Z_PARAM_STR(arg1_str)
3318 }
3319
3320 if (arg1_obj) {
3321 if (!arg2_str) {
3322 zend_argument_value_error(2, "cannot be null when argument #1 ($objectOrMethod) is an object");
3323 RETURN_THROWS();
3324 }
3325
3326 orig_obj = arg1_obj;
3327 ce = arg1_obj->ce;
3328 method_name = ZSTR_VAL(arg2_str);
3329 method_name_len = ZSTR_LEN(arg2_str);
3330 } else if (arg2_str) {
3331 class_name = zend_string_copy(arg1_str);
3332 method_name = ZSTR_VAL(arg2_str);
3333 method_name_len = ZSTR_LEN(arg2_str);
3334 } else {
3335 char *tmp;
3336 size_t tmp_len;
3337 char *name = ZSTR_VAL(arg1_str);
3338
3339 if ((tmp = strstr(name, "::")) == NULL) {
3340 zend_argument_error(reflection_exception_ptr, 1, "must be a valid method name");
3341 RETURN_THROWS();
3342 }
3343 tmp_len = tmp - name;
3344
3345 class_name = zend_string_init(name, tmp_len, 0);
3346 method_name = tmp + 2;
3347 method_name_len = ZSTR_LEN(arg1_str) - tmp_len - 2;
3348 }
3349
3350 if (class_name) {
3351 if ((ce = zend_lookup_class(class_name)) == NULL) {
3352 if (!EG(exception)) {
3353 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class \"%s\" does not exist", ZSTR_VAL(class_name));
3354 }
3355 zend_string_release(class_name);
3356 RETURN_THROWS();
3357 }
3358
3359 zend_string_release(class_name);
3360 }
3361
3362 if (is_constructor) {
3363 object = ZEND_THIS;
3364 } else {
3366 object = return_value;
3367 }
3368 intern = Z_REFLECTION_P(object);
3369
3370 lcname = zend_str_tolower_dup(method_name, method_name_len);
3371
3372 if (ce == zend_ce_closure && orig_obj && (method_name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
3373 && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
3374 && (mptr = zend_get_closure_invoke_method(orig_obj)) != NULL)
3375 {
3376 /* do nothing, mptr already set */
3377 } else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, method_name_len)) == NULL) {
3378 efree(lcname);
3380 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), method_name);
3381 RETURN_THROWS();
3382 }
3383 efree(lcname);
3384
3385 ZVAL_STR_COPY(reflection_prop_name(object), mptr->common.function_name);
3386 ZVAL_STR_COPY(reflection_prop_class(object), mptr->common.scope->name);
3387 intern->ptr = mptr;
3388 intern->ref_type = REF_TYPE_FUNCTION;
3389 intern->ce = ce;
3390}
3391
3392/* {{{ Constructor. Throws an Exception in case the given method does not exist */
3394 instantiate_reflection_method(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
3395}
3396/* }}} */
3397
3398ZEND_METHOD(ReflectionMethod, createFromMethodName) {
3399 instantiate_reflection_method(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
3400}
3401
3402/* {{{ Returns a string representation */
3404{
3405 reflection_object *intern;
3406 zend_function *mptr;
3407 smart_str str = {0};
3408
3410 RETURN_THROWS();
3411 }
3413 _function_string(&str, mptr, intern->ce, "");
3414 RETURN_STR(smart_str_extract(&str));
3415}
3416/* }}} */
3417
3418/* {{{ Invokes the function */
3420{
3421 reflection_object *intern;
3422 zval *obj = NULL;
3423 zend_function *mptr;
3424
3425 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &obj) == FAILURE) {
3426 RETURN_THROWS();
3427 }
3428
3430
3431 if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3433 } else {
3434 if (!obj) {
3435 zend_argument_value_error(1, "cannot be null for non-static methods");
3436 RETURN_THROWS();
3437 }
3438
3439 if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope)) {
3440 _DO_THROW("Given object is not an instance of the class this method was declared in");
3441 RETURN_THROWS();
3442 }
3443
3444 /* This is an original closure object and __invoke is to be called. */
3445 if (Z_OBJCE_P(obj) == zend_ce_closure &&
3447 {
3449 } else {
3451 }
3452 }
3453}
3454/* }}} */
3455
3456/* {{{ reflection_method_invoke */
3457static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic)
3458{
3459 zval retval;
3460 zval *params = NULL, *object;
3461 HashTable *named_params = NULL;
3462 reflection_object *intern;
3463 zend_function *mptr, *callback;
3464 uint32_t argc = 0;
3465 zend_class_entry *obj_ce;
3466
3468
3469 if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
3471 "Trying to invoke abstract method %s::%s()",
3473 RETURN_THROWS();
3474 }
3475
3476 if (variadic) {
3479 Z_PARAM_VARIADIC_WITH_NAMED(params, argc, named_params)
3481 } else {
3482 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!h", &object, &named_params) == FAILURE) {
3483 RETURN_THROWS();
3484 }
3485 }
3486
3487 /* In case this is a static method, we shouldn't pass an object_ptr
3488 * (which is used as calling context aka $this). We can thus ignore the
3489 * first parameter.
3490 *
3491 * Else, we verify that the given object is an instance of the class.
3492 */
3493 if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3494 object = NULL;
3495 obj_ce = mptr->common.scope;
3496 } else {
3497 if (!object) {
3499 "Trying to invoke non static method %s::%s() without an object",
3501 RETURN_THROWS();
3502 }
3503
3504 obj_ce = Z_OBJCE_P(object);
3505
3506 if (!instanceof_function(obj_ce, mptr->common.scope)) {
3507 if (!variadic) {
3508 efree(params);
3509 }
3510 _DO_THROW("Given object is not an instance of the class this method was declared in");
3511 RETURN_THROWS();
3512 }
3513 }
3514 /* Copy the zend_function when calling via handler (e.g. Closure::__invoke()) */
3515 callback = _copy_function(mptr);
3516 zend_call_known_function(callback, (object ? Z_OBJ_P(object) : NULL), intern->ce, &retval, argc, params, named_params);
3517
3518 if (Z_TYPE(retval) == IS_UNDEF && !EG(exception)) {
3520 "Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3521 RETURN_THROWS();
3522 }
3523
3524 if (Z_ISREF(retval)) {
3525 zend_unwrap_reference(&retval);
3526 }
3528}
3529/* }}} */
3530
3531/* {{{ Invokes the method. */
3533{
3534 reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3535}
3536/* }}} */
3537
3538/* {{{ Invokes the function and pass its arguments as array. */
3540{
3541 reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3542}
3543/* }}} */
3544
3545/* {{{ Returns whether this method is final */
3547{
3548 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
3549}
3550/* }}} */
3551
3552/* {{{ Returns whether this method is abstract */
3554{
3556}
3557/* }}} */
3558
3559/* {{{ Returns whether this method is public */
3561{
3563}
3564/* }}} */
3565
3566/* {{{ Returns whether this method is private */
3568{
3570}
3571/* }}} */
3572
3573/* {{{ Returns whether this method is protected */
3575{
3577}
3578/* }}} */
3579
3580/* {{{ Returns whether this function is deprecated */
3585/* }}} */
3586
3587/* {{{ Returns whether this function is a generator */
3592/* }}} */
3593
3594/* {{{ Returns whether this function is variadic */
3599/* }}} */
3600
3601/* {{{ Returns whether this function is static */
3606/* }}} */
3607
3608/* {{{ Returns whether this function is defined in namespace */
3610{
3611 reflection_object *intern;
3612 zend_function *fptr;
3613
3615 RETURN_THROWS();
3616 }
3617
3619
3622 }
3623
3625 const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
3626 RETURN_BOOL(backslash);
3627}
3628/* }}} */
3629
3630/* {{{ Returns the name of namespace where this function is defined */
3632{
3633 reflection_object *intern;
3634 zend_function *fptr;
3635
3637 RETURN_THROWS();
3638 }
3639
3641
3644 }
3645
3647 const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
3648 if (backslash) {
3649 RETURN_STRINGL(ZSTR_VAL(name), backslash - ZSTR_VAL(name));
3650 }
3652}
3653/* }}} */
3654
3655/* {{{ Returns the short name of the function (without namespace part) */
3657{
3658 reflection_object *intern;
3659 zend_function *fptr;
3660
3662 RETURN_THROWS();
3663 }
3664
3666
3669 const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
3670 if (backslash) {
3671 RETURN_STRINGL(backslash + 1, ZSTR_LEN(name) - (backslash - ZSTR_VAL(name) + 1));
3672 }
3673 }
3674
3676}
3677/* }}} */
3678
3679/* {{{ Return whether the function has a return type */
3681{
3682 reflection_object *intern;
3683 zend_function *fptr;
3684
3686 RETURN_THROWS();
3687 }
3688
3690
3692}
3693/* }}} */
3694
3695/* {{{ Returns the return type associated with the function */
3697{
3698 reflection_object *intern;
3699 zend_function *fptr;
3700
3702 RETURN_THROWS();
3703 }
3704
3706
3708 RETURN_NULL();
3709 }
3710
3711 reflection_type_factory(fptr->common.arg_info[-1].type, return_value, 1);
3712}
3713/* }}} */
3714
3715/* {{{ Return whether the function has a return type */
3717{
3718 reflection_object *intern;
3719 zend_function *fptr;
3720
3722 RETURN_THROWS();
3723 }
3724
3726
3728}
3729/* }}} */
3730
3731/* {{{ Returns the return type associated with the function */
3733{
3734 reflection_object *intern;
3735 zend_function *fptr;
3736
3738 RETURN_THROWS();
3739 }
3740
3742
3744 RETURN_NULL();
3745 }
3746
3747 reflection_type_factory(fptr->common.arg_info[-1].type, return_value, 1);
3748}
3749/* }}} */
3750
3751/* {{{ Returns whether this method is the constructor */
3753{
3754 reflection_object *intern;
3755 zend_function *mptr;
3756
3758 RETURN_THROWS();
3759 }
3761 /* we need to check if the ctor is the ctor of the class level we we
3762 * looking at since we might be looking at an inherited old style ctor
3763 * defined in base class. */
3764 RETURN_BOOL((mptr->common.fn_flags & ZEND_ACC_CTOR) && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
3765}
3766/* }}} */
3767
3768/* {{{ Returns whether this method is a destructor */
3781/* }}} */
3782
3783/* {{{ Returns a bitfield of the access modifiers for this method */
3785{
3786 reflection_object *intern;
3787 zend_function *mptr;
3788 uint32_t keep_flags = ZEND_ACC_PPP_MASK
3790
3792 RETURN_THROWS();
3793 }
3795
3796 RETURN_LONG((mptr->common.fn_flags & keep_flags));
3797}
3798/* }}} */
3799
3800/* {{{ Get the declaring class */
3802{
3803 reflection_object *intern;
3804 zend_function *mptr;
3805
3807 RETURN_THROWS();
3808 }
3809
3811
3813}
3814/* }}} */
3815
3816/* {{{ Returns whether a method has a prototype or not */
3818{
3819 reflection_object *intern;
3820 zend_function *mptr;
3821
3823 RETURN_THROWS();
3824 }
3825
3827 RETURN_BOOL(mptr->common.prototype != NULL);
3828}
3829/* }}} */
3830
3831/* {{{ Get the prototype */
3833{
3834 reflection_object *intern;
3835 zend_function *mptr;
3836
3838 RETURN_THROWS();
3839 }
3840
3842
3843 if (!mptr->common.prototype) {
3845 "Method %s::%s does not have a prototype", ZSTR_VAL(intern->ce->name), ZSTR_VAL(mptr->common.function_name));
3846 RETURN_THROWS();
3847 }
3848
3849 reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value);
3850}
3851/* }}} */
3852
3853/* {{{ Sets whether non-public methods can be invoked */
3855{
3856 bool visible;
3857
3858 if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
3859 RETURN_THROWS();
3860 }
3861}
3862/* }}} */
3863
3864/* {{{ Constructor. Throws an Exception in case the given class constant does not exist */
3866{
3867 zval *object;
3868 zend_string *classname_str;
3869 zend_object *classname_obj;
3870 zend_string *constname;
3871 reflection_object *intern;
3872 zend_class_entry *ce;
3874
3876 Z_PARAM_OBJ_OR_STR(classname_obj, classname_str)
3877 Z_PARAM_STR(constname)
3879
3880 if (classname_obj) {
3881 ce = classname_obj->ce;
3882 } else {
3883 if ((ce = zend_lookup_class(classname_str)) == NULL) {
3884 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class \"%s\" does not exist", ZSTR_VAL(classname_str));
3885 RETURN_THROWS();
3886 }
3887 }
3888
3889 object = ZEND_THIS;
3890 intern = Z_REFLECTION_P(object);
3891
3892 if ((constant = zend_hash_find_ptr(CE_CONSTANTS_TABLE(ce), constname)) == NULL) {
3893 zend_throw_exception_ex(reflection_exception_ptr, 0, "Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
3894 RETURN_THROWS();
3895 }
3896
3897 intern->ptr = constant;
3899 intern->ce = constant->ce;
3900 ZVAL_STR_COPY(reflection_prop_name(object), constname);
3901 ZVAL_STR_COPY(reflection_prop_class(object), constant->ce->name);
3902}
3903/* }}} */
3904
3905/* {{{ Returns a string representation */
3907{
3908 reflection_object *intern;
3910 smart_str str = {0};
3911
3913 RETURN_THROWS();
3914 }
3915
3917
3918 zval *name = reflection_prop_name(ZEND_THIS);
3919 if (Z_ISUNDEF_P(name)) {
3921 "Typed property ReflectionClassConstant::$name "
3922 "must not be accessed before initialization");
3923 RETURN_THROWS();
3924 }
3927
3928 _class_const_string(&str, Z_STR_P(name), ref, "");
3929 RETURN_STR(smart_str_extract(&str));
3930}
3931/* }}} */
3932
3933/* {{{ Returns the constant' name */
3935{
3937 RETURN_THROWS();
3938 }
3939
3940 zval *name = reflection_prop_name(ZEND_THIS);
3941 if (Z_ISUNDEF_P(name)) {
3943 "Typed property ReflectionClassConstant::$name "
3944 "must not be accessed before initialization");
3945 RETURN_THROWS();
3946 }
3947
3949}
3950/* }}} */
3951
3952/* Returns the type associated with the class constant */
3954{
3955 reflection_object *intern;
3957
3959 RETURN_THROWS();
3960 }
3961
3963
3964 if (!ZEND_TYPE_IS_SET(ref->type)) {
3965 RETURN_NULL();
3966 }
3967
3968 reflection_type_factory(ref->type, return_value, 1);
3969}
3970
3971/* Returns whether class constant has a type */
3973{
3974 reflection_object *intern;
3976
3978 RETURN_THROWS();
3979 }
3980
3983}
3984
3985static void _class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
3986{
3987 reflection_object *intern;
3989
3991 RETURN_THROWS();
3992 }
3995}
3996/* }}} */
3997
3998/* {{{ Returns whether this constant is public */
4000{
4001 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
4002}
4003/* }}} */
4004
4005/* {{{ Returns whether this constant is private */
4007{
4008 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
4009}
4010/* }}} */
4011
4012/* {{{ Returns whether this constant is protected */
4014{
4015 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
4016}
4017/* }}} */
4018
4019/* Returns whether this constant is final */
4021{
4022 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
4023}
4024
4025/* {{{ Returns a bitfield of the access modifiers for this constant */
4027{
4028 reflection_object *intern;
4030 uint32_t keep_flags = ZEND_ACC_FINAL | ZEND_ACC_PPP_MASK;
4031
4033 RETURN_THROWS();
4034 }
4036
4037 RETURN_LONG(ZEND_CLASS_CONST_FLAGS(ref) & keep_flags);
4038}
4039/* }}} */
4040
4041/* {{{ Returns this constant's value */
4043{
4044 reflection_object *intern;
4046
4048 RETURN_THROWS();
4049 }
4051
4052 zval *name = reflection_prop_name(ZEND_THIS);
4053 if (Z_ISUNDEF_P(name)) {
4055 "Typed property ReflectionClassConstant::$name "
4056 "must not be accessed before initialization");
4057 RETURN_THROWS();
4058 }
4059
4060 if (Z_TYPE(ref->value) == IS_CONSTANT_AST) {
4062 if (result == FAILURE) {
4063 RETURN_THROWS();
4064 }
4065 }
4067}
4068/* }}} */
4069
4070/* {{{ Get the declaring class */
4072{
4073 reflection_object *intern;
4075
4077 RETURN_THROWS();
4078 }
4080
4082}
4083/* }}} */
4084
4085/* {{{ Returns the doc comment for this constant */
4087{
4088 reflection_object *intern;
4090
4092 RETURN_THROWS();
4093 }
4095 if (ref->doc_comment) {
4097 }
4099}
4100/* }}} */
4101
4102/* {{{ Returns the attributes of this constant */
4104{
4105 reflection_object *intern;
4107
4109
4110 reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU,
4112 ref->ce->type == ZEND_USER_CLASS ? ref->ce->info.user.filename : NULL);
4113}
4114/* }}} */
4115
4125
4127{
4128 reflection_object *intern;
4129 zend_constant *ref;
4130
4132 RETURN_THROWS();
4133 }
4134
4136
4138}
4139
4140/* {{{ reflection_class_object_ctor */
4141static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
4142{
4143 zval *object;
4144 zend_string *arg_class = NULL;
4145 zend_object *arg_obj;
4146 reflection_object *intern;
4147 zend_class_entry *ce;
4148
4149 if (is_object) {
4151 Z_PARAM_OBJ(arg_obj)
4153 } else {
4155 Z_PARAM_OBJ_OR_STR(arg_obj, arg_class)
4157 }
4158
4159 object = ZEND_THIS;
4160 intern = Z_REFLECTION_P(object);
4161
4162 /* Note: class entry name is interned, no need to destroy them */
4163 if (arg_obj) {
4164 ZVAL_STR_COPY(reflection_prop_name(object), arg_obj->ce->name);
4165 intern->ptr = arg_obj->ce;
4166 if (is_object) {
4167 zval_ptr_dtor(&intern->obj);
4168 ZVAL_OBJ_COPY(&intern->obj, arg_obj);
4169 }
4170 } else {
4171 if ((ce = zend_lookup_class(arg_class)) == NULL) {
4172 if (!EG(exception)) {
4173 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class \"%s\" does not exist", ZSTR_VAL(arg_class));
4174 }
4175 RETURN_THROWS();
4176 }
4177
4178 ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
4179 intern->ptr = ce;
4180 }
4181 intern->ref_type = REF_TYPE_OTHER;
4182}
4183/* }}} */
4184
4185/* {{{ Constructor. Takes a string or an instance as an argument */
4187{
4188 reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
4189}
4190/* }}} */
4191
4192/* {{{ add_class_vars */
4193static void add_class_vars(zend_class_entry *ce, bool statics, zval *return_value)
4194{
4196 zval *prop, prop_copy;
4198
4200 if (((prop_info->flags & ZEND_ACC_PRIVATE) &&
4201 prop_info->ce != ce)) {
4202 continue;
4203 }
4204
4205 bool is_static = (prop_info->flags & ZEND_ACC_STATIC) != 0;
4206 if (statics != is_static) {
4207 continue;
4208 }
4209
4210 prop = property_get_default(prop_info);
4211 if (!prop || Z_ISUNDEF_P(prop)) {
4212 continue;
4213 }
4214
4215 /* copy: enforce read only access */
4216 ZVAL_DEREF(prop);
4217 ZVAL_COPY_OR_DUP(&prop_copy, prop);
4218
4219 /* this is necessary to make it able to work with default array
4220 * properties, returned to user */
4221 if (Z_TYPE(prop_copy) == IS_CONSTANT_AST) {
4222 if (UNEXPECTED(zval_update_constant_ex(&prop_copy, ce) != SUCCESS)) {
4223 return;
4224 }
4225 }
4226
4229}
4230/* }}} */
4231
4232/* {{{ Returns an associative array containing all static property values of the class */
4233ZEND_METHOD(ReflectionClass, getStaticProperties)
4234{
4235 reflection_object *intern;
4236 zend_class_entry *ce;
4238 zval *prop;
4240
4242 RETURN_THROWS();
4243 }
4244
4246
4248 RETURN_THROWS();
4249 }
4250
4253 }
4254
4256
4258 if (((prop_info->flags & ZEND_ACC_PRIVATE) &&
4259 prop_info->ce != ce)) {
4260 continue;
4261 }
4262 if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
4263 continue;
4264 }
4265
4266 prop = &CE_STATIC_MEMBERS(ce)[prop_info->offset];
4267 ZVAL_DEINDIRECT(prop);
4268
4269 if (ZEND_TYPE_IS_SET(prop_info->type) && Z_ISUNDEF_P(prop)) {
4270 continue;
4271 }
4272
4273 /* enforce read only access */
4274 ZVAL_DEREF(prop);
4275 Z_TRY_ADDREF_P(prop);
4276
4279}
4280/* }}} */
4281
4282/* {{{ Returns the value of a static property */
4283ZEND_METHOD(ReflectionClass, getStaticPropertyValue)
4284{
4285 reflection_object *intern;
4286 zend_class_entry *ce, *old_scope;
4288 zval *prop, *def_value = NULL;
4289
4290 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &name, &def_value) == FAILURE) {
4291 RETURN_THROWS();
4292 }
4293
4295
4297 RETURN_THROWS();
4298 }
4299
4300 old_scope = EG(fake_scope);
4301 EG(fake_scope) = ce;
4303 EG(fake_scope) = old_scope;
4304
4305 if (prop) {
4306 RETURN_COPY_DEREF(prop);
4307 }
4308
4309 if (def_value) {
4310 RETURN_COPY(def_value);
4311 }
4312
4314 "Property %s::$%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4315}
4316/* }}} */
4317
4318/* {{{ Sets the value of a static property */
4319ZEND_METHOD(ReflectionClass, setStaticPropertyValue)
4320{
4321 reflection_object *intern;
4322 zend_class_entry *ce, *old_scope;
4326
4328 RETURN_THROWS();
4329 }
4330
4332
4334 RETURN_THROWS();
4335 }
4336 old_scope = EG(fake_scope);
4337 EG(fake_scope) = ce;
4339 EG(fake_scope) = old_scope;
4340 if (!variable_ptr) {
4343 "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4344 RETURN_THROWS();
4345 }
4346
4347 if (Z_ISREF_P(variable_ptr)) {
4350
4351 if (!zend_verify_ref_assignable_zval(ref, value, 0)) {
4352 return;
4353 }
4354 }
4355
4357 return;
4358 }
4359
4362
4363}
4364/* }}} */
4365
4366/* {{{ Returns an associative array containing copies of all default property values of the class */
4367ZEND_METHOD(ReflectionClass, getDefaultProperties)
4368{
4369 reflection_object *intern;
4370 zend_class_entry *ce;
4371
4373 RETURN_THROWS();
4374 }
4378 RETURN_THROWS();
4379 }
4380 add_class_vars(ce, 1, return_value);
4381 add_class_vars(ce, 0, return_value);
4382}
4383/* }}} */
4384
4385/* {{{ Returns a string representation */
4387{
4388 reflection_object *intern;
4389 zend_class_entry *ce;
4390 smart_str str = {0};
4391
4393 RETURN_THROWS();
4394 }
4396 _class_string(&str, ce, &intern->obj, "");
4397 RETURN_STR(smart_str_extract(&str));
4398}
4399/* }}} */
4400
4401/* {{{ Returns the class' name */
4403{
4404 reflection_object *intern;
4405 zend_class_entry *ce;
4406
4408 RETURN_THROWS();
4409 }
4410
4412 RETURN_STR_COPY(ce->name);
4413}
4414/* }}} */
4415
4416/* {{{ Returns whether this class is an internal class */
4418{
4419 reflection_object *intern;
4420 zend_class_entry *ce;
4421
4423 RETURN_THROWS();
4424 }
4427}
4428/* }}} */
4429
4430/* {{{ Returns whether this class is user-defined */
4432{
4433 reflection_object *intern;
4434 zend_class_entry *ce;
4435
4437 RETURN_THROWS();
4438 }
4441}
4442/* }}} */
4443
4444/* {{{ Returns whether this class is anonymous */
4446{
4447 reflection_object *intern;
4448 zend_class_entry *ce;
4449
4451 RETURN_THROWS();
4452 }
4455}
4456/* }}} */
4457
4458/* {{{ Returns the filename of the file this class was declared in */
4460{
4461 reflection_object *intern;
4462 zend_class_entry *ce;
4463
4465 RETURN_THROWS();
4466 }
4468 if (ce->type == ZEND_USER_CLASS) {
4470 }
4472}
4473/* }}} */
4474
4475/* {{{ Returns the line this class' declaration starts at */
4477{
4478 reflection_object *intern;
4479 zend_class_entry *ce;
4480
4482 RETURN_THROWS();
4483 }
4485 if (ce->type == ZEND_USER_CLASS) {
4487 }
4489}
4490/* }}} */
4491
4492/* {{{ Returns the line this class' declaration ends at */
4494{
4495 reflection_object *intern;
4496 zend_class_entry *ce;
4497
4499 RETURN_THROWS();
4500 }
4502 if (ce->type == ZEND_USER_CLASS) {
4504 }
4506}
4507/* }}} */
4508
4509/* {{{ Returns the doc comment for this class */
4511{
4512 reflection_object *intern;
4513 zend_class_entry *ce;
4514
4516 RETURN_THROWS();
4517 }
4519 if (ce->doc_comment) {
4521 }
4523}
4524/* }}} */
4525
4526/* {{{ Returns the attributes for this class */
4528{
4529 reflection_object *intern;
4530 zend_class_entry *ce;
4531
4533
4534 reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU,
4536 ce->type == ZEND_USER_CLASS ? ce->info.user.filename : NULL);
4537}
4538/* }}} */
4539
4540/* {{{ Returns the class' constructor if there is one, NULL otherwise */
4542{
4543 reflection_object *intern;
4544 zend_class_entry *ce;
4545
4547 RETURN_THROWS();
4548 }
4550
4551 if (ce->constructor) {
4552 reflection_method_factory(ce, ce->constructor, NULL, return_value);
4553 } else {
4554 RETURN_NULL();
4555 }
4556}
4557/* }}} */
4558
4559/* {{{ Returns whether a method exists or not */
4561{
4562 reflection_object *intern;
4563 zend_class_entry *ce;
4564 zend_string *name, *lc_name;
4565
4567 RETURN_THROWS();
4568 }
4569
4571 lc_name = zend_string_tolower(name);
4572 RETVAL_BOOL(zend_hash_exists(&ce->function_table, lc_name) || is_closure_invoke(ce, lc_name));
4573 zend_string_release(lc_name);
4574}
4575/* }}} */
4576
4577/* {{{ Returns the class' method specified by its name */
4579{
4580 reflection_object *intern;
4581 zend_class_entry *ce;
4582 zend_function *mptr;
4583 zval obj_tmp;
4584 zend_string *name, *lc_name;
4585
4587 RETURN_THROWS();
4588 }
4589
4591 lc_name = zend_string_tolower(name);
4592 if (!Z_ISUNDEF(intern->obj) && is_closure_invoke(ce, lc_name)
4593 && (mptr = zend_get_closure_invoke_method(Z_OBJ(intern->obj))) != NULL)
4594 {
4595 /* don't assign closure_object since we only reflect the invoke handler
4596 method and not the closure definition itself */
4597 reflection_method_factory(ce, mptr, NULL, return_value);
4598 } else if (Z_ISUNDEF(intern->obj) && is_closure_invoke(ce, lc_name)
4599 && object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(Z_OBJ(obj_tmp))) != NULL) {
4600 /* don't assign closure_object since we only reflect the invoke handler
4601 method and not the closure definition itself */
4602 reflection_method_factory(ce, mptr, NULL, return_value);
4603 zval_ptr_dtor(&obj_tmp);
4604 } else if ((mptr = zend_hash_find_ptr(&ce->function_table, lc_name)) != NULL) {
4605 reflection_method_factory(ce, mptr, NULL, return_value);
4606 } else {
4608 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4609 }
4610 zend_string_release(lc_name);
4611}
4612/* }}} */
4613
4614/* {{{ _addmethod */
4615static bool _addmethod(zend_function *mptr, zend_class_entry *ce, HashTable *ht, zend_long filter)
4616{
4617 if ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && mptr->common.scope != ce) {
4618 return 0;
4619 }
4620
4621 if (mptr->common.fn_flags & filter) {
4622 zval method;
4623 reflection_method_factory(ce, mptr, NULL, &method);
4625 return 1;
4626 }
4627 return 0;
4628}
4629/* }}} */
4630
4631/* {{{ Returns an array of this class' methods */
4633{
4634 reflection_object *intern;
4635 zend_class_entry *ce;
4636 zend_function *mptr;
4637 zend_long filter;
4638 bool filter_is_null = 1;
4639
4640 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4641 RETURN_THROWS();
4642 }
4643
4644 if (filter_is_null) {
4646 }
4647
4649
4652 _addmethod(mptr, ce, Z_ARRVAL_P(return_value), filter);
4654
4655 if (instanceof_function(ce, zend_ce_closure)) {
4656 bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
4657 zval obj_tmp;
4658 zend_object *obj;
4659 if (!has_obj) {
4660 object_init_ex(&obj_tmp, ce);
4661 obj = Z_OBJ(obj_tmp);
4662 } else {
4663 obj = Z_OBJ(intern->obj);
4664 }
4666 if (closure) {
4667 if (!_addmethod(closure, ce, Z_ARRVAL_P(return_value), filter)) {
4668 _free_function(closure);
4669 }
4670 }
4671 if (!has_obj) {
4672 zval_ptr_dtor(&obj_tmp);
4673 }
4674 }
4675}
4676/* }}} */
4677
4678/* {{{ Returns whether a property exists or not */
4680{
4681 reflection_object *intern;
4682 zend_property_info *property_info;
4683 zend_class_entry *ce;
4685
4687 RETURN_THROWS();
4688 }
4689
4691 if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4692 if ((property_info->flags & ZEND_ACC_PRIVATE) && property_info->ce != ce) {
4694 }
4696 } else {
4697 if (Z_TYPE(intern->obj) != IS_UNDEF) {
4698 if (Z_OBJ_HANDLER(intern->obj, has_property)(Z_OBJ(intern->obj), name, 2, NULL)) {
4700 }
4701 }
4703 }
4704}
4705/* }}} */
4706
4707/* {{{ Returns the class' property specified by its name */
4709{
4710 reflection_object *intern;
4711 zend_class_entry *ce, *ce2;
4712 zend_property_info *property_info;
4713 zend_string *name, *classname;
4714 char *tmp, *str_name;
4715 size_t classname_len, str_name_len;
4716
4718 RETURN_THROWS();
4719 }
4720
4722 if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4723 if (!(property_info->flags & ZEND_ACC_PRIVATE) || property_info->ce == ce) {
4724 reflection_property_factory(ce, name, property_info, return_value);
4725 return;
4726 }
4727 } else if (Z_TYPE(intern->obj) != IS_UNDEF) {
4728 /* Check for dynamic properties */
4729 if (zend_hash_exists(Z_OBJ_HT(intern->obj)->get_properties(Z_OBJ(intern->obj)), name)) {
4730 reflection_property_factory(ce, name, NULL, return_value);
4731 return;
4732 }
4733 }
4734 str_name = ZSTR_VAL(name);
4735 if ((tmp = strstr(ZSTR_VAL(name), "::")) != NULL) {
4736 classname_len = tmp - ZSTR_VAL(name);
4737 classname = zend_string_alloc(classname_len, 0);
4738 zend_str_tolower_copy(ZSTR_VAL(classname), ZSTR_VAL(name), classname_len);
4739 ZSTR_VAL(classname)[classname_len] = '\0';
4740 str_name_len = ZSTR_LEN(name) - (classname_len + 2);
4741 str_name = tmp + 2;
4742
4743 ce2 = zend_lookup_class(classname);
4744 if (!ce2) {
4745 if (!EG(exception)) {
4746 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class \"%s\" does not exist", ZSTR_VAL(classname));
4747 }
4748 zend_string_release_ex(classname, 0);
4749 RETURN_THROWS();
4750 }
4751 zend_string_release_ex(classname, 0);
4752
4753 if (!instanceof_function(ce, ce2)) {
4754 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));
4755 RETURN_THROWS();
4756 }
4757 ce = ce2;
4758
4759 property_info = zend_hash_str_find_ptr(&ce->properties_info, str_name, str_name_len);
4760 if (property_info != NULL
4761 && (!(property_info->flags & ZEND_ACC_PRIVATE)
4762 || property_info->ce == ce)) {
4763 reflection_property_factory_str(ce, str_name, str_name_len, property_info, return_value);
4764 return;
4765 }
4766 }
4767 zend_throw_exception_ex(reflection_exception_ptr, 0, "Property %s::$%s does not exist", ZSTR_VAL(ce->name), str_name);
4768}
4769/* }}} */
4770
4771/* {{{ _addproperty */
4772static void _addproperty(zend_property_info *pptr, zend_string *key, zend_class_entry *ce, HashTable *ht, long filter)
4773{
4774 if ((pptr->flags & ZEND_ACC_PRIVATE) && pptr->ce != ce) {
4775 return;
4776 }
4777
4778 if (pptr->flags & filter) {
4779 zval property;
4780 reflection_property_factory(ce, key, pptr, &property);
4782 }
4783}
4784/* }}} */
4785
4786/* {{{ _adddynproperty */
4787static void _adddynproperty(zval *ptr, zend_string *key, zend_class_entry *ce, zval *retval)
4788{
4789 zval property;
4790
4791 /* under some circumstances, the properties hash table may contain numeric
4792 * properties (e.g. when casting from array). This is a WON'T FIX bug, at
4793 * least for the moment. Ignore these */
4794 if (key == NULL) {
4795 return;
4796 }
4797
4798 /* Not a dynamic property */
4799 if (Z_TYPE_P(ptr) == IS_INDIRECT) {
4800 return;
4801 }
4802
4803 reflection_property_factory(ce, key, NULL, &property);
4804 add_next_index_zval(retval, &property);
4805}
4806/* }}} */
4807
4808/* {{{ Returns an array of this class' properties */
4810{
4811 reflection_object *intern;
4812 zend_class_entry *ce;
4815 zend_long filter;
4816 bool filter_is_null = 1;
4817
4818 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4819 RETURN_THROWS();
4820 }
4821
4822 if (filter_is_null) {
4824 }
4825
4827
4830 _addproperty(prop_info, key, ce, Z_ARRVAL_P(return_value), filter);
4832
4833 if (Z_TYPE(intern->obj) != IS_UNDEF && (filter & ZEND_ACC_PUBLIC) != 0) {
4834 HashTable *properties = Z_OBJ_HT(intern->obj)->get_properties(Z_OBJ(intern->obj));
4835 zval *prop;
4836 ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
4837 _adddynproperty(prop, key, ce, return_value);
4839 }
4840}
4841/* }}} */
4842
4843/* {{{ Returns whether a constant exists or not */
4845{
4846 reflection_object *intern;
4847 zend_class_entry *ce;
4849
4851 RETURN_THROWS();
4852 }
4853
4855 if (zend_hash_exists(&ce->constants_table, name)) {
4857 } else {
4859 }
4860}
4861/* }}} */
4862
4863/* {{{ Returns an associative array containing this class' constants and their values */
4865{
4866 reflection_object *intern;
4867 zend_class_entry *ce;
4870 zval val;
4871 zend_long filter;
4872 bool filter_is_null = 1;
4873
4874 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4875 RETURN_THROWS();
4876 }
4877
4878 if (filter_is_null) {
4879 filter = ZEND_ACC_PPP_MASK;
4880 }
4881
4883
4887 RETURN_THROWS();
4888 }
4889
4890 if (ZEND_CLASS_CONST_FLAGS(constant) & filter) {
4891 ZVAL_COPY_OR_DUP(&val, &constant->value);
4893 }
4895}
4896/* }}} */
4897
4898/* {{{ Returns an associative array containing this class' constants as ReflectionClassConstant objects */
4899ZEND_METHOD(ReflectionClass, getReflectionConstants)
4900{
4901 reflection_object *intern;
4902 zend_class_entry *ce;
4905 zend_long filter;
4906 bool filter_is_null = 1;
4907
4908 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4909 RETURN_THROWS();
4910 }
4911
4912 if (filter_is_null) {
4913 filter = ZEND_ACC_PPP_MASK;
4914 }
4915
4917
4920 if (ZEND_CLASS_CONST_FLAGS(constant) & filter) {
4921 zval class_const;
4922 reflection_class_constant_factory(name, constant, &class_const);
4924 }
4926}
4927/* }}} */
4928
4929/* {{{ Returns the class' constant specified by its name */
4931{
4932 reflection_object *intern;
4933 zend_class_entry *ce;
4934 HashTable *constants_table;
4936 zend_string *name, *key;
4937
4939 RETURN_THROWS();
4940 }
4941
4943 constants_table = CE_CONSTANTS_TABLE(ce);
4944 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(constants_table, key, c) {
4946 RETURN_THROWS();
4947 }
4949 if ((c = zend_hash_find_ptr(constants_table, name)) == NULL) {
4951 }
4953}
4954/* }}} */
4955
4956/* {{{ Returns the class' constant as ReflectionClassConstant objects */
4957ZEND_METHOD(ReflectionClass, getReflectionConstant)
4958{
4959 reflection_object *intern;
4960 zend_class_entry *ce;
4963
4966 RETURN_THROWS();
4967 }
4968
4969 if ((constant = zend_hash_find_ptr(CE_CONSTANTS_TABLE(ce), name)) == NULL) {
4971 }
4972 reflection_class_constant_factory(name, constant, return_value);
4973}
4974/* }}} */
4975
4976/* {{{ _class_check_flag */
4977static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
4978{
4979 reflection_object *intern;
4980 zend_class_entry *ce;
4981
4983 RETURN_THROWS();
4984 }
4986 RETVAL_BOOL(ce->ce_flags & mask);
4987}
4988/* }}} */
4989
4990/* {{{ Returns whether this class is instantiable */
4992{
4993 reflection_object *intern;
4994 zend_class_entry *ce;
4995
4997 RETURN_THROWS();
4998 }
5002 }
5003
5004 /* Basically, the class is instantiable. Though, if there is a constructor
5005 * and it is not publicly accessible, it isn't! */
5006 if (!ce->constructor) {
5008 }
5009
5011}
5012/* }}} */
5013
5014/* {{{ Returns whether this class is cloneable */
5016{
5017 reflection_object *intern;
5018 zend_class_entry *ce;
5019 zval obj;
5020
5022 RETURN_THROWS();
5023 }
5027 }
5028 if (!Z_ISUNDEF(intern->obj)) {
5029 if (ce->clone) {
5031 } else {
5033 }
5034 } else {
5035 if (ce->clone) {
5037 } else {
5038 if (UNEXPECTED(object_init_ex(&obj, ce) != SUCCESS)) {
5039 return;
5040 }
5041 /* We're not calling the constructor, so don't call the destructor either. */
5042 zend_object_store_ctor_failed(Z_OBJ(obj));
5044 zval_ptr_dtor(&obj);
5045 }
5046 }
5047}
5048/* }}} */
5049
5050/* {{{ Returns whether this is an interface or a class */
5052{
5054}
5055/* }}} */
5056
5057/* {{{ Returns whether this is a trait */
5059{
5061}
5062/* }}} */
5063
5065{
5067}
5068
5069/* {{{ Returns whether this class is final */
5071{
5073}
5074/* }}} */
5075
5076/* Returns whether this class is readonly */
5081
5082/* {{{ Returns whether this class is abstract */
5087/* }}} */
5088
5089/* {{{ Returns a bitfield of the access modifiers for this class */
5091{
5092 reflection_object *intern;
5093 zend_class_entry *ce;
5095
5097 RETURN_THROWS();
5098 }
5100
5101 RETURN_LONG((ce->ce_flags & keep_flags));
5102}
5103/* }}} */
5104
5105/* {{{ Returns whether the given object is an instance of this class */
5107{
5108 reflection_object *intern;
5109 zend_class_entry *ce;
5110 zval *object;
5111
5112 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
5113 RETURN_THROWS();
5114 }
5116 RETURN_BOOL(instanceof_function(Z_OBJCE_P(object), ce));
5117}
5118/* }}} */
5119
5120/* {{{ Returns an instance of this class */
5122{
5123 reflection_object *intern;
5124 zend_class_entry *ce, *old_scope;
5125 zend_function *constructor;
5126
5128
5130 return;
5131 }
5132
5133 old_scope = EG(fake_scope);
5134 EG(fake_scope) = ce;
5135 constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
5136 EG(fake_scope) = old_scope;
5137
5138 /* Run the constructor if there is one */
5139 if (constructor) {
5140 zval *params;
5141 int num_args;
5142 HashTable *named_params;
5143
5144 if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
5145 zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
5147 RETURN_NULL();
5148 }
5149
5151 Z_PARAM_VARIADIC_WITH_NAMED(params, num_args, named_params)
5153
5156 num_args, params, named_params);
5157
5158 if (EG(exception)) {
5159 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
5160 }
5161 } else if (ZEND_NUM_ARGS()) {
5162 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));
5163 }
5164}
5165/* }}} */
5166
5167/* {{{ Returns an instance of this class without invoking its constructor */
5168ZEND_METHOD(ReflectionClass, newInstanceWithoutConstructor)
5169{
5170 reflection_object *intern;
5171 zend_class_entry *ce;
5172
5174
5176 RETURN_THROWS();
5177 }
5178
5179 if (ce->type == ZEND_INTERNAL_CLASS
5180 && ce->create_object != NULL && (ce->ce_flags & ZEND_ACC_FINAL)) {
5181 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));
5182 RETURN_THROWS();
5183 }
5184
5186}
5187/* }}} */
5188
5189/* {{{ Returns an instance of this class */
5191{
5192 reflection_object *intern;
5193 zend_class_entry *ce, *old_scope;
5194 int argc = 0;
5195 HashTable *args = NULL;
5196 zend_function *constructor;
5197
5199
5200 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|h", &args) == FAILURE) {
5201 RETURN_THROWS();
5202 }
5203
5204 if (args) {
5205 argc = zend_hash_num_elements(args);
5206 }
5207
5209 return;
5210 }
5211
5212 old_scope = EG(fake_scope);
5213 EG(fake_scope) = ce;
5214 constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
5215 EG(fake_scope) = old_scope;
5216
5217 /* Run the constructor if there is one */
5218 if (constructor) {
5219 if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
5220 zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
5222 RETURN_NULL();
5223 }
5224
5226 constructor, Z_OBJ_P(return_value), Z_OBJCE_P(return_value), NULL, 0, NULL, args);
5227
5228 if (EG(exception)) {
5229 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
5230 }
5231 } else if (argc) {
5232 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));
5233 }
5234}
5235/* }}} */
5236
5238 int strategy, bool is_reset)
5239{
5240 reflection_object *intern;
5241 zend_object *obj;
5242 zend_class_entry *ce;
5243 zend_fcall_info fci;
5245 zend_long options = 0;
5246
5248 || strategy == ZEND_LAZY_OBJECT_STRATEGY_PROXY);
5249
5251
5252 if (is_reset) {
5254 Z_PARAM_OBJ_OF_CLASS(obj, ce)
5255 Z_PARAM_FUNC(fci, fcc)
5259 } else {
5261 Z_PARAM_FUNC(fci, fcc)
5265 obj = NULL;
5266 }
5267
5269 uint32_t arg_num = 2 + is_reset;
5271 "contains invalid flags");
5272 RETURN_THROWS();
5273 }
5274
5275 if (!is_reset && (options & ZEND_LAZY_OBJECT_SKIP_DESTRUCTOR)) {
5277 "does not accept ReflectionClass::SKIP_DESTRUCTOR");
5278 RETURN_THROWS();
5279 }
5280
5281 if (is_reset) {
5282 if (zend_object_is_lazy(obj) && !zend_lazy_object_initialized(obj)) {
5283 zend_throw_exception_ex(reflection_exception_ptr, 0, "Object is already lazy");
5284 RETURN_THROWS();
5285 }
5286 } else {
5287 obj = NULL;
5288 }
5289
5290 if (!fcc.function_handler) {
5291 /* Call trampoline has been cleared by zpp. Refetch it, because we want to deal
5292 * with it ourselves. It is important that it is not refetched on every call,
5293 * because calls may occur from different scopes. */
5295 }
5296
5297 obj = zend_object_make_lazy(obj, ce, &fci.function_name, &fcc,
5298 strategy | options);
5299
5300 if (!obj) {
5301 RETURN_THROWS();
5302 }
5303
5304 if (!is_reset) {
5305 RETURN_OBJ(obj);
5306 }
5307}
5308
5309/* {{{ Instantiates a lazy instance, using the ghost strategy */
5315/* }}} */
5316
5317/* {{{ Instantiates a lazy instance, using the proxy strategy */
5323/* }}} */
5324
5325/* {{{ Reset an object and make it lazy, using the ghost strategy */
5331/* }}} */
5332
5333/* {{{ Reset an object and make it lazy, using the proxy strategy */
5339/* }}} */
5340
5341/* {{{ Returns whether object lazy and uninitialized */
5342ZEND_METHOD(ReflectionClass, isUninitializedLazyObject)
5343{
5344 reflection_object *intern;
5345 zend_class_entry *ce;
5347
5349
5351 Z_PARAM_OBJ_OF_CLASS(object, ce)
5353
5354 RETURN_BOOL(zend_object_is_lazy(object) && !zend_lazy_object_initialized(object));
5355}
5356/* }}} */
5357
5358/* {{{ Trigger object initialization */
5359ZEND_METHOD(ReflectionClass, initializeLazyObject)
5360{
5361 reflection_object *intern;
5362 zend_class_entry *ce;
5364
5366
5368 Z_PARAM_OBJ_OF_CLASS(object, ce)
5370
5371 if (zend_object_is_lazy(object)
5372 && !zend_lazy_object_initialized(object)) {
5373 zend_lazy_object_init(object);
5374 }
5375
5376 if (zend_lazy_object_initialized(object)) {
5378 } else {
5379 RETURN_THROWS();
5380 }
5381}
5382/* }}} */
5383
5384/* {{{ Mark object as initialized without calling the initializer */
5385ZEND_METHOD(ReflectionClass, markLazyObjectAsInitialized)
5386{
5387 reflection_object *intern;
5388 zend_class_entry *ce;
5390
5392
5394 Z_PARAM_OBJ_OF_CLASS(object, ce)
5396
5397 if (zend_object_is_lazy(object)
5398 && !zend_lazy_object_initialized(object)) {
5400 }
5401
5402 if (zend_lazy_object_initialized(object)) {
5404 } else {
5405 RETURN_THROWS();
5406 }
5407}
5408/* }}} */
5409
5410/* {{{ Get lazy object initializer */
5411ZEND_METHOD(ReflectionClass, getLazyInitializer)
5412{
5413 reflection_object *intern;
5414 zend_class_entry *ce;
5416
5418
5420 Z_PARAM_OBJ_OF_CLASS(object, ce)
5422
5423 if (!zend_object_is_lazy(object)
5424 || zend_lazy_object_initialized(object)) {
5425 RETURN_NULL();
5426 }
5427
5429}
5430/* }}} */
5431
5432/* {{{ Returns an array of interfaces this class implements */
5434{
5435 reflection_object *intern;
5436 zend_class_entry *ce;
5437
5439 RETURN_THROWS();
5440 }
5442
5443 if (ce->num_interfaces) {
5444 uint32_t i;
5445
5448 for (i=0; i < ce->num_interfaces; i++) {
5449 zval interface;
5450 zend_reflection_class_factory(ce->interfaces[i], &interface);
5452 }
5453 } else {
5455 }
5456}
5457/* }}} */
5458
5459/* {{{ Returns an array of names of interfaces this class implements */
5460ZEND_METHOD(ReflectionClass, getInterfaceNames)
5461{
5462 reflection_object *intern;
5463 zend_class_entry *ce;
5464 uint32_t i;
5465
5467 RETURN_THROWS();
5468 }
5470
5471 if (!ce->num_interfaces) {
5472 /* Return an empty array if this class implements no interfaces */
5474 }
5475
5478
5479 for (i=0; i < ce->num_interfaces; i++) {
5480 add_next_index_str(return_value, zend_string_copy(ce->interfaces[i]->name));
5481 }
5482}
5483/* }}} */
5484
5485/* {{{ Returns an array of traits used by this class */
5487{
5488 reflection_object *intern;
5489 zend_class_entry *ce;
5490 uint32_t i;
5491
5493 RETURN_THROWS();
5494 }
5496
5497 if (!ce->num_traits) {
5499 }
5500
5502
5503 for (i=0; i < ce->num_traits; i++) {
5504 zval trait;
5505 zend_class_entry *trait_ce;
5506
5507 trait_ce = zend_fetch_class_by_name(ce->trait_names[i].name,
5509 ZEND_ASSERT(trait_ce);
5510 zend_reflection_class_factory(trait_ce, &trait);
5512 }
5513}
5514/* }}} */
5515
5516/* {{{ Returns an array of names of traits used by this class */
5518{
5519 reflection_object *intern;
5520 zend_class_entry *ce;
5521 uint32_t i;
5522
5524 RETURN_THROWS();
5525 }
5527
5528 if (!ce->num_traits) {
5530 }
5531
5533
5534 for (i=0; i < ce->num_traits; i++) {
5535 add_next_index_str(return_value, zend_string_copy(ce->trait_names[i].name));
5536 }
5537}
5538/* }}} */
5539
5540/* {{{ Returns an array of trait aliases */
5542{
5543 reflection_object *intern;
5544 zend_class_entry *ce;
5545
5547 RETURN_THROWS();
5548 }
5550
5551
5552 if (ce->trait_aliases) {
5553 uint32_t i = 0;
5554
5556 while (ce->trait_aliases[i]) {
5557 zend_string *mname;
5559
5560 if (ce->trait_aliases[i]->alias) {
5561 zend_string *class_name = cur_ref->class_name;
5562
5563 if (!class_name) {
5564 uint32_t j = 0;
5565 zend_string *lcname = zend_string_tolower(cur_ref->method_name);
5566
5567 for (j = 0; j < ce->num_traits; j++) {
5568 zend_class_entry *trait =
5569 zend_hash_find_ptr(CG(class_table), ce->trait_names[j].lc_name);
5570 ZEND_ASSERT(trait && "Trait must exist");
5571 if (zend_hash_exists(&trait->function_table, lcname)) {
5572 class_name = trait->name;
5573 break;
5574 }
5575 }
5577 ZEND_ASSERT(class_name != NULL);
5578 }
5579
5580 mname = zend_string_alloc(ZSTR_LEN(class_name) + ZSTR_LEN(cur_ref->method_name) + 2, 0);
5581 snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(class_name), ZSTR_VAL(cur_ref->method_name));
5583 }
5584 i++;
5585 }
5586 } else {
5588 }
5589}
5590/* }}} */
5591
5592/* {{{ Returns the class' parent class, or, if none exists, FALSE */
5594{
5595 reflection_object *intern;
5596 zend_class_entry *ce;
5597
5599 RETURN_THROWS();
5600 }
5602
5603 if (ce->parent) {
5605 } else {
5607 }
5608}
5609/* }}} */
5610
5611/* {{{ Returns whether this class is a subclass of another class */
5613{
5614 reflection_object *intern, *argument;
5615 zend_class_entry *ce, *class_ce;
5616 zend_string *class_str;
5617 zend_object *class_obj;
5618
5622
5623 if (class_obj) {
5624 argument = reflection_object_from_obj(class_obj);
5625 if (argument->ptr == NULL) {
5626 zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5627 RETURN_THROWS();
5628 }
5629
5630 class_ce = argument->ptr;
5631 } else {
5632 if ((class_ce = zend_lookup_class(class_str)) == NULL) {
5633 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class \"%s\" does not exist", ZSTR_VAL(class_str));
5634 RETURN_THROWS();
5635 }
5636 }
5637
5639
5640 RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce)));
5641}
5642/* }}} */
5643
5644/* {{{ Returns whether this class is a subclass of another class */
5645ZEND_METHOD(ReflectionClass, implementsInterface)
5646{
5647 reflection_object *intern, *argument;
5648 zend_string *interface_str;
5649 zend_class_entry *ce, *interface_ce;
5650 zend_object *interface_obj;
5651
5653 Z_PARAM_OBJ_OF_CLASS_OR_STR(interface_obj, reflection_class_ptr, interface_str)
5655
5656 if (interface_obj) {
5657 argument = reflection_object_from_obj(interface_obj);
5658 if (argument->ptr == NULL) {
5659 zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5660 RETURN_THROWS();
5661 }
5662
5663 interface_ce = argument->ptr;
5664 } else {
5665 if ((interface_ce = zend_lookup_class(interface_str)) == NULL) {
5666 zend_throw_exception_ex(reflection_exception_ptr, 0, "Interface \"%s\" does not exist", ZSTR_VAL(interface_str));
5667 RETURN_THROWS();
5668 }
5669 }
5670
5671 if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
5672 zend_throw_exception_ex(reflection_exception_ptr, 0, "%s is not an interface", ZSTR_VAL(interface_ce->name));
5673 RETURN_THROWS();
5674 }
5675
5677
5678 RETURN_BOOL(instanceof_function(ce, interface_ce));
5679}
5680/* }}} */
5681
5682/* {{{ Returns whether this class is iterable (can be used inside foreach) */
5684{
5685 reflection_object *intern;
5686 zend_class_entry *ce;
5687
5689 RETURN_THROWS();
5690 }
5691
5693
5697 }
5698
5699 RETURN_BOOL(ce->get_iterator || instanceof_function(ce, zend_ce_traversable));
5700}
5701/* }}} */
5702
5703/* {{{ Returns NULL or the extension the class belongs to */
5705{
5706 reflection_object *intern;
5707 zend_class_entry *ce;
5708
5710 RETURN_THROWS();
5711 }
5712
5714
5715 if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5716 reflection_extension_factory(return_value, ce->info.internal.module->name);
5717 }
5718}
5719/* }}} */
5720
5721/* {{{ Returns false or the name of the extension the class belongs to */
5723{
5724 reflection_object *intern;
5725 zend_class_entry *ce;
5726
5728 RETURN_THROWS();
5729 }
5730
5732
5733 if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5735 } else {
5737 }
5738}
5739/* }}} */
5740
5741/* {{{ Returns whether this class is defined in namespace */
5743{
5744 reflection_object *intern;
5745 zend_class_entry *ce;
5746
5748 RETURN_THROWS();
5749 }
5750
5752
5753 zend_string *name = ce->name;
5754 const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
5755 RETURN_BOOL(backslash);
5756}
5757/* }}} */
5758
5759/* {{{ Returns the name of namespace where this class is defined */
5761{
5762 reflection_object *intern;
5763 zend_class_entry *ce;
5764
5766 RETURN_THROWS();
5767 }
5768
5770
5771 zend_string *name = ce->name;
5772 const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
5773 if (backslash) {
5774 RETURN_STRINGL(ZSTR_VAL(name), backslash - ZSTR_VAL(name));
5775 }
5777}
5778/* }}} */
5779
5780/* {{{ Returns the short name of the class (without namespace part) */
5782{
5783 reflection_object *intern;
5784 zend_class_entry *ce;
5785
5787 RETURN_THROWS();
5788 }
5789
5791
5792 zend_string *name = ce->name;
5793 const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
5794 if (backslash) {
5795 RETURN_STRINGL(backslash + 1, ZSTR_LEN(name) - (backslash - ZSTR_VAL(name) + 1));
5796 }
5798}
5799/* }}} */
5800
5801/* {{{ Constructor. Takes an instance as an argument */
5803{
5804 reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
5805}
5806/* }}} */
5807
5808/* {{{ Constructor. Throws an Exception in case the given property does not exist */
5810{
5811 zend_string *classname_str;
5812 zend_object *classname_obj;
5814 int dynam_prop = 0;
5815 zval *object;
5816 reflection_object *intern;
5817 zend_class_entry *ce;
5818 zend_property_info *property_info = NULL;
5819 property_reference *reference;
5820
5822 Z_PARAM_OBJ_OR_STR(classname_obj, classname_str)
5825
5826 object = ZEND_THIS;
5827 intern = Z_REFLECTION_P(object);
5828
5829 if (classname_obj) {
5830 ce = classname_obj->ce;
5831 } else {
5832 if ((ce = zend_lookup_class(classname_str)) == NULL) {
5833 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class \"%s\" does not exist", ZSTR_VAL(classname_str));
5834 RETURN_THROWS();
5835 }
5836 }
5837
5838 property_info = zend_hash_find_ptr(&ce->properties_info, name);
5839 if (property_info == NULL
5840 || ((property_info->flags & ZEND_ACC_PRIVATE)
5841 && property_info->ce != ce)) {
5842 /* Check for dynamic properties */
5843 if (property_info == NULL && classname_obj) {
5844 if (zend_hash_exists(classname_obj->handlers->get_properties(classname_obj), name)) {
5845 dynam_prop = 1;
5846 }
5847 }
5848 if (dynam_prop == 0) {
5849 zend_throw_exception_ex(reflection_exception_ptr, 0, "Property %s::$%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
5850 RETURN_THROWS();
5851 }
5852 }
5853
5854 zval *prop_name = reflection_prop_name(object);
5855 zval_ptr_dtor(prop_name);
5856 ZVAL_STR_COPY(prop_name, name);
5857 /* Note: class name are always interned, no need to destroy them */
5858 if (dynam_prop == 0) {
5859 ZVAL_STR_COPY(reflection_prop_class(object), property_info->ce->name);
5860 } else {
5861 ZVAL_STR_COPY(reflection_prop_class(object), ce->name);
5862 }
5863
5864 if (intern->ptr) {
5865 reflection_free_property_reference(intern->ptr);
5866 }
5867
5868 reference = (property_reference*) emalloc(sizeof(property_reference));
5869 reference->prop = dynam_prop ? NULL : property_info;
5870 reference->unmangled_name = zend_string_copy(name);
5871 intern->ptr = reference;
5872 intern->ref_type = REF_TYPE_PROPERTY;
5873 intern->ce = ce;
5874}
5875/* }}} */
5876
5877/* {{{ Returns a string representation */
5879{
5880 reflection_object *intern;
5881 property_reference *ref;
5882 smart_str str = {0};
5883
5885 RETURN_THROWS();
5886 }
5888 _property_string(&str, ref->prop, ZSTR_VAL(ref->unmangled_name), "");
5889 RETURN_STR(smart_str_extract(&str));
5890}
5891/* }}} */
5892
5893/* {{{ Returns the class' name */
5895{
5896 reflection_object *intern;
5897 property_reference *ref;
5898
5900 RETURN_THROWS();
5901 }
5902
5905}
5906/* }}} */
5907
5908static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
5909{
5910 reflection_object *intern;
5911 property_reference *ref;
5912
5914 RETURN_THROWS();
5915 }
5917 RETURN_BOOL(prop_get_flags(ref) & mask);
5918}
5919/* }}} */
5920
5921/* {{{ Returns whether this property is public */
5923{
5925}
5926/* }}} */
5927
5928/* {{{ Returns whether this property is private */
5930{
5932}
5933/* }}} */
5934
5935/* {{{ Returns whether this property is protected */
5937{
5939}
5940/* }}} */
5941
5943{
5945}
5946
5948{
5950}
5951
5952/* {{{ Returns whether this property is static */
5954{
5956}
5957/* }}} */
5958
5960{
5962}
5963
5965{
5967}
5968
5970{
5972}
5973
5974static void _property_check_dynamic(INTERNAL_FUNCTION_PARAMETERS, bool dynamic_true)
5975{
5976 reflection_object *intern;
5977 property_reference *ref;
5978
5980 RETURN_THROWS();
5981 }
5983 bool is_dynamic = ref->prop == NULL;
5984 RETURN_BOOL(dynamic_true ? is_dynamic : !is_dynamic);
5985}
5986
5987/* {{{ Returns whether this property is default (declared at compilation time). */
5989{
5990 _property_check_dynamic(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
5991}
5992/* }}} */
5993
5994/* {{{ Returns whether this property is dynamic (not declared at compilation time). */
5996{
5997 _property_check_dynamic(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
5998}
5999/* }}} */
6000
6001/* {{{ Returns whether this property has been promoted from a constructor */
6003{
6005}
6006/* }}} */
6007
6008/* {{{ Returns a bitfield of the access modifiers for this property */
6010{
6011 reflection_object *intern;
6012 property_reference *ref;
6014
6016 RETURN_THROWS();
6017 }
6019
6020 RETURN_LONG(prop_get_flags(ref) & keep_flags);
6021}
6022/* }}} */
6023
6024/* {{{ Returns this property's value */
6026{
6027 reflection_object *intern;
6028 property_reference *ref;
6029 zval *object = NULL;
6030 zval *member_p = NULL;
6031
6032 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &object) == FAILURE) {
6033 RETURN_THROWS();
6034 }
6035
6037
6038 if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
6039 member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 0);
6040 if (member_p) {
6041 RETURN_COPY_DEREF(member_p);
6042 }
6043 } else {
6044 zval rv;
6045
6046 if (!object) {
6047 zend_argument_type_error(1, "must be provided for instance properties");
6048 RETURN_THROWS();
6049 }
6050
6051 /* TODO: Should this always use intern->ce? */
6052 if (!instanceof_function(Z_OBJCE_P(object), ref->prop ? ref->prop->ce : intern->ce)) {
6053 _DO_THROW("Given object is not an instance of the class this property was declared in");
6054 RETURN_THROWS();
6055 }
6056
6057 member_p = zend_read_property_ex(intern->ce, Z_OBJ_P(object), ref->unmangled_name, 0, &rv);
6058 if (member_p != &rv) {
6059 RETURN_COPY_DEREF(member_p);
6060 } else {
6061 if (Z_ISREF_P(member_p)) {
6062 zend_unwrap_reference(member_p);
6063 }
6064 RETURN_COPY_VALUE(member_p);
6065 }
6066 }
6067}
6068/* }}} */
6069
6070/* {{{ Sets this property's value */
6072{
6073 reflection_object *intern;
6074 property_reference *ref;
6075 zval *object;
6076 zval *value;
6077 zval *tmp;
6078
6080
6081 if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
6083 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &tmp, &value) == FAILURE) {
6084 RETURN_THROWS();
6085 }
6086
6087 if (Z_TYPE_P(tmp) != IS_NULL && Z_TYPE_P(tmp) != IS_OBJECT) {
6089 zend_error(E_DEPRECATED, "Calling %s() with a 1st argument which is not null or an object is deprecated", ZSTR_VAL(method_name));
6090 zend_string_release(method_name);
6091 if (UNEXPECTED(EG(exception))) {
6092 RETURN_THROWS();
6093 }
6094 }
6095 } else {
6097 zend_error(E_DEPRECATED, "Calling %s() with a single argument is deprecated", ZSTR_VAL(method_name));
6098 zend_string_release(method_name);
6099 if (UNEXPECTED(EG(exception))) {
6100 RETURN_THROWS();
6101 }
6102 }
6103
6105 } else {
6106 if (zend_parse_parameters(ZEND_NUM_ARGS(), "oz", &object, &value) == FAILURE) {
6107 RETURN_THROWS();
6108 }
6109
6110 zend_update_property_ex(intern->ce, Z_OBJ_P(object), ref->unmangled_name, value);
6111 }
6112}
6113/* }}} */
6114
6115/* Return the property info being used when accessing 'ref->prop' from scope
6116 * 'scope' on 'object'. The result may be different from 'ref->prop' when the
6117 * property is overridden on 'object' and was not private in 'scope'.
6118 * The effective prop may add hooks or change flags. */
6119static zend_property_info *reflection_property_get_effective_prop(
6121 zend_property_info *prop = ref->prop;
6122 if (scope != object->ce && !(prop && (prop->flags & ZEND_ACC_PRIVATE))) {
6123 prop = zend_hash_find_ptr(&object->ce->properties_info, ref->unmangled_name);
6124 }
6125 return prop;
6126}
6127
6129{
6130 reflection_object *intern;
6131 property_reference *ref;
6132 zval *object;
6133
6134 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
6135 RETURN_THROWS();
6136 }
6137
6139
6140 if (!instanceof_function(Z_OBJCE_P(object), intern->ce)) {
6141 _DO_THROW("Given object is not an instance of the class this property was declared in");
6142 RETURN_THROWS();
6143 }
6144
6145 zend_property_info *prop = reflection_property_get_effective_prop(ref,
6146 intern->ce, Z_OBJ_P(object));
6147
6148 if (UNEXPECTED(prop && (prop->flags & ZEND_ACC_STATIC))) {
6149 _DO_THROW("May not use getRawValue on static properties");
6150 RETURN_THROWS();
6151 }
6152
6153 if (!prop || !prop->hooks || !prop->hooks[ZEND_PROPERTY_HOOK_GET]) {
6154 zval rv;
6155 zval *member_p = zend_read_property_ex(intern->ce, Z_OBJ_P(object), ref->unmangled_name, 0, &rv);
6156
6157 if (member_p != &rv) {
6158 RETURN_COPY_DEREF(member_p);
6159 } else {
6160 if (Z_ISREF_P(member_p)) {
6161 zend_unwrap_reference(member_p);
6162 }
6163 RETURN_COPY_VALUE(member_p);
6164 }
6165 } else {
6167 zend_call_known_instance_method_with_0_params(func, Z_OBJ_P(object), return_value);
6168 }
6169}
6170
6171static void reflection_property_set_raw_value(zend_property_info *prop,
6172 zend_string *unmangled_name, reflection_object *intern,
6173 zend_object *object, zval *value)
6174{
6175 if (!prop || !prop->hooks || !prop->hooks[ZEND_PROPERTY_HOOK_SET]) {
6176 zend_update_property_ex(intern->ce, object, unmangled_name, value);
6177 } else {
6179 zend_call_known_instance_method_with_1_params(func, object, NULL, value);
6180 }
6181}
6182
6184{
6185 reflection_object *intern;
6186 property_reference *ref;
6187 zval *object;
6188 zval *value;
6189
6191
6192 if (zend_parse_parameters(ZEND_NUM_ARGS(), "oz", &object, &value) == FAILURE) {
6193 RETURN_THROWS();
6194 }
6195
6196 zend_property_info *prop = reflection_property_get_effective_prop(ref,
6197 intern->ce, Z_OBJ_P(object));
6198
6199 if (UNEXPECTED(prop && (prop->flags & ZEND_ACC_STATIC))) {
6200 _DO_THROW("May not use setRawValue on static properties");
6201 RETURN_THROWS();
6202 }
6203
6204 reflection_property_set_raw_value(prop, ref->unmangled_name, intern, Z_OBJ_P(object), value);
6205}
6206
6207static zend_result reflection_property_check_lazy_compatible(
6208 zend_property_info *prop, zend_string *unmangled_name,
6209 reflection_object *intern, zend_object *object, const char *method)
6210{
6211 if (!prop) {
6213 "Can not use %s on dynamic property %s::$%s",
6214 method, ZSTR_VAL(intern->ce->name),
6215 ZSTR_VAL(unmangled_name));
6216 return FAILURE;
6217 }
6218
6219 if (prop->flags & ZEND_ACC_STATIC) {
6221 "Can not use %s on static property %s::$%s",
6222 method, ZSTR_VAL(prop->ce->name),
6223 ZSTR_VAL(unmangled_name));
6224 return FAILURE;
6225 }
6226
6227 if (prop->flags & ZEND_ACC_VIRTUAL) {
6229 "Can not use %s on virtual property %s::$%s",
6230 method, ZSTR_VAL(prop->ce->name),
6231 ZSTR_VAL(unmangled_name));
6232 return FAILURE;
6233 }
6234
6235 if (UNEXPECTED(object->handlers->write_property != zend_std_write_property)) {
6236 if (!zend_class_can_be_lazy(object->ce)) {
6238 "Can not use %s on internal class %s",
6239 method, ZSTR_VAL(object->ce->name));
6240 return FAILURE;
6241 }
6242 }
6243
6245
6246 return SUCCESS;
6247}
6248
6249/* {{{ Set property value withtout triggering initializer while skipping hooks if any */
6250ZEND_METHOD(ReflectionProperty, setRawValueWithoutLazyInitialization)
6251{
6252 reflection_object *intern;
6253 property_reference *ref;
6255 zval *value;
6256
6258
6260 Z_PARAM_OBJ_OF_CLASS(object, intern->ce)
6263
6264 while (zend_object_is_lazy_proxy(object)
6265 && zend_lazy_object_initialized(object)) {
6266 object = zend_lazy_object_get_instance(object);
6267 }
6268
6269 zend_property_info *prop = reflection_property_get_effective_prop(ref,
6270 intern->ce, object);
6271
6272 if (reflection_property_check_lazy_compatible(prop, ref->unmangled_name,
6273 intern, object, "setRawValueWithoutLazyInitialization") == FAILURE) {
6274 RETURN_THROWS();
6275 }
6276
6277 zval *var_ptr = OBJ_PROP(object, prop->offset);
6278 bool prop_was_lazy = Z_PROP_FLAG_P(var_ptr) & IS_PROP_LAZY;
6279
6280 /* Do not trigger initialization */
6282
6283 reflection_property_set_raw_value(prop, ref->unmangled_name, intern, object,
6284 value);
6285
6286 /* Mark property as lazy again if an exception prevented update */
6287 if (EG(exception) && prop_was_lazy && Z_TYPE_P(var_ptr) == IS_UNDEF
6288 && zend_object_is_lazy(object)
6289 && !zend_lazy_object_initialized(object)) {
6291 }
6292
6293 /* Object becomes non-lazy if this was the last lazy prop */
6294 if (prop_was_lazy && !(Z_PROP_FLAG_P(var_ptr) & IS_PROP_LAZY)
6295 && zend_object_is_lazy(object)
6296 && !zend_lazy_object_initialized(object)) {
6299 }
6300 }
6301}
6302
6303/* {{{ Mark property as non-lazy, and initialize to default value */
6304ZEND_METHOD(ReflectionProperty, skipLazyInitialization)
6305{
6306 reflection_object *intern;
6307 property_reference *ref;
6309
6311
6313 Z_PARAM_OBJ_OF_CLASS(object, intern->ce)
6315
6316 if (reflection_property_check_lazy_compatible(ref->prop,
6317 ref->unmangled_name, intern, object,
6318 "skipLazyInitialization") == FAILURE) {
6319 RETURN_THROWS();
6320 }
6321
6322 while (zend_object_is_lazy_proxy(object)
6323 && zend_lazy_object_initialized(object)) {
6324 object = zend_lazy_object_get_instance(object);
6325 }
6326
6327 zval *src = &object->ce->default_properties_table[OBJ_PROP_TO_NUM(ref->prop->offset)];
6328 zval *dst = OBJ_PROP(object, ref->prop->offset);
6329
6330 if (!(Z_PROP_FLAG_P(dst) & IS_PROP_LAZY)) {
6331 /* skipLazyInitialization has no effect on non-lazy properties */
6332 return;
6333 }
6334
6335 ZEND_ASSERT(Z_TYPE_P(dst) == IS_UNDEF && "Lazy property should be UNDEF");
6336
6337 ZVAL_COPY_PROP(dst, src);
6338
6339 /* Object becomes non-lazy if this was the last lazy prop */
6340 if (zend_object_is_lazy(object)
6341 && !zend_lazy_object_initialized(object)) {
6344 }
6345 }
6346}
6347
6349{
6350 reflection_object *intern;
6351 property_reference *ref;
6353
6355
6357 Z_PARAM_OBJ_OF_CLASS(object, intern->ce)
6359
6360 if (!ref->prop || ref->prop->flags & (ZEND_ACC_STATIC | ZEND_ACC_VIRTUAL)) {
6362 }
6363
6364 while (zend_object_is_lazy_proxy(object)
6365 && zend_lazy_object_initialized(object)) {
6366 object = zend_lazy_object_get_instance(object);
6367 }
6368
6370}
6371
6372/* {{{ Returns true if property was initialized */
6374{
6375 reflection_object *intern;
6376 property_reference *ref;
6377 zval *object = NULL;
6378 zval *member_p = NULL;
6379
6380 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &object) == FAILURE) {
6381 RETURN_THROWS();
6382 }
6383
6385
6386 if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
6387 member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 1);
6388 if (member_p) {
6389 RETURN_BOOL(!Z_ISUNDEF_P(member_p));
6390 }
6392 } else {
6393 zend_class_entry *old_scope;
6394 int retval;
6395
6396 if (!object) {
6397 zend_argument_type_error(1, "must be provided for instance properties");
6398 RETURN_THROWS();
6399 }
6400
6401 /* TODO: Should this always use intern->ce? */
6402 if (!instanceof_function(Z_OBJCE_P(object), ref->prop ? ref->prop->ce : intern->ce)) {
6403 _DO_THROW("Given object is not an instance of the class this property was declared in");
6404 RETURN_THROWS();
6405 }
6406
6407 old_scope = EG(fake_scope);
6408 EG(fake_scope) = intern->ce;
6409 retval = Z_OBJ_HT_P(object)->has_property(Z_OBJ_P(object), ref->unmangled_name, ZEND_PROPERTY_EXISTS, NULL);
6410 EG(fake_scope) = old_scope;
6411
6413 }
6414}
6415/* }}} */
6416
6417/* {{{ Get the declaring class */
6419{
6420 reflection_object *intern;
6421 property_reference *ref;
6422 zend_class_entry *ce;
6423
6425 RETURN_THROWS();
6426 }
6428
6429 ce = ref->prop ? ref->prop->ce : intern->ce;
6431}
6432/* }}} */
6433
6434/* {{{ Returns the doc comment for this property */
6436{
6437 reflection_object *intern;
6438 property_reference *ref;
6439
6441 RETURN_THROWS();
6442 }
6444 if (ref->prop && ref->prop->doc_comment) {
6446 }
6448}
6449/* }}} */
6450
6451/* {{{ Returns the attributes of this property */
6453{
6454 reflection_object *intern;
6455 property_reference *ref;
6456
6458
6459 if (ref->prop == NULL) {
6461 }
6462
6463 reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU,
6465 ref->prop->ce->type == ZEND_USER_CLASS ? ref->prop->ce->info.user.filename : NULL);
6466}
6467/* }}} */
6468
6469/* {{{ Sets whether non-public properties can be requested */
6471{
6472 bool visible;
6473
6474 if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
6475 RETURN_THROWS();
6476 }
6477}
6478/* }}} */
6479
6480/* {{{ Returns the type associated with the property */
6482{
6483 reflection_object *intern;
6484 property_reference *ref;
6485
6487 RETURN_THROWS();
6488 }
6489
6491
6492 if (!ref->prop || !ZEND_TYPE_IS_SET(ref->prop->type)) {
6493 RETURN_NULL();
6494 }
6495
6496 reflection_type_factory(ref->prop->type, return_value, 1);
6497}
6498/* }}} */
6499
6501{
6502 reflection_object *intern;
6503 property_reference *ref;
6504
6506 RETURN_THROWS();
6507 }
6508
6510
6511 zend_property_info *prop = ref->prop;
6512 /* Dynamic property is untyped. */
6513 if (!ref->prop) {
6514 RETURN_NULL();
6515 }
6516
6517 /* Get-only virtual property can never be written to. */
6518 if (prop->hooks && (prop->flags & ZEND_ACC_VIRTUAL) && !prop->hooks[ZEND_PROPERTY_HOOK_SET]) {
6519 zend_type never_type = ZEND_TYPE_INIT_CODE(IS_NEVER, 0, 0);
6520 reflection_type_factory(never_type, return_value, 0);
6521 return;
6522 }
6523
6524 /* Extract set $value parameter type. */
6525 if (prop->hooks && prop->hooks[ZEND_PROPERTY_HOOK_SET]) {
6527 if (!ZEND_TYPE_IS_SET(arg_info->type)) {
6528 RETURN_NULL();
6529 }
6530 reflection_type_factory(arg_info->type, return_value, 0);
6531 return;
6532 }
6533
6534 /* Fall back to property type */
6535 if (!ZEND_TYPE_IS_SET(ref->prop->type)) {
6536 RETURN_NULL();
6537 }
6538 reflection_type_factory(ref->prop->type, return_value, 0);
6539}
6540
6541/* {{{ Returns whether property has a type */
6543{
6544 reflection_object *intern;
6545 property_reference *ref;
6546
6548 RETURN_THROWS();
6549 }
6550
6552
6553 RETVAL_BOOL(ref->prop && ZEND_TYPE_IS_SET(ref->prop->type));
6554}
6555/* }}} */
6556
6557/* {{{ Returns whether property has a default value */
6559{
6560 reflection_object *intern;
6561 property_reference *ref;
6563 zval *prop;
6564
6566 RETURN_THROWS();
6567 }
6568
6570
6571 prop_info = ref->prop;
6572
6573 if (prop_info == NULL) {
6575 }
6576
6577 prop = property_get_default(prop_info);
6578 RETURN_BOOL(prop && !Z_ISUNDEF_P(prop));
6579}
6580/* }}} */
6581
6582/* {{{ Returns the default value of a property */
6584{
6585 reflection_object *intern;
6586 property_reference *ref;
6588 zval *prop;
6589
6591 RETURN_THROWS();
6592 }
6593
6595
6596 prop_info = ref->prop;
6597
6598 if (prop_info == NULL) {
6599 return; // throw exception?
6600 }
6601
6602 prop = property_get_default(prop_info);
6603 if (!prop || Z_ISUNDEF_P(prop)) {
6604 return;
6605 }
6606
6607 /* copy: enforce read only access */
6608 ZVAL_DEREF(prop);
6610
6611 /* this is necessary to make it able to work with default array
6612 * properties, returned to user */
6615 RETURN_THROWS();
6616 }
6617 }
6618}
6619/* }}} */
6620
6622{
6623 reflection_object *intern;
6624 property_reference *ref;
6625
6627
6629
6630 RETURN_BOOL(ref->prop && ref->prop->hooks);
6631}
6632
6634{
6635 reflection_object *intern;
6636 property_reference *ref;
6637
6639
6641
6642 // ref->prop can be missing for dynamic properties
6643 if (!ref->prop || !ref->prop->hooks) {
6645 }
6646
6648 if (ref->prop->hooks[ZEND_PROPERTY_HOOK_GET]) {
6649 zval hook_obj;
6651 reflection_method_factory(hook->common.scope, hook, NULL, &hook_obj);
6652 zend_hash_update(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_GET), &hook_obj);
6653 }
6654 if (ref->prop->hooks[ZEND_PROPERTY_HOOK_SET]) {
6655 zval hook_obj;
6657 reflection_method_factory(hook->common.scope, hook, NULL, &hook_obj);
6658 zend_hash_update(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_SET), &hook_obj);
6659 }
6660}
6661
6663{
6664
6665 reflection_object *intern;
6666 property_reference *ref;
6668
6672
6674
6676 if (zend_string_equals_literal(Z_STR_P(zend_enum_fetch_case_name(type)), "Get")) {
6678 } else {
6680 }
6681
6682 RETURN_BOOL(ref->prop && ref->prop->hooks && ref->prop->hooks[kind]);
6683}
6684
6686{
6687 reflection_object *intern;
6688 property_reference *ref;
6690
6694
6696
6697 // ref->prop can be missing for dynamic properties
6698 if (!ref->prop || !ref->prop->hooks) {
6699 RETURN_NULL();
6700 }
6701
6702 zend_function *hook;
6703 if (zend_string_equals_literal(Z_STR_P(zend_enum_fetch_case_name(type)), "Get")) {
6704 hook = ref->prop->hooks[ZEND_PROPERTY_HOOK_GET];
6705 } else {
6706 hook = ref->prop->hooks[ZEND_PROPERTY_HOOK_SET];
6707 }
6708
6709 if (!hook) {
6710 RETURN_NULL();
6711 }
6712
6713 reflection_method_factory(hook->common.scope, hook, NULL, return_value);
6714}
6715
6717{
6718 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
6719}
6720
6721/* {{{ Constructor. Throws an Exception in case the given extension does not exist */
6723{
6724 zval *object;
6725 char *lcname;
6726 reflection_object *intern;
6727 zend_module_entry *module;
6728 char *name_str;
6729 size_t name_len;
6730 ALLOCA_FLAG(use_heap)
6731
6732 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
6733 RETURN_THROWS();
6734 }
6735
6736 object = ZEND_THIS;
6737 intern = Z_REFLECTION_P(object);
6738 lcname = do_alloca(name_len + 1, use_heap);
6739 zend_str_tolower_copy(lcname, name_str, name_len);
6740 if ((module = zend_hash_str_find_ptr(&module_registry, lcname, name_len)) == NULL) {
6741 free_alloca(lcname, use_heap);
6743 "Extension \"%s\" does not exist", name_str);
6744 RETURN_THROWS();
6745 }
6746 free_alloca(lcname, use_heap);
6747 zval *prop_name = reflection_prop_name(object);
6748 zval_ptr_dtor(prop_name);
6749 ZVAL_STRING(prop_name, module->name);
6750 intern->ptr = module;
6751 intern->ref_type = REF_TYPE_OTHER;
6752 intern->ce = NULL;
6753}
6754/* }}} */
6755
6756/* {{{ Returns a string representation */
6758{
6759 reflection_object *intern;
6760 zend_module_entry *module;
6761 smart_str str = {0};
6762
6764 RETURN_THROWS();
6765 }
6767 _extension_string(&str, module, "");
6768 RETURN_STR(smart_str_extract(&str));
6769}
6770/* }}} */
6771
6772/* {{{ Returns this extension's name */
6774{
6775 reflection_object *intern;
6776 zend_module_entry *module;
6777
6779 RETURN_THROWS();
6780 }
6781
6783 RETURN_STRING(module->name);
6784}
6785/* }}} */
6786
6787/* {{{ Returns this extension's version */
6789{
6790 reflection_object *intern;
6791 zend_module_entry *module;
6792
6794 RETURN_THROWS();
6795 }
6797
6798 /* An extension does not necessarily have a version number */
6799 if (module->version == NO_VERSION_YET) {
6800 RETURN_NULL();
6801 } else {
6802 RETURN_STRING(module->version);
6803 }
6804}
6805/* }}} */
6806
6807/* {{{ Returns an array of this extension's functions */
6809{
6810 reflection_object *intern;
6811 zend_module_entry *module;
6812 zval function;
6813 zend_function *fptr;
6814
6816 RETURN_THROWS();
6817 }
6819
6821 ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), fptr) {
6823 && fptr->internal_function.module == module) {
6824 reflection_function_factory(fptr, NULL, &function);
6826 }
6828}
6829/* }}} */
6830
6831/* {{{ Returns an associative array containing this extension's constants and their values */
6833{
6834 reflection_object *intern;
6835 zend_module_entry *module;
6837
6839 RETURN_THROWS();
6840 }
6842
6844 ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) {
6845 if (module->module_number == ZEND_CONSTANT_MODULE_NUMBER(constant)) {
6846 zval const_val;
6847 ZVAL_COPY_OR_DUP(&const_val, &constant->value);
6848 zend_hash_update(Z_ARRVAL_P(return_value), constant->name, &const_val);
6849 }
6851}
6852/* }}} */
6853
6854/* {{{ _addinientry */
6855static void _addinientry(zend_ini_entry *ini_entry, zval *retval, int number)
6856{
6857 if (number == ini_entry->module_number) {
6858 zval zv;
6859 if (ini_entry->value) {
6860 ZVAL_STR_COPY(&zv, ini_entry->value);
6861 } else {
6862 ZVAL_NULL(&zv);
6863 }
6864 zend_symtable_update(Z_ARRVAL_P(retval), ini_entry->name, &zv);
6865 }
6866}
6867/* }}} */
6868
6869/* {{{ Returns an associative array containing this extension's INI entries and their values */
6871{
6872 reflection_object *intern;
6873 zend_module_entry *module;
6874 zend_ini_entry *ini_entry;
6875
6877 RETURN_THROWS();
6878 }
6880
6882 ZEND_HASH_MAP_FOREACH_PTR(EG(ini_directives), ini_entry) {
6883 _addinientry(ini_entry, return_value, module->module_number);
6885}
6886/* }}} */
6887
6888/* {{{ add_extension_class */
6889static void add_extension_class(zend_class_entry *ce, zend_string *key, zval *class_array, zend_module_entry *module, bool add_reflection_class)
6890{
6891 if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
6893
6894 if (!zend_string_equals_ci(ce->name, key)) {
6895 /* This is a class alias, use alias name */
6896 name = key;
6897 } else {
6898 /* Use class name */
6899 name = ce->name;
6900 }
6901 if (add_reflection_class) {
6902 zval zclass;
6903 zend_reflection_class_factory(ce, &zclass);
6904 zend_hash_update(Z_ARRVAL_P(class_array), name, &zclass);
6905 } else {
6906 add_next_index_str(class_array, zend_string_copy(name));
6907 }
6908 }
6909}
6910/* }}} */
6911
6912/* {{{ Returns an array containing ReflectionClass objects for all classes of this extension */
6914{
6915 reflection_object *intern;
6916 zend_module_entry *module;
6918 zend_class_entry *ce;
6919
6921 RETURN_THROWS();
6922 }
6924
6926 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
6927 add_extension_class(ce, key, return_value, module, 1);
6929}
6930/* }}} */
6931
6932/* {{{ Returns an array containing all names of all classes of this extension */
6934{
6935 reflection_object *intern;
6936 zend_module_entry *module;
6938 zend_class_entry *ce;
6939
6941 RETURN_THROWS();
6942 }
6944
6946 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
6947 add_extension_class(ce, key, return_value, module, 0);
6949}
6950/* }}} */
6951
6952/* {{{ Returns an array containing all names of all extensions this extension depends on */
6954{
6955 reflection_object *intern;
6956 zend_module_entry *module;
6957 const zend_module_dep *dep;
6958
6960 RETURN_THROWS();
6961 }
6963
6964 dep = module->deps;
6965
6966 if (!dep)
6967 {
6969 }
6970
6972 while(dep->name) {
6973 zend_string *relation;
6974 char *rel_type;
6975 size_t len = 0;
6976
6977 switch(dep->type) {
6979 rel_type = "Required";
6980 len += sizeof("Required") - 1;
6981 break;
6983 rel_type = "Conflicts";
6984 len += sizeof("Conflicts") - 1;
6985 break;
6987 rel_type = "Optional";
6988 len += sizeof("Optional") - 1;
6989 break;
6990 default:
6991 rel_type = "Error"; /* shouldn't happen */
6992 len += sizeof("Error") - 1;
6993 break;
6994 }
6995
6996 if (dep->rel) {
6997 len += strlen(dep->rel) + 1;
6998 }
6999
7000 if (dep->version) {
7001 len += strlen(dep->version) + 1;
7002 }
7003
7004 relation = zend_string_alloc(len, 0);
7005 snprintf(ZSTR_VAL(relation), ZSTR_LEN(relation) + 1, "%s%s%s%s%s",
7006 rel_type,
7007 dep->rel ? " " : "",
7008 dep->rel ? dep->rel : "",
7009 dep->version ? " " : "",
7010 dep->version ? dep->version : "");
7011 add_assoc_str(return_value, dep->name, relation);
7012 dep++;
7013 }
7014}
7015/* }}} */
7016
7017/* {{{ Prints phpinfo block for the extension */
7019{
7020 reflection_object *intern;
7021 zend_module_entry *module;
7022
7024 RETURN_THROWS();
7025 }
7027
7028 php_info_print_module(module);
7029}
7030/* }}} */
7031
7032/* {{{ Returns whether this extension is persistent */
7034{
7035 reflection_object *intern;
7036 zend_module_entry *module;
7037
7039 RETURN_THROWS();
7040 }
7042
7043 RETURN_BOOL(module->type == MODULE_PERSISTENT);
7044}
7045/* }}} */
7046
7047/* {{{ Returns whether this extension is temporary */
7049{
7050 reflection_object *intern;
7051 zend_module_entry *module;
7052
7054 RETURN_THROWS();
7055 }
7057
7058 RETURN_BOOL(module->type == MODULE_TEMPORARY);
7059}
7060/* }}} */
7061
7062/* {{{ Constructor. Throws an Exception in case the given Zend extension does not exist */
7064{
7065 zval *object;
7066 reflection_object *intern;
7067 zend_extension *extension;
7068 char *name_str;
7069 size_t name_len;
7070
7071 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
7072 RETURN_THROWS();
7073 }
7074
7075 object = ZEND_THIS;
7076 intern = Z_REFLECTION_P(object);
7077
7078 extension = zend_get_extension(name_str);
7079 if (!extension) {
7081 "Zend Extension \"%s\" does not exist", name_str);
7082 RETURN_THROWS();
7083 }
7084 ZVAL_STRING(reflection_prop_name(object), extension->name);
7085 intern->ptr = extension;
7086 intern->ref_type = REF_TYPE_OTHER;
7087 intern->ce = NULL;
7088}
7089/* }}} */
7090
7091/* {{{ Returns a string representation */
7093{
7094 reflection_object *intern;
7095 zend_extension *extension;
7096 smart_str str = {0};
7097
7099 RETURN_THROWS();
7100 }
7101 GET_REFLECTION_OBJECT_PTR(extension);
7102 _zend_extension_string(&str, extension, "");
7103 RETURN_STR(smart_str_extract(&str));
7104}
7105/* }}} */
7106
7107/* {{{ Returns the name of this Zend extension */
7109{
7110 reflection_object *intern;
7111 zend_extension *extension;
7112
7114 RETURN_THROWS();
7115 }
7116 GET_REFLECTION_OBJECT_PTR(extension);
7117
7118 RETURN_STRING(extension->name);
7119}
7120/* }}} */
7121
7122/* {{{ Returns the version information of this Zend extension */
7124{
7125 reflection_object *intern;
7126 zend_extension *extension;
7127
7129 RETURN_THROWS();
7130 }
7131 GET_REFLECTION_OBJECT_PTR(extension);
7132
7133 if (extension->version) {
7134 RETURN_STRING(extension->version);
7135 } else {
7137 }
7138}
7139/* }}} */
7140
7141/* {{{ Returns the name of this Zend extension's author */
7143{
7144 reflection_object *intern;
7145 zend_extension *extension;
7146
7148 RETURN_THROWS();
7149 }
7150 GET_REFLECTION_OBJECT_PTR(extension);
7151
7152 if (extension->author) {
7153 RETURN_STRING(extension->author);
7154 } else {
7156 }
7157}
7158/* }}} */
7159
7160/* {{{ Returns this Zend extension's URL*/
7162{
7163 reflection_object *intern;
7164 zend_extension *extension;
7165
7167 RETURN_THROWS();
7168 }
7169 GET_REFLECTION_OBJECT_PTR(extension);
7170
7171 if (extension->URL) {
7172 RETURN_STRING(extension->URL);
7173 } else {
7175 }
7176}
7177/* }}} */
7178
7179/* {{{ Returns this Zend extension's copyright information */
7181{
7182 reflection_object *intern;
7183 zend_extension *extension;
7184
7186 RETURN_THROWS();
7187 }
7188 GET_REFLECTION_OBJECT_PTR(extension);
7189
7190 if (extension->copyright) {
7191 RETURN_STRING(extension->copyright);
7192 } else {
7194 }
7195}
7196/* }}} */
7197
7198/* {{{ Dummy constructor -- always throws ReflectionExceptions. */
7200{
7201 _DO_THROW(
7202 "Cannot directly instantiate ReflectionReference. "
7203 "Use ReflectionReference::fromArrayElement() instead"
7204 );
7205}
7206/* }}} */
7207
7208static bool is_ignorable_reference(HashTable *ht, zval *ref) {
7209 if (Z_REFCOUNT_P(ref) != 1) {
7210 return 0;
7211 }
7212
7213 /* Directly self-referential arrays are treated as proper references
7214 * in zend_array_dup() despite rc=1. */
7215 return Z_TYPE_P(Z_REFVAL_P(ref)) != IS_ARRAY || Z_ARRVAL_P(Z_REFVAL_P(ref)) != ht;
7216}
7217
7218/* {{{ Create ReflectionReference for array item. Returns null if not a reference. */
7220{
7221 HashTable *ht;
7222 zval *item;
7223 zend_string *string_key = NULL;
7224 zend_long int_key = 0;
7225 reflection_object *intern;
7226
7229 Z_PARAM_STR_OR_LONG(string_key, int_key)
7231
7232 if (string_key) {
7233 item = zend_hash_find(ht, string_key);
7234 } else {
7235 item = zend_hash_index_find(ht, int_key);
7236 }
7237
7238 if (!item) {
7239 _DO_THROW("Array key not found");
7240 RETURN_THROWS();
7241 }
7242
7243 if (Z_TYPE_P(item) != IS_REFERENCE || is_ignorable_reference(ht, item)) {
7244 RETURN_NULL();
7245 }
7246
7248 intern = Z_REFLECTION_P(return_value);
7249 ZVAL_COPY(&intern->obj, item);
7250 intern->ref_type = REF_TYPE_OTHER;
7251}
7252/* }}} */
7253
7254/* {{{ Returns a unique identifier for the reference.
7255 * The format of the return value is unspecified and may change. */
7257{
7258 reflection_object *intern;
7259 unsigned char digest[20];
7261
7263 RETURN_THROWS();
7264 }
7265
7266 intern = Z_REFLECTION_P(ZEND_THIS);
7267 if (Z_TYPE(intern->obj) != IS_REFERENCE) {
7268 _DO_THROW("Corrupted ReflectionReference object");
7269 RETURN_THROWS();
7270 }
7271
7273 if (php_random_bytes_throw(&REFLECTION_G(key), 16) == FAILURE) {
7274 RETURN_THROWS();
7275 }
7276
7278 }
7279
7280 /* SHA1(ref || key) to avoid directly exposing memory addresses. */
7282 PHP_SHA1Update(&context, (unsigned char *) &Z_REF(intern->obj), sizeof(zend_reference *));
7284 PHP_SHA1Final(digest, &context);
7285
7286 RETURN_STRINGL((char *) digest, sizeof(digest));
7287}
7288/* }}} */
7289
7291{
7292 _DO_THROW("Cannot directly instantiate ReflectionAttribute");
7293}
7294
7296{
7297 /* __clone() is private but this is reachable with reflection */
7298 _DO_THROW("Cannot clone object using __clone()");
7299}
7300
7301/* {{{ Returns a string representation */
7303{
7304 reflection_object *intern;
7306
7308 RETURN_THROWS();
7309 }
7310
7312
7313 smart_str str = {0};
7314 smart_str_appends(&str, "Attribute [ ");
7315 smart_str_append(&str, attr->data->name);
7316 smart_str_appends(&str, " ]");
7317
7318 if (attr->data->argc > 0) {
7319 smart_str_appends(&str, " {\n");
7320 smart_str_append_printf(&str, " - Arguments [%d] {\n", attr->data->argc);
7321
7322 for (uint32_t i = 0; i < attr->data->argc; i++) {
7323 smart_str_append_printf(&str, " Argument #%d [ ", i);
7324 if (attr->data->args[i].name != NULL) {
7325 smart_str_append(&str, attr->data->args[i].name);
7326 smart_str_appends(&str, " = ");
7327 }
7328
7329 if (format_default_value(&str, &attr->data->args[i].value) == FAILURE) {
7330 smart_str_free(&str);
7331 RETURN_THROWS();
7332 }
7333
7334 smart_str_appends(&str, " ]\n");
7335 }
7336 smart_str_appends(&str, " }\n");
7337
7338 smart_str_appends(&str, "}\n");
7339 } else {
7340 smart_str_appendc(&str, '\n');
7341 }
7342
7343 RETURN_STR(smart_str_extract(&str));
7344}
7345/* }}} */
7346
7347/* {{{ Returns the name of the attribute */
7349{
7350 reflection_object *intern;
7352
7354 RETURN_THROWS();
7355 }
7357
7358 RETURN_STR_COPY(attr->data->name);
7359}
7360/* }}} */
7361
7362/* {{{ Returns the target of the attribute */
7364{
7365 reflection_object *intern;
7367
7369 RETURN_THROWS();
7370 }
7372
7373 RETURN_LONG(attr->target);
7374}
7375/* }}} */
7376
7377/* {{{ Returns true if the attribute is repeated */
7379{
7380 reflection_object *intern;
7382
7384 RETURN_THROWS();
7385 }
7387
7388 RETURN_BOOL(zend_is_attribute_repeated(attr->attributes, attr->data));
7389}
7390/* }}} */
7391
7392/* {{{ Returns the arguments passed to the attribute */
7394{
7395 reflection_object *intern;
7397
7398 zval tmp;
7399 uint32_t i;
7400
7402 RETURN_THROWS();
7403 }
7405
7407
7408 for (i = 0; i < attr->data->argc; i++) {
7409 if (FAILURE == zend_get_attribute_value(&tmp, attr->data, i, attr->scope)) {
7410 RETURN_THROWS();
7411 }
7412
7413 if (attr->data->args[i].name) {
7414 /* We ensured at compile-time that there are no duplicate parameter names. */
7415 zend_hash_add_new(Z_ARRVAL_P(return_value), attr->data->args[i].name, &tmp);
7416 } else {
7417 add_next_index_zval(return_value, &tmp);
7418 }
7419 }
7420}
7421/* }}} */
7422
7423/* {{{ Returns the attribute as an object */
7425{
7426 reflection_object *intern;
7428 zend_attribute *marker;
7429
7430 zend_class_entry *ce;
7431
7433 RETURN_THROWS();
7434 }
7435
7437
7438 if (NULL == (ce = zend_lookup_class(attr->data->name))) {
7439 zend_throw_error(NULL, "Attribute class \"%s\" not found", ZSTR_VAL(attr->data->name));
7440 RETURN_THROWS();
7441 }
7442
7443 if (NULL == (marker = zend_get_attribute_str(ce->attributes, ZEND_STRL("attribute")))) {
7444 zend_throw_error(NULL, "Attempting to use non-attribute class \"%s\" as attribute", ZSTR_VAL(attr->data->name));
7445 RETURN_THROWS();
7446 }
7447
7448 if (ce->type == ZEND_USER_CLASS) {
7449 uint32_t flags = zend_attribute_attribute_get_flags(marker, ce);
7450 if (EG(exception)) {
7451 RETURN_THROWS();
7452 }
7453
7454 if (!(attr->target & flags)) {
7457
7458 zend_throw_error(NULL, "Attribute \"%s\" cannot target %s (allowed targets: %s)",
7459 ZSTR_VAL(attr->data->name), ZSTR_VAL(location), ZSTR_VAL(allowed)
7460 );
7461
7462 zend_string_release(location);
7463 zend_string_release(allowed);
7464
7465 RETURN_THROWS();
7466 }
7467
7469 if (zend_is_attribute_repeated(attr->attributes, attr->data)) {
7470 zend_throw_error(NULL, "Attribute \"%s\" must not be repeated", ZSTR_VAL(attr->data->name));
7471 RETURN_THROWS();
7472 }
7473 }
7474 }
7475
7476 zval obj;
7477
7478 if (SUCCESS != zend_get_attribute_object(&obj, ce, attr->data, attr->scope, attr->filename)) {
7479 RETURN_THROWS();
7480 }
7481
7482 RETURN_COPY_VALUE(&obj);
7483}
7484
7486{
7487 reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
7488 if (EG(exception)) {
7489 RETURN_THROWS();
7490 }
7491
7492 reflection_object *intern;
7493 zend_class_entry *ce;
7495
7496 if (!(ce->ce_flags & ZEND_ACC_ENUM)) {
7497 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class \"%s\" is not an enum", ZSTR_VAL(ce->name));
7498 RETURN_THROWS();
7499 }
7500}
7501
7503{
7504 reflection_object *intern;
7505 zend_class_entry *ce;
7507
7509 RETURN_THROWS();
7510 }
7511
7513
7514 zend_class_constant *class_const = zend_hash_find_ptr(&ce->constants_table, name);
7515 if (class_const == NULL) {
7517 }
7518
7520}
7521
7523{
7524 reflection_object *intern;
7525 zend_class_entry *ce;
7527
7529 RETURN_THROWS();
7530 }
7531
7533
7534 zend_class_constant *constant = zend_hash_find_ptr(CE_CONSTANTS_TABLE(ce), name);
7535 if (constant == NULL) {
7536 zend_throw_exception_ex(reflection_exception_ptr, 0, "Case %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
7537 RETURN_THROWS();
7538 }
7540 zend_throw_exception_ex(reflection_exception_ptr, 0, "%s::%s is not a case", ZSTR_VAL(ce->name), ZSTR_VAL(name));
7541 RETURN_THROWS();
7542 }
7543
7544 reflection_enum_case_factory(ce, name, constant, return_value);
7545}
7546
7548{
7549 reflection_object *intern;
7550 zend_class_entry *ce;
7553
7555 RETURN_THROWS();
7556 }
7557
7559
7563 zval class_const;
7564 reflection_enum_case_factory(ce, name, constant, &class_const);
7566 }
7568}
7569
7571{
7572 reflection_object *intern;
7573 zend_class_entry *ce;
7574
7576 RETURN_THROWS();
7577 }
7578
7581}
7582
7584{
7585 reflection_object *intern;
7586 zend_class_entry *ce;
7587
7589 RETURN_THROWS();
7590 }
7591
7593
7594 if (ce->enum_backing_type == IS_UNDEF) {
7595 RETURN_NULL();
7596 } else {
7598 reflection_type_factory(type, return_value, 0);
7599 }
7600}
7601
7603{
7604 ZEND_MN(ReflectionClassConstant___construct)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
7605 if (EG(exception)) {
7606 RETURN_THROWS();
7607 }
7608
7609 reflection_object *intern;
7611
7613
7615 zval *case_name = reflection_prop_name(ZEND_THIS);
7616 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));
7617 RETURN_THROWS();
7618 }
7619}
7620
7633
7635{
7636 ZEND_MN(ReflectionEnumUnitCase___construct)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
7637 if (EG(exception)) {
7638 RETURN_THROWS();
7639 }
7640
7641 reflection_object *intern;
7643
7645
7646 if (ref->ce->enum_backing_type == IS_UNDEF) {
7647 zval *case_name = reflection_prop_name(ZEND_THIS);
7648 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));
7649 RETURN_THROWS();
7650 }
7651}
7652
7654{
7655 reflection_object *intern;
7657
7659 RETURN_THROWS();
7660 }
7662
7663 if (Z_TYPE(ref->value) == IS_CONSTANT_AST) {
7664 zval_update_constant_ex(&ref->value, ref->ce);
7665 if (EG(exception)) {
7666 RETURN_THROWS();
7667 }
7668 }
7669
7671 zval *member_p = zend_enum_fetch_case_value(Z_OBJ(ref->value));
7672
7673 ZVAL_COPY_OR_DUP(return_value, member_p);
7674}
7675
7676/* {{{ proto ReflectionFiber::__construct(Fiber $fiber) */
7678{
7679 zval *fiber, *object;
7680 reflection_object *intern;
7681
7682 object = ZEND_THIS;
7683 intern = Z_REFLECTION_P(object);
7684
7688
7689 if (intern->ce) {
7690 zval_ptr_dtor(&intern->obj);
7691 }
7692
7693 intern->ref_type = REF_TYPE_FIBER;
7694 ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(fiber));
7695 intern->ce = zend_ce_fiber;
7696}
7697/* }}} */
7698
7705
7706#define REFLECTION_CHECK_VALID_FIBER(fiber) do { \
7707 if (fiber == NULL || fiber->context.status == ZEND_FIBER_STATUS_INIT || fiber->context.status == ZEND_FIBER_STATUS_DEAD) { \
7708 zend_throw_error(NULL, "Cannot fetch information from a fiber that has not been started or is terminated"); \
7709 RETURN_THROWS(); \
7710 } \
7711 } while (0)
7712
7714{
7718
7723
7725
7728
7729 if (EG(active_fiber) != fiber) {
7730 // No need to replace current execute data if within the current fiber.
7731 EG(current_execute_data) = fiber->execute_data;
7732 }
7733
7735
7736 EG(current_execute_data) = execute_data; // Restore original execute data.
7737 fiber->stack_bottom->prev_execute_data = prev_execute_data; // Restore prev execute data on fiber stack.
7738}
7739
7741{
7744
7746
7748
7749 if (EG(active_fiber) == fiber) {
7750 prev_execute_data = execute_data->prev_execute_data;
7751 } else {
7753 }
7754
7755 while (prev_execute_data && (!prev_execute_data->func || !ZEND_USER_CODE(prev_execute_data->func->common.type))) {
7756 prev_execute_data = prev_execute_data->prev_execute_data;
7757 }
7758 if (prev_execute_data && prev_execute_data->func && ZEND_USER_CODE(prev_execute_data->func->common.type)) {
7759 RETURN_LONG(prev_execute_data->opline->lineno);
7760 }
7761 RETURN_NULL();
7762}
7763
7765{
7768
7770
7772
7773 if (EG(active_fiber) == fiber) {
7774 prev_execute_data = execute_data->prev_execute_data;
7775 } else {
7777 }
7778
7779 while (prev_execute_data && (!prev_execute_data->func || !ZEND_USER_CODE(prev_execute_data->func->common.type))) {
7780 prev_execute_data = prev_execute_data->prev_execute_data;
7781 }
7782 if (prev_execute_data && prev_execute_data->func && ZEND_USER_CODE(prev_execute_data->func->common.type)) {
7783 RETURN_STR_COPY(prev_execute_data->func->op_array.filename);
7784 }
7785 RETURN_NULL();
7786}
7787
7789{
7791
7793
7794 if (fiber == NULL || fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
7795 zend_throw_error(NULL, "Cannot fetch the callable from a fiber that has terminated"); \
7796 RETURN_THROWS();
7797 }
7798
7799 RETURN_COPY(&fiber->fci.function_name);
7800}
7801
7802/* {{{ _reflection_write_property */
7803static zval *_reflection_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
7804{
7805 if (zend_hash_exists(&object->ce->properties_info, name)
7806 && (zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_NAME)) || zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_CLASS))))
7807 {
7809 "Cannot set read-only property %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(name));
7810 return &EG(uninitialized_zval);
7811 }
7812 else
7813 {
7814 return zend_std_write_property(object, name, value, cache_slot);
7815 }
7816}
7817/* }}} */
7818
7820{
7822
7823 zval *object = ZEND_THIS;
7824 reflection_object *intern = Z_REFLECTION_P(object);
7825
7829
7830 /* Build name with lowercased ns. */
7831 bool backslash_prefixed = ZSTR_VAL(name)[0] == '\\';
7832 char *source = ZSTR_VAL(name) + backslash_prefixed;
7833 size_t source_len = ZSTR_LEN(name) - backslash_prefixed;
7834 zend_string *lc_name = zend_string_alloc(source_len, /* persistent */ false);
7835 const char *ns_end = zend_memrchr(source, '\\', source_len);
7836 size_t ns_len = 0;
7837 if (ns_end) {
7838 ns_len = ns_end - ZSTR_VAL(name);
7839 zend_str_tolower_copy(ZSTR_VAL(lc_name), source, ns_len);
7840 }
7841 memcpy(ZSTR_VAL(lc_name) + ns_len, source + ns_len, source_len - ns_len);
7842
7843 zend_constant *const_ = zend_get_constant_ptr(lc_name);
7844 zend_string_release_ex(lc_name, /* persistent */ false);
7845 if (!const_) {
7846 zend_throw_exception_ex(reflection_exception_ptr, 0, "Constant \"%s\" does not exist", ZSTR_VAL(name));
7847 RETURN_THROWS();
7848 }
7849
7850 intern->ptr = const_;
7851 intern->ref_type = REF_TYPE_OTHER;
7852
7853 zval *name_zv = reflection_prop_name(object);
7854 zval_ptr_dtor(name_zv);
7855 ZVAL_STR_COPY(name_zv, name);
7856}
7857
7859{
7860 reflection_object *intern;
7861 zend_constant *const_;
7862
7864 RETURN_THROWS();
7865 }
7866
7868 RETURN_STR_COPY(const_->name);
7869}
7870
7872{
7873 reflection_object *intern;
7874 zend_constant *const_;
7875
7877 RETURN_THROWS();
7878 }
7879
7881
7882 const char *backslash = zend_memrchr(ZSTR_VAL(const_->name), '\\', ZSTR_LEN(const_->name));
7883 if (backslash) {
7884 size_t length = backslash - ZSTR_VAL(const_->name);
7885 RETURN_STRINGL(ZSTR_VAL(const_->name), length);
7886 } else {
7888 }
7889}
7890
7892{
7893 reflection_object *intern;
7894 zend_constant *const_;
7895
7897 RETURN_THROWS();
7898 }
7899
7901
7902 const char *backslash = zend_memrchr(ZSTR_VAL(const_->name), '\\', ZSTR_LEN(const_->name));
7903 if (backslash) {
7904 size_t prefix = backslash - ZSTR_VAL(const_->name) + 1;
7905 size_t length = ZSTR_LEN(const_->name) - prefix;
7906 RETURN_STRINGL(ZSTR_VAL(const_->name) + prefix, length);
7907 } else {
7908 RETURN_STR_COPY(const_->name);
7909 }
7910}
7911
7913{
7914 reflection_object *intern;
7915 zend_constant *const_;
7916
7918 RETURN_THROWS();
7919 }
7920
7922 RETURN_COPY(&const_->value);
7923}
7924
7926{
7927 reflection_object *intern;
7928 zend_constant *const_;
7929
7931 RETURN_THROWS();
7932 }
7933
7936}
7937
7939{
7940 reflection_object *intern;
7941 zend_constant *const_;
7942 smart_str str = {0};
7943
7945 RETURN_THROWS();
7946 }
7947
7949 _const_string(&str, ZSTR_VAL(const_->name), &const_->value, "");
7950 RETURN_STR(smart_str_extract(&str));
7951}
7952
7953PHP_MINIT_FUNCTION(reflection) /* {{{ */
7954{
7955 memcpy(&reflection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
7956 reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo);
7957 reflection_object_handlers.free_obj = reflection_free_objects_storage;
7958 reflection_object_handlers.clone_obj = NULL;
7959 reflection_object_handlers.write_property = _reflection_write_property;
7960 reflection_object_handlers.get_gc = reflection_get_gc;
7961
7962 reflection_exception_ptr = register_class_ReflectionException(zend_ce_exception);
7963
7964 reflection_ptr = register_class_Reflection();
7965
7966 reflector_ptr = register_class_Reflector(zend_ce_stringable);
7967
7968 reflection_function_abstract_ptr = register_class_ReflectionFunctionAbstract(reflector_ptr);
7969 reflection_function_abstract_ptr->default_object_handlers = &reflection_object_handlers;
7970 reflection_function_abstract_ptr->create_object = reflection_objects_new;
7971
7972 reflection_function_ptr = register_class_ReflectionFunction(reflection_function_abstract_ptr);
7973 reflection_function_ptr->create_object = reflection_objects_new;
7974 reflection_function_ptr->default_object_handlers = &reflection_object_handlers;
7975
7976 reflection_generator_ptr = register_class_ReflectionGenerator();
7977 reflection_generator_ptr->create_object = reflection_objects_new;
7978 reflection_generator_ptr->default_object_handlers = &reflection_object_handlers;
7979
7980 reflection_parameter_ptr = register_class_ReflectionParameter(reflector_ptr);
7981 reflection_parameter_ptr->create_object = reflection_objects_new;
7982 reflection_parameter_ptr->default_object_handlers = &reflection_object_handlers;
7983
7984 reflection_type_ptr = register_class_ReflectionType(zend_ce_stringable);
7985 reflection_type_ptr->create_object = reflection_objects_new;
7986 reflection_type_ptr->default_object_handlers = &reflection_object_handlers;
7987
7988 reflection_named_type_ptr = register_class_ReflectionNamedType(reflection_type_ptr);
7989 reflection_named_type_ptr->create_object = reflection_objects_new;
7990 reflection_named_type_ptr->default_object_handlers = &reflection_object_handlers;
7991
7992 reflection_union_type_ptr = register_class_ReflectionUnionType(reflection_type_ptr);
7993 reflection_union_type_ptr->create_object = reflection_objects_new;
7994 reflection_union_type_ptr->default_object_handlers = &reflection_object_handlers;
7995
7996 reflection_intersection_type_ptr = register_class_ReflectionIntersectionType(reflection_type_ptr);
7997 reflection_intersection_type_ptr->create_object = reflection_objects_new;
7998 reflection_intersection_type_ptr->default_object_handlers = &reflection_object_handlers;
7999
8000 reflection_method_ptr = register_class_ReflectionMethod(reflection_function_abstract_ptr);
8001 reflection_method_ptr->create_object = reflection_objects_new;
8002 reflection_method_ptr->default_object_handlers = &reflection_object_handlers;
8003
8004 reflection_class_ptr = register_class_ReflectionClass(reflector_ptr);
8005 reflection_class_ptr->create_object = reflection_objects_new;
8006 reflection_class_ptr->default_object_handlers = &reflection_object_handlers;
8007
8008 reflection_object_ptr = register_class_ReflectionObject(reflection_class_ptr);
8009 reflection_object_ptr->create_object = reflection_objects_new;
8010 reflection_object_ptr->default_object_handlers = &reflection_object_handlers;
8011
8012 reflection_property_ptr = register_class_ReflectionProperty(reflector_ptr);
8013 reflection_property_ptr->create_object = reflection_objects_new;
8014 reflection_property_ptr->default_object_handlers = &reflection_object_handlers;
8015
8016 reflection_class_constant_ptr = register_class_ReflectionClassConstant(reflector_ptr);
8017 reflection_class_constant_ptr->create_object = reflection_objects_new;
8018 reflection_class_constant_ptr->default_object_handlers = &reflection_object_handlers;
8019
8020 reflection_extension_ptr = register_class_ReflectionExtension(reflector_ptr);
8021 reflection_extension_ptr->create_object = reflection_objects_new;
8022 reflection_extension_ptr->default_object_handlers = &reflection_object_handlers;
8023
8024 reflection_zend_extension_ptr = register_class_ReflectionZendExtension(reflector_ptr);
8025 reflection_zend_extension_ptr->create_object = reflection_objects_new;
8026 reflection_zend_extension_ptr->default_object_handlers = &reflection_object_handlers;
8027
8028 reflection_reference_ptr = register_class_ReflectionReference();
8029 reflection_reference_ptr->create_object = reflection_objects_new;
8030 reflection_reference_ptr->default_object_handlers = &reflection_object_handlers;
8031
8032 reflection_attribute_ptr = register_class_ReflectionAttribute(reflector_ptr);
8033 reflection_attribute_ptr->create_object = reflection_objects_new;
8034 reflection_attribute_ptr->default_object_handlers = &reflection_object_handlers;
8035
8036 reflection_enum_ptr = register_class_ReflectionEnum(reflection_class_ptr);
8037 reflection_enum_ptr->create_object = reflection_objects_new;
8038 reflection_enum_ptr->default_object_handlers = &reflection_object_handlers;
8039
8040 reflection_enum_unit_case_ptr = register_class_ReflectionEnumUnitCase(reflection_class_constant_ptr);
8041 reflection_enum_unit_case_ptr->create_object = reflection_objects_new;
8042 reflection_enum_unit_case_ptr->default_object_handlers = &reflection_object_handlers;
8043
8044 reflection_enum_backed_case_ptr = register_class_ReflectionEnumBackedCase(reflection_enum_unit_case_ptr);
8045 reflection_enum_backed_case_ptr->create_object = reflection_objects_new;
8046 reflection_enum_backed_case_ptr->default_object_handlers = &reflection_object_handlers;
8047
8048 reflection_fiber_ptr = register_class_ReflectionFiber();
8049 reflection_fiber_ptr->create_object = reflection_objects_new;
8050 reflection_fiber_ptr->default_object_handlers = &reflection_object_handlers;
8051
8052 reflection_constant_ptr = register_class_ReflectionConstant(reflector_ptr);
8053 reflection_constant_ptr->create_object = reflection_objects_new;
8054 reflection_constant_ptr->default_object_handlers = &reflection_object_handlers;
8055
8056 reflection_property_hook_type_ptr = register_class_PropertyHookType();
8057
8059
8060 return SUCCESS;
8061} /* }}} */
8062
8063PHP_MINFO_FUNCTION(reflection) /* {{{ */
8064{
8066 php_info_print_table_row(2, "Reflection", "enabled");
8068} /* }}} */
8069
8072 "Reflection",
8073 NULL,
8074 PHP_MINIT(reflection),
8075 NULL,
8076 NULL,
8077 NULL,
8078 PHP_MINFO(reflection),
8080 ZEND_MODULE_GLOBALS(reflection),
8081 NULL,
8082 NULL,
8083 NULL,
8085}; /* }}} */
size_t len
Definition apprentice.c:174
bool exception
Definition assert.c:30
zval callback
Definition assert.c:25
constant(string $name)
is_object(mixed $value)
count(Countable|array $value, int $mode=COUNT_NORMAL)
strstr(string $haystack, string $needle, bool $before_needle=false)
zend_ffi_type * type
Definition ffi.c:3812
zval * zv
Definition ffi.c:3975
new_type kind
Definition ffi.c:4363
void * ptr
Definition ffi.c:3814
memcpy(ptr1, ptr2, size)
new_type attr
Definition ffi.c:4364
zval * val
Definition ffi.c:4262
HashTable * ht
Definition ffi.c:4838
const php_stream_filter_ops * ops
Definition filters.c:1899
zend_long offset
#define SIZE_MAX
Definition funcs.c:51
#define NULL
Definition gdcache.h:45
#define prefix
#define SUCCESS
Definition hash_sha3.c:261
again j
foreach($dp as $el) foreach( $dp as $el) if( $pass2< 2) echo ""
PHPAPI ZEND_COLD void php_info_print_module(zend_module_entry *zend_module)
Definition info.c:133
php_info_print_table_start()
Definition info.c:1064
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_MINIT
Definition php.h:392
#define PHP_METHOD
Definition php.h:365
#define PHPAPI
Definition php.h:71
unsigned const char * end
Definition php_ffi.h:51
PHP_JSON_API size_t int options
Definition php_json.h:102
#define REFLECTION_ATTRIBUTE_IS_INSTANCEOF
PHPAPI zend_class_entry * reflection_zend_extension_ptr
PHPAPI zend_class_entry * reflection_extension_ptr
PHPAPI zend_class_entry * reflection_function_ptr
struct _attribute_reference attribute_reference
#define REFLECTION_G(v)
reflection_object_handlers clone_obj
#define REFLECTION_CHECK_VALID_GENERATOR(ex)
PHPAPI zend_class_entry * reflection_attribute_ptr
reflection_type_kind
@ INTERSECTION_TYPE
@ UNION_TYPE
@ NAMED_TYPE
struct _type_reference type_reference
PHPAPI zend_class_entry * reflector_ptr
PHPAPI zend_class_entry * reflection_constant_ptr
PHPAPI zend_class_entry * reflection_property_ptr
PHPAPI zend_class_entry * reflection_intersection_type_ptr
#define GET_REFLECTION_OBJECT_PTR(target)
PHPAPI zend_class_entry * reflection_parameter_ptr
PHPAPI zend_class_entry * reflection_fiber_ptr
#define Z_REFLECTION_P(zv)
unsigned char key[REFLECTION_KEY_LEN]
#define GET_REFLECTION_OBJECT()
PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object)
PHPAPI zend_class_entry * reflection_reference_ptr
PHPAPI zend_class_entry * reflection_enum_ptr
PHPAPI zend_class_entry * reflection_enum_unit_case_ptr
#define REFLECTION_CHECK_VALID_FIBER(fiber)
#define DUMP_CONST_FLAG(flag, output)
#define REFLECTION_KEY_LEN
#define _DO_THROW(msg)
PHPAPI zend_class_entry * reflection_type_ptr
zend_module_entry reflection_module_entry
php_info_print_table_row(2, "Reflection", "enabled")
PHPAPI zend_class_entry * reflection_method_ptr
reflection_type_t
@ REF_TYPE_FUNCTION
@ REF_TYPE_PARAMETER
@ REF_TYPE_TYPE
@ REF_TYPE_FIBER
@ REF_TYPE_PROPERTY
@ REF_TYPE_OTHER
@ REF_TYPE_ATTRIBUTE
@ REF_TYPE_GENERATOR
@ REF_TYPE_CLASS_CONSTANT
PHPAPI zend_class_entry * reflection_property_hook_type_ptr
PHPAPI zend_class_entry * reflection_object_ptr
PHPAPI zend_class_entry * reflection_ptr
struct _parameter_reference parameter_reference
PHPAPI zend_class_entry * reflection_named_type_ptr
struct _property_reference property_reference
php_info_print_table_end()
Definition info.c:1074
bool key_initialized
PHPAPI zend_class_entry * reflection_generator_ptr
PHPAPI zend_class_entry * reflection_class_constant_ptr
PHPAPI zend_class_entry * reflection_enum_backed_case_ptr
PHPAPI zend_class_entry * reflection_class_ptr
PHPAPI zend_class_entry * reflection_function_abstract_ptr
PHPAPI zend_class_entry * reflection_union_type_ptr
PHPAPI zend_class_entry * reflection_exception_ptr
void reflection_class_new_lazy(INTERNAL_FUNCTION_PARAMETERS, int strategy, bool is_reset)
#define PHP_REFLECTION_VERSION
zend_test_fiber * active_fiber
Definition php_test.h:61
zend_constant * data
zend_string * lcname
zend_object * ex
zval * current
Definition session.c:1024
zval rv
Definition session.c:1024
PHPAPI void PHP_SHA1Final(unsigned char digest[20], PHP_SHA1_CTX *context)
Definition sha1.c:215
PHPAPI void PHP_SHA1Update(PHP_SHA1_CTX *context, const unsigned char *input, size_t inputLen)
Definition sha1.c:173
#define PHP_SHA1Init(ctx)
Definition sha1.h:28
#define strpprintf
Definition spprintf.h:30
zend_string * key
Definition zend_types.h:383
zval val
Definition zend_types.h:381
zend_attribute * data
zend_class_entry * scope
zend_function * fptr
struct _zend_arg_info * arg_info
zend_string * unmangled_name
zend_property_info * prop
zend_string * default_value
zend_string * name
Bucket * arData
Definition zend_types.h:403
zend_ast_kind kind
Definition zend_ast.h:187
zend_ast * child[1]
Definition zend_ast.h:190
zend_class_entry * ce
zend_string * doc_comment
HashTable constants_table
Definition zend.h:165
zend_object *(* create_object)(zend_class_entry *class_type)
Definition zend.h:195
struct _zend_module_entry * module
Definition zend.h:234
zval * default_static_members_table
Definition zend.h:161
struct _zend_class_entry::@126215362204241324314155352336150042254204116267::@166057154351252324007362117353350250255142166322 user
HashTable properties_info
Definition zend.h:164
zend_object_iterator *(* get_iterator)(zend_class_entry *ce, zval *object, int by_ref)
Definition zend.h:198
zend_string * filename
Definition zend.h:228
zend_class_name * trait_names
Definition zend.h:216
zend_string * name
Definition zend.h:149
union _zend_class_entry::@126215362204241324314155352336150042254204116267 info
uint32_t num_traits
Definition zend.h:206
struct _zend_class_entry::@126215362204241324314155352336150042254204116267::@031207115026352130035014265255253014334154061307 internal
uint32_t num_interfaces
Definition zend.h:205
uint32_t line_end
Definition zend.h:230
uint32_t ce_flags
Definition zend.h:156
char type
Definition zend.h:148
uint32_t line_start
Definition zend.h:229
zend_trait_alias ** trait_aliases
Definition zend.h:217
zend_class_entry ** interfaces
Definition zend.h:212
int default_static_members_count
Definition zend.h:159
HashTable * attributes
Definition zend.h:219
zend_function * constructor
Definition zend.h:172
uint32_t enum_backing_type
Definition zend.h:221
zend_class_entry * parent
Definition zend.h:152
zend_string * doc_comment
Definition zend.h:224
zval * default_properties_table
Definition zend.h:160
HashTable function_table
Definition zend.h:163
zend_function * clone
Definition zend.h:174
zend_string * lc_name
Definition zend.h:87
zend_string * name
Definition zend.h:86
zend_string * name
zend_execute_data * prev_execute_data
const char * version
const char * URL
const char * name
const char * author
const char * copyright
zend_function * function_handler
Definition zend_API.h:60
zend_class_entry * called_scope
Definition zend_API.h:62
zend_object * object
Definition zend_API.h:63
zend_fiber_status status
Definition zend_fibers.h:93
zend_execute_data * stack_bottom
zend_fcall_info fci
zend_fiber_context context
zend_execute_data * execute_data
zend_execute_data * execute_data
zend_string * value
Definition zend_ini.h:53
uint8_t modifiable
Definition zend_ini.h:59
zend_string * orig_value
Definition zend_ini.h:54
int module_number
Definition zend_ini.h:57
zend_string * name
Definition zend_ini.h:48
uint8_t modified
Definition zend_ini.h:61
zend_class_entry * scope
zend_string * function_name
zend_function * prototype
struct _zend_module_entry * module
zend_internal_arg_info * arg_info
zend_string * doc_comment
unsigned char type
const char * name
const char * rel
const char * version
const char * name
zend_object_get_properties_t get_properties
zend_class_entry * ce
Definition zend_types.h:560
const zend_object_handlers * handlers
Definition zend_types.h:561
HashTable * static_variables
zend_string * filename
zend_string * doc_comment
uint32_t line_start
zend_op * opcodes
uint32_t line_end
uint32_t fn_flags
znode_op op1
znode_op op2
uint8_t opcode
uint32_t extended_value
zend_string * doc_comment
zend_function ** hooks
zend_string * name
HashTable * attributes
zend_class_entry * ce
zend_trait_method_reference trait_method
Definition zend.h:102
zend_string * alias
Definition zend.h:107
zend_string * method_name
Definition zend.h:91
zend_string * class_name
Definition zend.h:92
Definition dce.c:49
reflection_type_t ref_type
zend_class_entry * ce
zend_string * s
zend_arg_info * arg_info
zend_function * prototype
uint32_t required_num_args
zend_class_entry * scope
zend_op_array op_array
zend_string * function_name
struct _zend_function::@236135173067030250234125302313220025134003177336 common
HashTable * attributes
uint32_t fn_flags
zend_internal_function internal_function
uint32_t num_args
uint32_t num
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
#define DEBUG_BACKTRACE_PROVIDE_OBJECT
Definition zend.h:450
struct _zend_trait_method_reference zend_trait_method_reference
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type)
Definition zend_API.c:1518
ZEND_API zval * zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv)
Definition zend_API.c:5187
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length)
Definition zend_API.c:2195
ZEND_API zval * zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, bool silent)
Definition zend_API.c:5213
ZEND_API HashTable module_registry
Definition zend_API.c:41
ZEND_API zend_result zend_get_default_from_internal_arg_info(zval *default_value_zval, zend_internal_arg_info *arg_info)
Definition zend_API.c:5352
ZEND_API const char * zend_zval_type_name(const zval *arg)
Definition zend_API.c:167
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format,...)
Definition zend_API.c:413
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error)
Definition zend_API.c:4271
ZEND_API void add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str)
Definition zend_API.c:1973
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zval *value)
Definition zend_API.c:4979
ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, const zend_string *name, zend_class_entry *scope)
Definition zend_API.c:1490
ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value)
Definition zend_API.c:5086
ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str)
Definition zend_API.c:2177
ZEND_API zend_result zend_parse_parameters_ex(int flags, uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1287
#define CE_STATIC_MEMBERS(ce)
Definition zend_API.h:328
#define Z_PARAM_FUNC(dest_fci, dest_fcc)
Definition zend_API.h:1824
#define RETURN_COPY_DEREF(zv)
Definition zend_API.h:1056
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
struct _zend_fcall_info_cache zend_fcall_info_cache
#define Z_PARAM_OBJ_OF_CLASS_OR_STR(destination_object, base_ce, destination_string)
Definition zend_API.h:1788
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define RETURN_STRINGL(s, l)
Definition zend_API.h:1044
#define RETURN_OBJ(r)
Definition zend_API.h:1052
#define RETURN_COPY(zv)
Definition zend_API.h:1054
#define ZEND_PARSE_PARAMS_QUIET
Definition zend_API.h:361
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define Z_PARAM_STR_OR_NULL(dest)
Definition zend_API.h:2089
#define ZEND_PARSE_PARAMETERS_NONE()
Definition zend_API.h:1623
#define RETURN_NULL()
Definition zend_API.h:1036
#define Z_PARAM_OBJ_OR_STR(destination_object, destination_string)
Definition zend_API.h:1768
#define ZVAL_STRING(z, s)
Definition zend_API.h:956
#define ZEND_DECLARE_MODULE_GLOBALS(module_name)
Definition zend_API.h:268
#define RETVAL_STR_COPY(s)
Definition zend_API.h:1016
#define RETVAL_NEW_STR(s)
Definition zend_API.h:1015
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define zend_parse_parameters_none()
Definition zend_API.h:353
#define Z_PARAM_STR(dest)
Definition zend_API.h:2086
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define ZEND_END_MODULE_GLOBALS(module_name)
Definition zend_API.h:248
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETVAL_NULL()
Definition zend_API.h:1010
#define RETURN_BOOL(b)
Definition zend_API.h:1035
#define RETURN_OBJ_COPY(r)
Definition zend_API.h:1053
struct _zend_fcall_info zend_fcall_info
#define ZEND_METHOD(classname, name)
Definition zend_API.h:76
#define RETURN_THROWS()
Definition zend_API.h:1060
#define Z_PARAM_OBJ(dest)
Definition zend_API.h:1955
#define CE_CONSTANTS_TABLE(ce)
Definition zend_API.h:331
#define Z_PARAM_ARRAY_HT(dest)
Definition zend_API.h:1852
#define Z_PARAM_OBJ_OF_CLASS(dest, _ce)
Definition zend_API.h:1997
#define RETURN_STR(s)
Definition zend_API.h:1039
#define ZEND_THIS
Definition zend_API.h:523
#define RETVAL_BOOL(b)
Definition zend_API.h:1009
#define RETURN_COPY_VALUE(zv)
Definition zend_API.h:1055
#define Z_PARAM_STR_OR_LONG(dest_str, dest_long)
Definition zend_API.h:2165
#define RETVAL_LONG(l)
Definition zend_API.h:1011
#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce)
Definition zend_API.h:1976
#define RETURN_EMPTY_ARRAY()
Definition zend_API.h:1051
#define RETURN_EMPTY_STRING()
Definition zend_API.h:1047
ZEND_API void zend_call_known_function(zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr, uint32_t param_count, zval *params, HashTable *named_params)
#define Z_PARAM_ZVAL(dest)
Definition zend_API.h:2100
#define getThis()
Definition zend_API.h:526
#define ZVAL_STRINGL(z, s, l)
Definition zend_API.h:952
#define RETURN_ZVAL(zv, copy, dtor)
Definition zend_API.h:1057
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define ZEND_MN(name)
Definition zend_API.h:72
#define Z_PARAM_OBJECT_OR_NULL(dest)
Definition zend_API.h:1943
#define ZEND_BEGIN_MODULE_GLOBALS(module_name)
Definition zend_API.h:246
#define RETVAL_STRINGL(s, l)
Definition zend_API.h:1018
#define RETURN_STR_COPY(s)
Definition zend_API.h:1042
#define array_init(arg)
Definition zend_API.h:537
#define Z_PARAM_VARIADIC_WITH_NAMED(dest, dest_num, dest_named)
Definition zend_API.h:2127
#define efree(ptr)
Definition zend_alloc.h:155
#define emalloc(size)
Definition zend_alloc.h:151
ZEND_API ZEND_COLD zend_string * zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
Definition zend_ast.c:2679
@ ZEND_AST_CONSTANT
Definition zend_ast.h:37
@ ZEND_AST_CLASS_CONST
Definition zend_ast.h:120
@ ZEND_AST_CONSTANT_CLASS
Definition zend_ast.h:75
ZEND_API zend_result zend_get_attribute_value(zval *ret, zend_attribute *attr, uint32_t i, zend_class_entry *scope)
ZEND_API zend_result zend_get_attribute_object(zval *obj, zend_class_entry *attribute_ce, zend_attribute *attribute_data, zend_class_entry *scope, zend_string *filename)
ZEND_API bool zend_is_attribute_repeated(HashTable *attributes, zend_attribute *attr)
uint32_t zend_attribute_attribute_get_flags(zend_attribute *attr, zend_class_entry *scope)
ZEND_API zend_string * zend_get_attribute_target_names(uint32_t flags)
ZEND_API zend_attribute * zend_get_attribute_str(HashTable *attributes, const char *str, size_t len)
#define ZEND_ATTRIBUTE_TARGET_METHOD
#define ZEND_ATTRIBUTE_TARGET_PARAMETER
#define ZEND_ATTRIBUTE_IS_REPEATABLE
struct _zend_attribute zend_attribute
#define ZEND_ATTRIBUTE_TARGET_FUNCTION
#define ZEND_ATTRIBUTE_TARGET_CLASS_CONST
#define ZEND_ATTRIBUTE_TARGET_PROPERTY
#define ZEND_ATTRIBUTE_TARGET_CLASS
ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit)
struct _zval_struct zval
strlen(string $string)
strcmp(string $string1, string $string2)
ZEND_API const zend_function * zend_get_closure_method_def(zend_object *obj)
uint32_t num_args
ZEND_API zend_class_entry * zend_ce_closure
ZEND_API zval * zend_get_closure_this_ptr(zval *obj)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API void zend_create_fake_closure(zval *res, zend_function *func, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr)
execute_data func
zval * args
ZEND_API zend_function * zend_get_closure_invoke_method(zend_object *object)
#define ZEND_CLOSURE_OBJECT(op_array)
ZEND_API zend_string * zend_type_to_string(zend_type type)
#define ZEND_ARG_IS_PROMOTED(arg_info)
#define ZEND_BIND_REF
#define ZEND_DESTRUCTOR_FUNC_NAME
#define ZEND_ACC_ENUM
struct _zend_op zend_op
#define OBJ_PROP_TO_NUM(offset)
#define ZEND_USER_CODE(type)
#define ZEND_ACC_FINAL
#define ZEND_ACC_FAKE_CLOSURE
#define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS
#define BP_VAR_W
#define ZEND_SEND_BY_REF
#define ZEND_ACC_CTOR
#define ZEND_INTERNAL_FUNCTION
#define ZEND_ACC_ABSTRACT
#define ZEND_CLASS_CONST_FLAGS(c)
#define ZEND_ACC_PROMOTED
#define ZEND_ACC_LINKED
#define ZEND_ACC_READONLY
#define ZEND_ACC_PROTECTED_SET
#define ZEND_ARG_SEND_MODE(arg_info)
#define zend_unmangle_property_name(mangled_property, class_name, prop_name)
#define ZEND_FETCH_CLASS_TRAIT
#define ZEND_ACC_PPP_SET_MASK
#define ZEND_ACC_USER_ARG_INFO
#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
#define ZEND_USER_FUNCTION
#define ZEND_ACC_INTERFACE
#define ZEND_ACC_PRIVATE_SET
#define ZEND_ACC_CALL_VIA_TRAMPOLINE
#define ZEND_ACC_GENERATOR
struct _zend_op_array zend_op_array
#define ZEND_ACC_READONLY_CLASS
#define OBJ_PROP(obj, offset)
struct _zend_class_constant zend_class_constant
struct _zend_property_info zend_property_info
#define ZEND_ACC_TRAIT
#define ZEND_BIND_IMPLICIT
#define ZEND_ACC_PRIVATE
#define ZEND_ARG_TYPE_IS_TENTATIVE(arg_info)
struct _zend_internal_arg_info zend_internal_arg_info
#define ZEND_ACC_ANON_CLASS
#define RT_CONSTANT(opline, node)
#define ZEND_ACC_PPP_MASK
#define ZEND_ACC_STATIC
#define ZEND_ARG_IS_VARIADIC(arg_info)
#define ZEND_ACC_PUBLIC
#define ZEND_ACC_HAS_RETURN_TYPE
struct _zend_arg_info zend_arg_info
#define ZEND_ACC_PUBLIC_SET
#define ZEND_ACC_VIRTUAL
#define ZEND_ACC_VARIADIC
#define ZEND_USER_CLASS
#define ZEND_CLASS_CONST_IS_CASE
#define ZEND_INTERNAL_CLASS
struct _zend_internal_function zend_internal_function
#define ZEND_ACC_DEPRECATED
#define ZEND_INVOKE_FUNC_NAME
#define ZEND_ACC_RETURN_REFERENCE
char * zend_visibility_string(uint32_t fn_flags)
#define ZEND_ACC_PROTECTED
#define BP_VAR_IS
#define ZEND_ACC_CLOSURE
#define ZEND_BIND_EXPLICIT
#define strcasecmp(s1, s2)
#define snprintf
ZEND_API zend_constant * zend_get_constant_ptr(zend_string *name)
#define ZEND_CONSTANT_FLAGS(c)
#define ZEND_CONSTANT_MODULE_NUMBER(c)
#define CONST_NO_FILE_CACHE
#define CONST_PERSISTENT
struct _zend_constant zend_constant
#define CONST_DEPRECATED
#define E_DEPRECATED
Definition zend_errors.h:37
ZEND_API zend_class_entry * zend_ce_exception
ZEND_API void zend_clear_exception(void)
ZEND_API ZEND_COLD zend_object * zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format,...)
ZEND_API zend_function *ZEND_FASTCALL zend_fetch_function(zend_string *name)
ZEND_API bool zend_never_inline zend_verify_property_type(const zend_property_info *info, zval *property, bool strict)
ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict)
ZEND_API zend_class_entry * zend_lookup_class(zend_string *name)
ZEND_API zend_class_entry * zend_fetch_class_by_name(zend_string *class_name, zend_string *lcname, uint32_t fetch_type)
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope)
ZEND_API zend_string * get_active_function_or_method_name(void)
ZEND_API zend_class_entry * zend_lookup_class_ex(zend_string *name, zend_string *lcname, uint32_t flags)
ZEND_API zend_extension * zend_get_extension(const char *extension_name)
struct _zend_extension zend_extension
ZEND_API zend_class_entry * zend_ce_fiber
@ ZEND_FIBER_STATUS_DEAD
Definition zend_fibers.h:37
union _zend_function zend_function
ZEND_API zend_class_entry * zend_ce_generator
struct _zend_generator zend_generator
struct _zend_ini_entry zend_ini_entry
struct _zend_fiber zend_fiber
#define CG(v)
#define EG(v)
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert_new(HashTable *ht, zval *pData)
Definition zend_hash.c:1229
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData)
Definition zend_hash.c:1224
ZEND_API zval *ZEND_FASTCALL zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:1007
ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
Definition zend_hash.c:2240
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
Definition zend_hash.c:2438
ZEND_API zval *ZEND_FASTCALL zend_hash_update(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:997
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
Definition zend_hash.c:2668
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
#define ZEND_HASH_MAP_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1326
#define ZEND_HASH_PACKED_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1487
#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val)
Definition zend_hash.h:1181
#define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val)
Definition zend_hash.h:1166
#define ZEND_HASH_MAP_FOREACH_STR_KEY(ht, _key)
Definition zend_hash.h:1346
#define ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(ht, _key, _ptr)
Definition zend_hash.h:1433
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define ZEND_HASH_FOREACH_STR_KEY(ht, _key)
Definition zend_hash.h:1138
else
Definition zend_ini.c:906
#define ZEND_INI_SYSTEM
Definition zend_ini.h:26
#define ZEND_INI_PERDIR
Definition zend_ini.h:25
#define ZEND_INI_ALL
Definition zend_ini.h:28
#define ZEND_INI_USER
Definition zend_ini.h:24
ZEND_API zend_class_entry * zend_ce_traversable
ZEND_API zend_class_entry * zend_ce_stringable
ZEND_API bool zend_class_can_be_lazy(zend_class_entry *ce)
ZEND_API zend_object * zend_lazy_object_mark_as_initialized(zend_object *obj)
zend_object * zend_lazy_object_get_instance(zend_object *obj)
ZEND_API zend_object * zend_lazy_object_init(zend_object *obj)
ZEND_API zend_object * zend_object_make_lazy(zend_object *obj, zend_class_entry *reflection_ce, zval *initializer_zv, zend_fcall_info_cache *initializer_fcc, zend_lazy_object_flags_t flags)
void zend_lazy_object_realize(zend_object *obj)
bool zend_lazy_object_decr_lazy_props(zend_object *obj)
zval * zend_lazy_object_get_initializer_zv(zend_object *obj)
#define ZEND_LAZY_OBJECT_STRATEGY_GHOST
#define ZEND_LAZY_OBJECT_USER_MASK
#define ZEND_LAZY_OBJECT_SKIP_DESTRUCTOR
#define ZEND_LAZY_OBJECT_STRATEGY_PROXY
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
#define ZEND_MAP_PTR_GET(ptr)
#define ZEND_MAP_PTR_SET(ptr, val)
#define STANDARD_MODULE_HEADER
#define ZEND_MODULE_GLOBALS(module_name)
#define MODULE_DEP_OPTIONAL
#define MODULE_TEMPORARY
struct _zend_module_dep zend_module_dep
#define MODULE_DEP_REQUIRED
struct _zend_module_entry zend_module_entry
#define MODULE_DEP_CONFLICTS
#define STANDARD_MODULE_PROPERTIES_EX
#define NO_VERSION_YET
#define MODULE_PERSISTENT
ZEND_API zval * zend_std_get_static_property_with_info(zend_class_entry *ce, zend_string *property_name, int type, zend_property_info **property_info_ptr)
ZEND_API HashTable * zend_get_properties_no_lazy_init(zend_object *zobj)
ZEND_API void zend_class_init_statics(zend_class_entry *class_type)
ZEND_API HashTable * zend_std_get_properties(zend_object *zobj)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API zval * zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot)
ZEND_API zend_function * zend_get_property_hook_trampoline(const zend_property_info *prop_info, zend_property_hook_kind kind, zend_string *prop_name)
ZEND_API zval * zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, int type)
#define ZEND_PROPERTY_EXISTS
#define IS_VALID_PROPERTY_OFFSET(offset)
#define zend_free_trampoline(func)
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length)
#define ALLOCA_FLAG(name)
#define do_alloca(p, use_heap)
#define zend_always_inline
#define XtOffsetOf(s_type, field)
#define ZEND_ASSERT(c)
#define ZEND_UNREACHABLE()
#define ZEND_STRL(str)
#define free_alloca(p, use_heap)
#define EMPTY_SWITCH_DEFAULT_CASE()
#define UNEXPECTED(condition)
zend_property_hook_kind
@ ZEND_PROPERTY_HOOK_SET
@ ZEND_PROPERTY_HOOK_GET
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
ZEND_API void ZEND_FASTCALL smart_str_append_escaped(smart_str *str, const char *s, size_t l)
ZEND_API zend_result ZEND_FASTCALL smart_str_append_zval(smart_str *dest, const zval *value, size_t truncate)
ZEND_API void smart_str_append_printf(smart_str *dest, const char *format,...)
ZEND_API zend_string * zend_string_concat2(const char *str1, size_t str1_len, const char *str2, size_t str2_len)
ZEND_API zend_string * zend_string_concat3(const char *str1, size_t str1_len, const char *str2, size_t str2_len, const char *str3, size_t str3_len)
#define ZSTR_ALLOCA_FREE(str, use_heap)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_KNOWN(idx)
#define zend_string_equals_literal(str, literal)
#define zend_string_equals_ci(s1, s2)
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define zend_string_equals_literal_ci(str, c)
#define ZSTR_ALLOCA_ALLOC(str, _len, use_heap)
#define MAY_BE_STRING
#define MAY_BE_FALSE
#define MAY_BE_BOOL
#define MAY_BE_NULL
#define MAY_BE_STATIC
#define MAY_BE_DOUBLE
#define MAY_BE_VOID
#define MAY_BE_NEVER
#define MAY_BE_LONG
#define MAY_BE_TRUE
#define MAY_BE_ANY
#define MAY_BE_OBJECT
#define MAY_BE_CALLABLE
#define MAY_BE_ARRAY
#define ZEND_TYPE_IS_ITERABLE_FALLBACK(t)
Definition zend_types.h:183
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZEND_TYPE_PURE_MASK(t)
Definition zend_types.h:257
#define Z_ISREF_P(zval_p)
Definition zend_types.h:954
#define Z_CONSTANT_FLAGS_P(zval_p)
Definition zend_types.h:693
#define Z_TRY_ADDREF_P(pz)
#define ZEND_TYPE_NAME(t)
Definition zend_types.h:198
#define ZVAL_UNDEF(z)
#define ZEND_TYPE_INIT_MASK(_type_mask)
Definition zend_types.h:283
#define Z_REFVAL_P(zval_p)
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define IS_UNDEF
Definition zend_types.h:600
#define Z_ISUNDEF_P(zval_p)
Definition zend_types.h:957
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_NULL(z)
#define ZVAL_DEREF(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
#define ZEND_TYPE_IS_INTERSECTION(t)
Definition zend_types.h:186
#define ZVAL_STR_COPY(z, s)
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define IS_ARRAY
Definition zend_types.h:607
#define ZVAL_COPY_OR_DUP(z, v)
#define Z_OBJ_HT_P(zval_p)
Definition zend_types.h:993
#define ZEND_TYPE_HAS_NAME(t)
Definition zend_types.h:174
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
#define ZEND_TYPE_IS_UNION(t)
Definition zend_types.h:189
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define ZEND_TYPE_FULL_MASK(t)
Definition zend_types.h:254
#define Z_ADDREF_P(pz)
#define ZEND_TYPE_HAS_LIST(t)
Definition zend_types.h:180
#define ZEND_TYPE_LIST_FOREACH_END()
Definition zend_types.h:217
#define IS_NULL
Definition zend_types.h:601
#define Z_OBJCE_P(zval_p)
#define ZVAL_OBJ(z, o)
@ FAILURE
Definition zend_types.h:61
#define Z_TRY_ADDREF(z)
#define IS_OBJECT
Definition zend_types.h:608
#define ZEND_TYPE_INIT_CODE(code, allow_null, extra_flags)
Definition zend_types.h:286
#define ZEND_TYPE_IS_ONLY_MASK(t)
Definition zend_types.h:195
#define ZEND_TYPE_IS_SET(t)
Definition zend_types.h:166
#define IS_REFERENCE
Definition zend_types.h:610
#define ZVAL_COPY(z, v)
struct _Bucket Bucket
#define Z_REF_P(zval_p)
#define ZVAL_OBJ_COPY(z, o)
#define Z_REFCOUNT_P(pz)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define Z_ASTVAL(zval)
#define IS_CONSTANT_AST
Definition zend_types.h:611
#define ZVAL_COPY_PROP(z, v)
#define Z_ISREF(zval)
Definition zend_types.h:953
#define ZEND_TYPE_PURE_MASK_WITHOUT_NULL(t)
Definition zend_types.h:263
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags)
Definition zend_types.h:303
#define ZEND_TYPE_ALLOW_NULL(t)
Definition zend_types.h:269
#define Z_REF(zval)
#define IS_PROP_LAZY
#define ZEND_TYPE_LIST_FOREACH(list, type_ptr)
Definition zend_types.h:211
#define Z_PROP_FLAG_P(z)
#define Z_TYPE(zval)
Definition zend_types.h:659
#define IS_INDIRECT
Definition zend_types.h:623
#define IS_NEVER
Definition zend_types.h:620
#define ZEND_TYPE_LIST(t)
Definition zend_types.h:204
struct _zend_ast zend_ast
Definition zend_types.h:102
#define Z_OBJ_HT(zval)
Definition zend_types.h:992
struct _zend_execute_data zend_execute_data
Definition zend_types.h:91
#define Z_ASTVAL_P(zval_p)
#define ZVAL_COPY_VALUE(z, v)
#define Z_OBJ_HANDLER(zval, hf)
Definition zend_types.h:995
struct _zend_reference zend_reference
Definition zend_types.h:100
#define ZVAL_DEINDIRECT(z)
#define _ZEND_TYPE_ITERABLE_BIT
Definition zend_types.h:154
#define ZEND_TYPE_IS_COMPLEX(t)
Definition zend_types.h:171
#define Z_OBJ(zval)
Definition zend_types.h:989
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
ZEND_API void zval_add_ref(zval *p)
zval retval
zval * return_value
call prev_execute_data
zend_property_info * prop_info
uint32_t arg_num
zend_generator * generator
zend_string * name
bool result
function(EX_VAR(opline->result.var))
zval * variable_ptr
execute_data
object
zval * ret
value
var_ptr
property
new_op_array scope
#define ZEND_RECV_INIT
#define ZEND_RECV
#define ZEND_RECV_VARIADIC
#define ZEND_BIND_STATIC